Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
63d0b8b1
Commit
63d0b8b1
authored
Feb 10, 2002
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add writev support to TUN driver.
From Eddie C. Dost
parent
4bf64838
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
55 additions
and
8 deletions
+55
-8
drivers/net/tun.c
drivers/net/tun.c
+55
-8
No files found.
drivers/net/tun.c
View file @
63d0b8b1
...
@@ -181,12 +181,16 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
...
@@ -181,12 +181,16 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
}
}
/* Get packet from user space buffer(already verified) */
/* Get packet from user space buffer(already verified) */
static
__inline__
ssize_t
tun_get_user
(
struct
tun_struct
*
tun
,
const
char
*
buf
,
size_t
count
)
static
__inline__
ssize_t
tun_get_user
(
struct
tun_struct
*
tun
,
const
struct
iovec
*
iov
,
unsigned
long
count
,
size_t
total
)
{
{
struct
tun_pi
pi
=
{
0
,
__constant_htons
(
ETH_P_IP
)
};
struct
tun_pi
pi
=
{
0
,
__constant_htons
(
ETH_P_IP
)
};
register
const
char
*
ptr
=
buf
;
const
struct
iovec
*
vector
=
&
iov
[
0
];
register
int
len
=
count
;
register
const
char
*
ptr
=
vector
->
iov_base
;
register
int
len
=
vector
->
iov_len
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
ssize_t
sent
=
0
;
if
(
!
(
tun
->
flags
&
TUN_NO_PI
))
{
if
(
!
(
tun
->
flags
&
TUN_NO_PI
))
{
if
((
len
-=
sizeof
(
pi
))
<
0
)
if
((
len
-=
sizeof
(
pi
))
<
0
)
...
@@ -194,15 +198,33 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, const char *buf,
...
@@ -194,15 +198,33 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, const char *buf,
copy_from_user
(
&
pi
,
ptr
,
sizeof
(
pi
));
copy_from_user
(
&
pi
,
ptr
,
sizeof
(
pi
));
ptr
+=
sizeof
(
pi
);
ptr
+=
sizeof
(
pi
);
if
(
len
==
0
)
{
vector
++
;
count
--
;
ptr
=
vector
->
iov_base
;
len
=
vector
->
iov_len
;
}
}
}
if
(
!
(
skb
=
alloc_skb
(
len
+
2
,
GFP_KERNEL
)))
{
if
(
!
(
skb
=
alloc_skb
(
total
+
2
,
GFP_KERNEL
)))
{
tun
->
stats
.
rx_dropped
++
;
tun
->
stats
.
rx_dropped
++
;
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
skb_reserve
(
skb
,
2
);
skb_reserve
(
skb
,
2
);
while
(
count
>
0
)
{
copy_from_user
(
skb_put
(
skb
,
len
),
ptr
,
len
);
copy_from_user
(
skb_put
(
skb
,
len
),
ptr
,
len
);
sent
+=
len
;
vector
++
;
count
--
;
ptr
=
vector
->
iov_base
;
len
=
vector
->
iov_len
;
}
skb
->
dev
=
&
tun
->
dev
;
skb
->
dev
=
&
tun
->
dev
;
switch
(
tun
->
flags
&
TUN_TYPE_MASK
)
{
switch
(
tun
->
flags
&
TUN_TYPE_MASK
)
{
...
@@ -221,9 +243,9 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, const char *buf,
...
@@ -221,9 +243,9 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, const char *buf,
netif_rx_ni
(
skb
);
netif_rx_ni
(
skb
);
tun
->
stats
.
rx_packets
++
;
tun
->
stats
.
rx_packets
++
;
tun
->
stats
.
rx_bytes
+=
len
;
tun
->
stats
.
rx_bytes
+=
sent
;
return
count
;
return
total
;
}
}
/* Write */
/* Write */
...
@@ -231,6 +253,7 @@ static ssize_t tun_chr_write(struct file * file, const char * buf,
...
@@ -231,6 +253,7 @@ static ssize_t tun_chr_write(struct file * file, const char * buf,
size_t
count
,
loff_t
*
pos
)
size_t
count
,
loff_t
*
pos
)
{
{
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
file
->
private_data
;
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
file
->
private_data
;
struct
iovec
iov
;
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
...
@@ -240,7 +263,30 @@ static ssize_t tun_chr_write(struct file * file, const char * buf,
...
@@ -240,7 +263,30 @@ static ssize_t tun_chr_write(struct file * file, const char * buf,
if
(
verify_area
(
VERIFY_READ
,
buf
,
count
))
if
(
verify_area
(
VERIFY_READ
,
buf
,
count
))
return
-
EFAULT
;
return
-
EFAULT
;
return
tun_get_user
(
tun
,
buf
,
count
);
iov
.
iov_base
=
(
char
*
)
buf
;
iov
.
iov_len
=
count
;
return
tun_get_user
(
tun
,
&
iov
,
1
,
count
);
}
/* Writev */
static
ssize_t
tun_chr_writev
(
struct
file
*
file
,
const
struct
iovec
*
iov
,
unsigned
long
count
,
loff_t
*
pos
)
{
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
file
->
private_data
;
size_t
total
=
0
;
unsigned
long
i
;
if
(
!
tun
)
return
-
EBADFD
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
verify_area
(
VERIFY_READ
,
iov
[
i
].
iov_base
,
iov
[
i
].
iov_len
))
return
-
EFAULT
;
total
+=
iov
[
i
].
iov_len
;
}
return
tun_get_user
(
tun
,
iov
,
count
,
total
);
}
}
/* Put packet to user space buffer(already verified) */
/* Put packet to user space buffer(already verified) */
...
@@ -547,6 +593,7 @@ static struct file_operations tun_fops = {
...
@@ -547,6 +593,7 @@ static struct file_operations tun_fops = {
llseek:
no_llseek
,
llseek:
no_llseek
,
read:
tun_chr_read
,
read:
tun_chr_read
,
write:
tun_chr_write
,
write:
tun_chr_write
,
writev:
tun_chr_writev
,
poll:
tun_chr_poll
,
poll:
tun_chr_poll
,
ioctl:
tun_chr_ioctl
,
ioctl:
tun_chr_ioctl
,
open:
tun_chr_open
,
open:
tun_chr_open
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment