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
3a6045ff
Commit
3a6045ff
authored
Aug 08, 2003
by
Stephen Hemminger
Committed by
David S. Miller
Aug 08, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[NET]: Fix tun driver to use private linked lists.
parent
c891ba69
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
49 additions
and
32 deletions
+49
-32
drivers/net/tun.c
drivers/net/tun.c
+48
-31
include/linux/if_tun.h
include/linux/if_tun.h
+1
-1
No files found.
drivers/net/tun.c
View file @
3a6045ff
...
@@ -51,6 +51,8 @@ static int debug;
...
@@ -51,6 +51,8 @@ static int debug;
/* Network device part of the driver */
/* Network device part of the driver */
static
LIST_HEAD
(
tun_dev_list
);
/* Net device open. */
/* Net device open. */
static
int
tun_net_open
(
struct
net_device
*
dev
)
static
int
tun_net_open
(
struct
net_device
*
dev
)
{
{
...
@@ -70,7 +72,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -70,7 +72,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
{
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
dev
->
priv
;
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
dev
->
priv
;
DBG
(
KERN_INFO
"%s: tun_net_xmit %d
\n
"
,
tun
->
name
,
skb
->
len
);
DBG
(
KERN_INFO
"%s: tun_net_xmit %d
\n
"
,
tun
->
dev
->
name
,
skb
->
len
);
/* Drop packet if interface is not attached */
/* Drop packet if interface is not attached */
if
(
!
tun
->
attached
)
if
(
!
tun
->
attached
)
...
@@ -120,7 +122,7 @@ int tun_net_init(struct net_device *dev)
...
@@ -120,7 +122,7 @@ int tun_net_init(struct net_device *dev)
{
{
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
dev
->
priv
;
struct
tun_struct
*
tun
=
(
struct
tun_struct
*
)
dev
->
priv
;
DBG
(
KERN_INFO
"%s: tun_net_init
\n
"
,
tun
->
name
);
DBG
(
KERN_INFO
"%s: tun_net_init
\n
"
,
tun
->
dev
->
name
);
switch
(
tun
->
flags
&
TUN_TYPE_MASK
)
{
switch
(
tun
->
flags
&
TUN_TYPE_MASK
)
{
case
TUN_TUN_DEV
:
case
TUN_TUN_DEV
:
...
@@ -161,7 +163,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
...
@@ -161,7 +163,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
DBG
(
KERN_INFO
"%s: tun_chr_poll
\n
"
,
tun
->
name
);
DBG
(
KERN_INFO
"%s: tun_chr_poll
\n
"
,
tun
->
dev
->
name
);
poll_wait
(
file
,
&
tun
->
read_wait
,
wait
);
poll_wait
(
file
,
&
tun
->
read_wait
,
wait
);
...
@@ -226,7 +228,7 @@ static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
...
@@ -226,7 +228,7 @@ static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
DBG
(
KERN_INFO
"%s: tun_chr_write %
d
\n
"
,
tun
->
name
,
count
);
DBG
(
KERN_INFO
"%s: tun_chr_write %
ld
\n
"
,
tun
->
dev
->
name
,
count
);
for
(
i
=
0
,
len
=
0
;
i
<
count
;
i
++
)
{
for
(
i
=
0
,
len
=
0
;
i
<
count
;
i
++
)
{
if
(
verify_area
(
VERIFY_READ
,
iv
[
i
].
iov_base
,
iv
[
i
].
iov_len
))
if
(
verify_area
(
VERIFY_READ
,
iv
[
i
].
iov_base
,
iv
[
i
].
iov_len
))
...
@@ -290,7 +292,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
...
@@ -290,7 +292,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
DBG
(
KERN_INFO
"%s: tun_chr_read
\n
"
,
tun
->
name
);
DBG
(
KERN_INFO
"%s: tun_chr_read
\n
"
,
tun
->
dev
->
name
);
for
(
i
=
0
,
len
=
0
;
i
<
count
;
i
++
)
{
for
(
i
=
0
,
len
=
0
;
i
<
count
;
i
++
)
{
if
(
verify_area
(
VERIFY_WRITE
,
iv
[
i
].
iov_base
,
iv
[
i
].
iov_len
))
if
(
verify_area
(
VERIFY_WRITE
,
iv
[
i
].
iov_base
,
iv
[
i
].
iov_len
))
...
@@ -350,7 +352,7 @@ static void tun_setup(struct net_device *dev)
...
@@ -350,7 +352,7 @@ static void tun_setup(struct net_device *dev)
tun
->
owner
=
-
1
;
tun
->
owner
=
-
1
;
dev
->
init
=
tun_net_init
;
dev
->
init
=
tun_net_init
;
tun
->
name
=
dev
->
name
;
SET_MODULE_OWNER
(
dev
);
SET_MODULE_OWNER
(
dev
);
dev
->
open
=
tun_net_open
;
dev
->
open
=
tun_net_open
;
dev
->
hard_start_xmit
=
tun_net_xmit
;
dev
->
hard_start_xmit
=
tun_net_xmit
;
...
@@ -359,27 +361,40 @@ static void tun_setup(struct net_device *dev)
...
@@ -359,27 +361,40 @@ static void tun_setup(struct net_device *dev)
dev
->
destructor
=
(
void
(
*
)(
struct
net_device
*
))
kfree
;
dev
->
destructor
=
(
void
(
*
)(
struct
net_device
*
))
kfree
;
}
}
static
struct
tun_struct
*
tun_get_by_name
(
const
char
*
name
)
{
struct
tun_struct
*
tun
;
ASSERT_RTNL
();
list_for_each_entry
(
tun
,
&
tun_dev_list
,
list
)
{
if
(
!
strncmp
(
tun
->
dev
->
name
,
name
,
IFNAMSIZ
))
return
tun
;
}
return
NULL
;
}
static
int
tun_set_iff
(
struct
file
*
file
,
struct
ifreq
*
ifr
)
static
int
tun_set_iff
(
struct
file
*
file
,
struct
ifreq
*
ifr
)
{
{
struct
tun_struct
*
tun
;
struct
tun_struct
*
tun
;
struct
net_device
*
dev
;
int
err
;
int
err
;
dev
=
__dev_get_by_name
(
ifr
->
ifr_name
);
tun
=
tun_get_by_name
(
ifr
->
ifr_name
);
if
(
dev
)
{
if
(
tun
)
{
/* Device exist */
if
(
tun
->
attached
)
tun
=
dev
->
priv
;
if
(
dev
->
init
!=
tun_net_init
||
tun
->
attached
)
return
-
EBUSY
;
return
-
EBUSY
;
/* Check permissions */
/* Check permissions */
if
(
tun
->
owner
!=
-
1
)
if
(
tun
->
owner
!=
-
1
&&
if
(
current
->
euid
!=
tun
->
owner
&&
!
capable
(
CAP_NET_ADMIN
))
current
->
euid
!=
tun
->
owner
&&
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
-
EPERM
;
}
else
{
}
else
if
(
__dev_get_by_name
(
ifr
->
ifr_name
))
return
-
EINVAL
;
else
{
char
*
name
;
char
*
name
;
unsigned
long
flags
=
0
;
unsigned
long
flags
=
0
;
struct
net_device
*
dev
;
err
=
-
EINVAL
;
err
=
-
EINVAL
;
...
@@ -420,9 +435,10 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
...
@@ -420,9 +435,10 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
goto
failed
;
goto
failed
;
}
}
list_add
(
&
tun
->
list
,
&
tun_dev_list
);
}
}
DBG
(
KERN_INFO
"%s: tun_set_iff
\n
"
,
tun
->
name
);
DBG
(
KERN_INFO
"%s: tun_set_iff
\n
"
,
tun
->
dev
->
name
);
if
(
ifr
->
ifr_flags
&
IFF_NO_PI
)
if
(
ifr
->
ifr_flags
&
IFF_NO_PI
)
tun
->
flags
|=
TUN_NO_PI
;
tun
->
flags
|=
TUN_NO_PI
;
...
@@ -433,7 +449,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
...
@@ -433,7 +449,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
file
->
private_data
=
tun
;
file
->
private_data
=
tun
;
tun
->
attached
=
1
;
tun
->
attached
=
1
;
strcpy
(
ifr
->
ifr_name
,
tun
->
name
);
strcpy
(
ifr
->
ifr_name
,
tun
->
dev
->
name
);
return
0
;
return
0
;
failed:
failed:
return
err
;
return
err
;
...
@@ -466,7 +482,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
...
@@ -466,7 +482,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
DBG
(
KERN_INFO
"%s: tun_chr_ioctl cmd %d
\n
"
,
tun
->
name
,
cmd
);
DBG
(
KERN_INFO
"%s: tun_chr_ioctl cmd %d
\n
"
,
tun
->
dev
->
name
,
cmd
);
switch
(
cmd
)
{
switch
(
cmd
)
{
case
TUNSETNOCSUM
:
case
TUNSETNOCSUM
:
...
@@ -477,7 +493,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
...
@@ -477,7 +493,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
tun
->
flags
&=
~
TUN_NOCHECKSUM
;
tun
->
flags
&=
~
TUN_NOCHECKSUM
;
DBG
(
KERN_INFO
"%s: checksum %s
\n
"
,
DBG
(
KERN_INFO
"%s: checksum %s
\n
"
,
tun
->
name
,
arg
?
"disabled"
:
"enabled"
);
tun
->
dev
->
name
,
arg
?
"disabled"
:
"enabled"
);
break
;
break
;
case
TUNSETPERSIST
:
case
TUNSETPERSIST
:
...
@@ -488,14 +504,14 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
...
@@ -488,14 +504,14 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
tun
->
flags
&=
~
TUN_PERSIST
;
tun
->
flags
&=
~
TUN_PERSIST
;
DBG
(
KERN_INFO
"%s: persist %s
\n
"
,
DBG
(
KERN_INFO
"%s: persist %s
\n
"
,
tun
->
name
,
arg
?
"disabled"
:
"enabled"
);
tun
->
dev
->
name
,
arg
?
"disabled"
:
"enabled"
);
break
;
break
;
case
TUNSETOWNER
:
case
TUNSETOWNER
:
/* Set owner of the device */
/* Set owner of the device */
tun
->
owner
=
(
uid_t
)
arg
;
tun
->
owner
=
(
uid_t
)
arg
;
DBG
(
KERN_INFO
"%s: owner set to %d
\n
"
,
tun
->
owner
);
DBG
(
KERN_INFO
"%s: owner set to %d
\n
"
,
tun
->
dev
->
name
,
tun
->
owner
);
break
;
break
;
#ifdef TUN_DEBUG
#ifdef TUN_DEBUG
...
@@ -519,7 +535,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
...
@@ -519,7 +535,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
if
(
!
tun
)
if
(
!
tun
)
return
-
EBADFD
;
return
-
EBADFD
;
DBG
(
KERN_INFO
"%s: tun_chr_fasync %d
\n
"
,
tun
->
name
,
on
);
DBG
(
KERN_INFO
"%s: tun_chr_fasync %d
\n
"
,
tun
->
dev
->
name
,
on
);
if
((
ret
=
fasync_helper
(
fd
,
file
,
on
,
&
tun
->
fasync
))
<
0
)
if
((
ret
=
fasync_helper
(
fd
,
file
,
on
,
&
tun
->
fasync
))
<
0
)
return
ret
;
return
ret
;
...
@@ -549,7 +565,7 @@ static int tun_chr_close(struct inode *inode, struct file *file)
...
@@ -549,7 +565,7 @@ static int tun_chr_close(struct inode *inode, struct file *file)
if
(
!
tun
)
if
(
!
tun
)
return
0
;
return
0
;
DBG
(
KERN_INFO
"%s: tun_chr_close
\n
"
,
tun
->
name
);
DBG
(
KERN_INFO
"%s: tun_chr_close
\n
"
,
tun
->
dev
->
name
);
tun_chr_fasync
(
-
1
,
file
,
0
);
tun_chr_fasync
(
-
1
,
file
,
0
);
...
@@ -562,8 +578,10 @@ static int tun_chr_close(struct inode *inode, struct file *file)
...
@@ -562,8 +578,10 @@ static int tun_chr_close(struct inode *inode, struct file *file)
/* Drop read queue */
/* Drop read queue */
skb_queue_purge
(
&
tun
->
readq
);
skb_queue_purge
(
&
tun
->
readq
);
if
(
!
(
tun
->
flags
&
TUN_PERSIST
))
if
(
!
(
tun
->
flags
&
TUN_PERSIST
))
{
list_del
(
&
tun
->
list
);
unregister_netdevice
(
tun
->
dev
);
unregister_netdevice
(
tun
->
dev
);
}
rtnl_unlock
();
rtnl_unlock
();
...
@@ -605,15 +623,14 @@ int __init tun_init(void)
...
@@ -605,15 +623,14 @@ int __init tun_init(void)
void
tun_cleanup
(
void
)
void
tun_cleanup
(
void
)
{
{
struct
net_device
*
dev
,
*
nxt
;
struct
tun_struct
*
tun
,
*
nxt
;
misc_deregister
(
&
tun_miscdev
);
misc_deregister
(
&
tun_miscdev
);
rtnl_lock
();
rtnl_lock
();
for
(
dev
=
dev_base
;
dev
;
dev
=
nxt
)
{
list_for_each_entry_safe
(
tun
,
nxt
,
&
tun_dev_list
,
list
)
{
nxt
=
dev
->
next
;
DBG
(
KERN_INFO
"%s cleaned up
\n
"
,
tun
->
dev
->
name
);
if
(
dev
->
init
==
tun_net_init
)
unregister_netdevice
(
tun
->
dev
);
unregister_netdevice
(
dev
);
}
}
rtnl_unlock
();
rtnl_unlock
();
...
...
include/linux/if_tun.h
View file @
3a6045ff
...
@@ -32,7 +32,7 @@
...
@@ -32,7 +32,7 @@
#endif
#endif
struct
tun_struct
{
struct
tun_struct
{
char
*
name
;
struct
list_head
list
;
unsigned
long
flags
;
unsigned
long
flags
;
int
attached
;
int
attached
;
uid_t
owner
;
uid_t
owner
;
...
...
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