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
Kirill Smelkov
linux
Commits
70ced8bf
Commit
70ced8bf
authored
Apr 22, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
b3d4c027
6febb776
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
385 additions
and
135 deletions
+385
-135
include/linux/igmp.h
include/linux/igmp.h
+5
-3
include/linux/net.h
include/linux/net.h
+3
-0
include/net/ip6_route.h
include/net/ip6_route.h
+1
-1
net/core/dev.c
net/core/dev.c
+10
-0
net/core/sock.c
net/core/sock.c
+9
-4
net/ipv4/igmp.c
net/ipv4/igmp.c
+129
-59
net/ipv4/ip_output.c
net/ipv4/ip_output.c
+1
-1
net/ipv4/ip_sockglue.c
net/ipv4/ip_sockglue.c
+161
-4
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Kconfig
+1
-1
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_sockglue.c
+10
-2
net/ipv6/mcast.c
net/ipv6/mcast.c
+3
-33
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+3
-3
net/ipv6/route.c
net/ipv6/route.c
+10
-8
net/netlink/af_netlink.c
net/netlink/af_netlink.c
+7
-1
net/socket.c
net/socket.c
+32
-15
No files found.
include/linux/igmp.h
View file @
70ced8bf
...
...
@@ -191,7 +191,7 @@ struct ip_mc_list
(IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp))))
#define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
#define IGMPV3_MRC(value) IGMPV3_EXP(0x80
00, 12
, 3, value)
#define IGMPV3_MRC(value) IGMPV3_EXP(0x80
, 4
, 3, value)
extern
int
ip_check_mc
(
struct
in_device
*
dev
,
u32
mc_addr
,
u32
src_addr
,
u16
proto
);
extern
int
igmp_rcv
(
struct
sk_buff
*
);
...
...
@@ -199,10 +199,12 @@ extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
extern
int
ip_mc_leave_group
(
struct
sock
*
sk
,
struct
ip_mreqn
*
imr
);
extern
void
ip_mc_drop_socket
(
struct
sock
*
sk
);
extern
int
ip_mc_source
(
int
add
,
int
omode
,
struct
sock
*
sk
,
struct
ip_mreq_source
*
mreqs
);
extern
int
ip_mc_msfilter
(
struct
sock
*
sk
,
struct
ip_msfilter
*
msf
);
struct
ip_mreq_source
*
mreqs
,
int
ifindex
);
extern
int
ip_mc_msfilter
(
struct
sock
*
sk
,
struct
ip_msfilter
*
msf
,
int
ifindex
);
extern
int
ip_mc_msfget
(
struct
sock
*
sk
,
struct
ip_msfilter
*
msf
,
struct
ip_msfilter
*
optval
,
int
*
optlen
);
extern
int
ip_mc_gsfget
(
struct
sock
*
sk
,
struct
group_filter
*
gsf
,
struct
group_filter
*
optval
,
int
*
optlen
);
extern
int
ip_mc_sf_allow
(
struct
sock
*
sk
,
u32
local
,
u32
rmt
,
int
dif
);
extern
void
ip_mr_init
(
void
);
extern
void
ip_mc_init_dev
(
struct
in_device
*
);
...
...
include/linux/net.h
View file @
70ced8bf
...
...
@@ -140,6 +140,9 @@ struct net_proto_family {
struct
module
*
owner
;
};
extern
int
net_family_get
(
int
family
);
extern
void
net_family_put
(
int
family
);
struct
iovec
;
extern
int
sock_wake_async
(
struct
socket
*
sk
,
int
how
,
int
band
);
...
...
include/net/ip6_route.h
View file @
70ced8bf
...
...
@@ -59,7 +59,7 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
struct
in6_addr
*
saddr
,
int
oif
,
int
flags
);
extern
struct
rt6_info
*
ndisc_get_dummy_rt
(
void
);
extern
struct
rt6_info
*
ip6_dst_alloc
(
void
);
/*
* support functions for ND
...
...
net/core/dev.c
View file @
70ced8bf
...
...
@@ -2582,6 +2582,16 @@ int register_netdevice(struct net_device *dev)
if
((
ret
=
kobject_register
(
&
dev
->
kobj
)))
goto
out_err
;
/* Fix illegal SG+CSUM combinations. */
if
((
dev
->
features
&
NETIF_F_SG
)
&&
!
(
dev
->
features
&
(
NETIF_F_IP_CSUM
|
NETIF_F_NO_CSUM
|
NETIF_F_HW_CSUM
)))
{
printk
(
"%s: Dropping NETIF_F_SG since no checksum feature.
\n
"
,
dev
->
name
);
dev
->
features
&=
~
NETIF_F_SG
;
}
/*
* nil rebuild_header routine,
* that should be never called and used as just bug trap.
...
...
net/core/sock.c
View file @
70ced8bf
...
...
@@ -589,8 +589,10 @@ static kmem_cache_t *sk_cachep;
*/
struct
sock
*
sk_alloc
(
int
family
,
int
priority
,
int
zero_it
,
kmem_cache_t
*
slab
)
{
struct
sock
*
sk
;
struct
sock
*
sk
=
NULL
;
if
(
!
net_family_get
(
family
))
goto
out
;
if
(
!
slab
)
slab
=
sk_cachep
;
sk
=
kmem_cache_alloc
(
slab
,
priority
);
...
...
@@ -602,14 +604,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
sock_lock_init
(
sk
);
}
sk
->
slab
=
slab
;
}
}
else
net_family_put
(
family
);
out:
return
sk
;
}
void
sk_free
(
struct
sock
*
sk
)
{
struct
sk_filter
*
filter
;
const
int
family
=
sk
->
family
;
if
(
sk
->
destruct
)
sk
->
destruct
(
sk
);
...
...
@@ -624,6 +628,7 @@ void sk_free(struct sock *sk)
printk
(
KERN_DEBUG
"sk_free: optmem leakage (%d bytes) detected.
\n
"
,
atomic_read
(
&
sk
->
omem_alloc
));
kmem_cache_free
(
sk
->
slab
,
sk
);
net_family_put
(
family
);
}
void
__init
sk_init
(
void
)
...
...
net/ipv4/igmp.c
View file @
70ced8bf
...
...
@@ -103,6 +103,7 @@
#define IP_MAX_MEMBERSHIPS 20
#ifdef CONFIG_IP_MULTICAST
/* Parameter names and values are taken from igmp-v2-06 draft */
#define IGMP_V1_Router_Present_Timeout (400*HZ)
...
...
@@ -126,13 +127,12 @@
#define IGMP_V2_SEEN(in_dev) ((in_dev)->mr_v2_seen && \
time_before(jiffies, (in_dev)->mr_v2_seen))
#ifdef CONFIG_MULTICAST
static
void
igmpv3_add_delrec
(
struct
in_device
*
in_dev
,
struct
ip_mc_list
*
im
);
#endif
static
void
igmpv3_del_delrec
(
struct
in_device
*
in_dev
,
__u32
multiaddr
);
static
void
igmpv3_clear_delrec
(
struct
in_device
*
in_dev
);
static
int
sf_setstate
(
struct
ip_mc_list
*
pmc
);
static
void
sf_markstate
(
struct
ip_mc_list
*
pmc
);
#endif
static
void
ip_mc_clear_src
(
struct
ip_mc_list
*
pmc
);
int
ip_mc_add_src
(
struct
in_device
*
in_dev
,
__u32
*
pmca
,
int
sfmode
,
int
sfcount
,
__u32
*
psfsrc
,
int
delta
);
...
...
@@ -770,11 +770,18 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
in_dev
->
mr_v2_seen
=
jiffies
+
IGMP_V2_Router_Present_Timeout
;
}
/* cancel the interface change timer */
in_dev
->
mr_ifc_count
=
0
;
if
(
del_timer
(
&
in_dev
->
mr_ifc_timer
))
atomic_dec
(
&
in_dev
->
refcnt
);
/* clear deleted report items */
igmpv3_clear_delrec
(
in_dev
);
}
else
if
(
len
<
12
)
{
return
;
/* ignore bogus packet; freed by caller */
}
else
{
/* v3 */
max_delay
=
IGMPV3_MRC
(
ih3
->
code
)
*
(
HZ
/
IGMP_TIMER_SCALE
);
if
(
!
max_delay
)
max_delay
=
1
;
/* can't mod w/ 0 */
in_dev
->
mr_maxdelay
=
max_delay
;
if
(
ih3
->
qrv
)
in_dev
->
mr_qrv
=
ih3
->
qrv
;
...
...
@@ -951,7 +958,6 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
in_dev
->
mc_tomb
=
pmc
;
write_unlock_bh
(
&
in_dev
->
mc_lock
);
}
#endif
static
void
igmpv3_del_delrec
(
struct
in_device
*
in_dev
,
__u32
multiaddr
)
{
...
...
@@ -997,7 +1003,23 @@ static void igmpv3_clear_delrec(struct in_device *in_dev)
in_dev_put
(
pmc
->
interface
);
kfree
(
pmc
);
}
/* clear dead sources, too */
read_lock
(
&
in_dev
->
lock
);
for
(
pmc
=
in_dev
->
mc_list
;
pmc
;
pmc
=
pmc
->
next
)
{
struct
ip_sf_list
*
psf
,
*
psf_next
;
spin_lock_bh
(
&
pmc
->
lock
);
psf
=
pmc
->
tomb
;
pmc
->
tomb
=
0
;
spin_unlock_bh
(
&
pmc
->
lock
);
for
(;
psf
;
psf
=
psf_next
)
{
psf_next
=
psf
->
sf_next
;
kfree
(
psf
);
}
}
read_unlock
(
&
in_dev
->
lock
);
}
#endif
static
void
igmp_group_dropped
(
struct
ip_mc_list
*
im
)
{
...
...
@@ -1030,8 +1052,8 @@ static void igmp_group_dropped(struct ip_mc_list *im)
igmp_ifc_event
(
in_dev
);
done:
ip_mc_clear_src
(
im
);
#endif
ip_mc_clear_src
(
im
);
}
static
void
igmp_group_added
(
struct
ip_mc_list
*
im
)
...
...
@@ -1102,7 +1124,7 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
im
->
crcount
=
0
;
atomic_set
(
&
im
->
refcnt
,
1
);
spin_lock_init
(
&
im
->
lock
);
#ifdef
CONFIG_IP_MULTICAST
#ifdef CONFIG_IP_MULTICAST
im
->
tm_running
=
0
;
init_timer
(
&
im
->
timer
);
im
->
timer
.
data
=
(
unsigned
long
)
im
;
...
...
@@ -1116,7 +1138,9 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
im
->
next
=
in_dev
->
mc_list
;
in_dev
->
mc_list
=
im
;
write_unlock_bh
(
&
in_dev
->
lock
);
#ifdef CONFIG_IP_MULTICAST
igmpv3_del_delrec
(
in_dev
,
im
->
multiaddr
);
#endif
igmp_group_added
(
im
);
if
(
in_dev
->
dev
->
flags
&
IFF_UP
)
ip_rt_multicast_event
(
in_dev
);
...
...
@@ -1173,7 +1197,9 @@ void ip_mc_down(struct in_device *in_dev)
for
(
i
=
in_dev
->
mc_list
;
i
;
i
=
i
->
next
)
igmp_group_dropped
(
i
);
#ifdef CONFIG_IP_MULTICAST
igmpv3_clear_delrec
(
in_dev
);
#endif
ip_mc_dec_group
(
in_dev
,
IGMP_ALL_HOSTS
);
}
...
...
@@ -1186,12 +1212,12 @@ void ip_mc_up(struct in_device *in_dev)
ASSERT_RTNL
();
in_dev
->
mc_tomb
=
0
;
#ifdef CONFIG_IP_MULTICAST
in_dev
->
mr_gq_running
=
0
;
init_timer
(
&
in_dev
->
mr_gq_timer
);
in_dev
->
mr_gq_timer
.
data
=
(
unsigned
long
)
in_dev
;
in_dev
->
mr_gq_timer
.
function
=&
igmp_gq_timer_expire
;
in_dev
->
mc_tomb
=
0
;
in_dev
->
mr_ifc_count
=
0
;
init_timer
(
&
in_dev
->
mr_ifc_timer
);
in_dev
->
mr_ifc_timer
.
data
=
(
unsigned
long
)
in_dev
;
...
...
@@ -1237,6 +1263,12 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
struct
net_device
*
dev
=
NULL
;
struct
in_device
*
idev
=
NULL
;
if
(
imr
->
imr_ifindex
)
{
idev
=
inetdev_by_index
(
imr
->
imr_ifindex
);
if
(
idev
)
__in_dev_put
(
idev
);
return
idev
;
}
if
(
imr
->
imr_address
.
s_addr
)
{
dev
=
ip_dev_find
(
imr
->
imr_address
.
s_addr
);
if
(
!
dev
)
...
...
@@ -1282,13 +1314,16 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
ip_rt_multicast_event
(
pmc
->
interface
);
}
if
(
!
psf
->
sf_count
[
MCAST_INCLUDE
]
&&
!
psf
->
sf_count
[
MCAST_EXCLUDE
])
{
#ifdef CONFIG_IP_MULTICAST
struct
in_device
*
in_dev
=
pmc
->
interface
;
#endif
/* no more filters for this source */
if
(
psf_prev
)
psf_prev
->
sf_next
=
psf
->
sf_next
;
else
pmc
->
sources
=
psf
->
sf_next
;
#ifdef CONFIG_IP_MULTICAST
if
(
psf
->
sf_oldin
&&
!
IGMP_V1_SEEN
(
in_dev
)
&&
!
IGMP_V2_SEEN
(
in_dev
))
{
psf
->
sf_crcount
=
in_dev
->
mr_qrv
?
in_dev
->
mr_qrv
:
...
...
@@ -1297,6 +1332,7 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
pmc
->
tomb
=
psf
;
rv
=
1
;
}
else
#endif
kfree
(
psf
);
}
return
rv
;
...
...
@@ -1327,7 +1363,9 @@ int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
}
spin_lock_bh
(
&
pmc
->
lock
);
read_unlock
(
&
in_dev
->
lock
);
#ifdef CONFIG_IP_MULTICAST
sf_markstate
(
pmc
);
#endif
if
(
!
delta
)
{
if
(
!
pmc
->
sfcount
[
sfmode
])
return
-
EINVAL
;
...
...
@@ -1344,10 +1382,13 @@ int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
if
(
pmc
->
sfmode
==
MCAST_EXCLUDE
&&
pmc
->
sfcount
[
MCAST_EXCLUDE
]
==
0
&&
pmc
->
sfcount
[
MCAST_INCLUDE
])
{
#ifdef CONFIG_IP_MULTICAST
struct
ip_sf_list
*
psf
;
#endif
/* filter mode change */
pmc
->
sfmode
=
MCAST_INCLUDE
;
#ifdef CONFIG_IP_MULTICAST
pmc
->
crcount
=
in_dev
->
mr_qrv
?
in_dev
->
mr_qrv
:
IGMP_Unsolicited_Report_Count
;
in_dev
->
mr_ifc_count
=
pmc
->
crcount
;
...
...
@@ -1356,6 +1397,7 @@ int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
igmp_ifc_event
(
pmc
->
interface
);
}
else
if
(
sf_setstate
(
pmc
)
||
changerec
)
{
igmp_ifc_event
(
pmc
->
interface
);
#endif
}
spin_unlock_bh
(
&
pmc
->
lock
);
return
err
;
...
...
@@ -1393,6 +1435,7 @@ static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
return
0
;
}
#ifdef CONFIG_IP_MULTICAST
static
void
sf_markstate
(
struct
ip_mc_list
*
pmc
)
{
struct
ip_sf_list
*
psf
;
...
...
@@ -1428,6 +1471,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
}
return
rv
;
}
#endif
/*
* Add multicast source filter list to the interface list
...
...
@@ -1454,7 +1498,9 @@ int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
spin_lock_bh
(
&
pmc
->
lock
);
read_unlock
(
&
in_dev
->
lock
);
#ifdef CONFIG_IP_MULTICAST
sf_markstate
(
pmc
);
#endif
isexclude
=
pmc
->
sfmode
==
MCAST_EXCLUDE
;
if
(
!
delta
)
pmc
->
sfcount
[
sfmode
]
++
;
...
...
@@ -1471,14 +1517,17 @@ int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
for
(
j
=
0
;
j
<
i
;
j
++
)
(
void
)
ip_mc_del1_src
(
pmc
,
sfmode
,
&
psfsrc
[
i
]);
}
else
if
(
isexclude
!=
(
pmc
->
sfcount
[
MCAST_EXCLUDE
]
!=
0
))
{
#ifdef CONFIG_IP_MULTICAST
struct
in_device
*
in_dev
=
pmc
->
interface
;
struct
ip_sf_list
*
psf
;
#endif
/* filter mode change */
if
(
pmc
->
sfcount
[
MCAST_EXCLUDE
])
pmc
->
sfmode
=
MCAST_EXCLUDE
;
else
if
(
pmc
->
sfcount
[
MCAST_INCLUDE
])
pmc
->
sfmode
=
MCAST_INCLUDE
;
#ifdef CONFIG_IP_MULTICAST
/* else no filters; keep old mode for reports */
pmc
->
crcount
=
in_dev
->
mr_qrv
?
in_dev
->
mr_qrv
:
...
...
@@ -1487,8 +1536,10 @@ int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
for
(
psf
=
pmc
->
sources
;
psf
;
psf
=
psf
->
sf_next
)
psf
->
sf_crcount
=
0
;
igmp_ifc_event
(
in_dev
);
}
else
if
(
sf_setstate
(
pmc
))
}
else
if
(
sf_setstate
(
pmc
))
{
igmp_ifc_event
(
in_dev
);
#endif
}
spin_unlock_bh
(
&
pmc
->
lock
);
return
err
;
}
...
...
@@ -1530,13 +1581,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
rtnl_shlock
();
if
(
!
imr
->
imr_ifindex
)
in_dev
=
ip_mc_find_dev
(
imr
);
else
{
in_dev
=
inetdev_by_index
(
imr
->
imr_ifindex
);
if
(
in_dev
)
__in_dev_put
(
in_dev
);
}
in_dev
=
ip_mc_find_dev
(
imr
);
if
(
!
in_dev
)
{
iml
=
NULL
;
...
...
@@ -1638,13 +1683,13 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
}
int
ip_mc_source
(
int
add
,
int
omode
,
struct
sock
*
sk
,
struct
ip_mreq_source
*
mreqs
)
ip_mreq_source
*
mreqs
,
int
ifindex
)
{
int
err
;
struct
ip_mreqn
imr
;
struct
ip_mreqn
imr
;
u32
addr
=
mreqs
->
imr_multiaddr
;
struct
ip_mc_socklist
*
pmc
;
struct
in_device
*
in_dev
;
struct
in_device
*
in_dev
=
0
;
struct
inet_opt
*
inet
=
inet_sk
(
sk
);
struct
ip_sf_socklist
*
psl
;
int
i
,
j
,
rv
;
...
...
@@ -1656,7 +1701,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
imr
.
imr_multiaddr
.
s_addr
=
mreqs
->
imr_multiaddr
;
imr
.
imr_address
.
s_addr
=
mreqs
->
imr_interface
;
imr
.
imr_ifindex
=
0
;
imr
.
imr_ifindex
=
ifindex
;
in_dev
=
ip_mc_find_dev
(
&
imr
);
if
(
!
in_dev
)
{
...
...
@@ -1753,7 +1798,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
return
err
;
}
int
ip_mc_msfilter
(
struct
sock
*
sk
,
struct
ip_msfilter
*
msf
)
int
ip_mc_msfilter
(
struct
sock
*
sk
,
struct
ip_msfilter
*
msf
,
int
ifindex
)
{
int
err
;
struct
ip_mreqn
imr
;
...
...
@@ -1773,7 +1818,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf)
imr
.
imr_multiaddr
.
s_addr
=
msf
->
imsf_multiaddr
;
imr
.
imr_address
.
s_addr
=
msf
->
imsf_interface
;
imr
.
imr_ifindex
=
0
;
imr
.
imr_ifindex
=
ifindex
;
in_dev
=
ip_mc_find_dev
(
&
imr
);
if
(
!
in_dev
)
{
...
...
@@ -1783,7 +1828,8 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf)
err
=
-
EADDRNOTAVAIL
;
for
(
pmc
=
inet
->
mc_list
;
pmc
;
pmc
=
pmc
->
next
)
{
if
(
memcmp
(
&
pmc
->
multi
,
&
imr
,
sizeof
(
imr
))
==
0
)
if
(
pmc
->
multi
.
imr_multiaddr
.
s_addr
==
msf
->
imsf_multiaddr
&&
pmc
->
multi
.
imr_ifindex
==
imr
.
imr_ifindex
)
break
;
}
if
(
!
pmc
)
/* must have a prior join */
...
...
@@ -1834,9 +1880,6 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
if
(
!
MULTICAST
(
addr
))
return
-
EINVAL
;
if
(
msf
->
imsf_fmode
!=
MCAST_INCLUDE
&&
msf
->
imsf_fmode
!=
MCAST_EXCLUDE
)
return
-
EINVAL
;
rtnl_shlock
();
...
...
@@ -1852,7 +1895,8 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
err
=
-
EADDRNOTAVAIL
;
for
(
pmc
=
inet
->
mc_list
;
pmc
;
pmc
=
pmc
->
next
)
{
if
(
memcmp
(
&
pmc
->
multi
,
&
imr
,
sizeof
(
imr
))
==
0
)
if
(
pmc
->
multi
.
imr_multiaddr
.
s_addr
==
msf
->
imsf_multiaddr
&&
pmc
->
multi
.
imr_ifindex
==
imr
.
imr_ifindex
)
break
;
}
if
(
!
pmc
)
/* must have a prior join */
...
...
@@ -1882,6 +1926,61 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
return
err
;
}
int
ip_mc_gsfget
(
struct
sock
*
sk
,
struct
group_filter
*
gsf
,
struct
group_filter
*
optval
,
int
*
optlen
)
{
int
err
,
i
,
count
,
copycount
;
struct
sockaddr_in
*
psin
;
u32
addr
;
struct
ip_mc_socklist
*
pmc
;
struct
inet_opt
*
inet
=
inet_sk
(
sk
);
struct
ip_sf_socklist
*
psl
;
psin
=
(
struct
sockaddr_in
*
)
&
gsf
->
gf_group
;
if
(
psin
->
sin_family
!=
AF_INET
)
return
-
EINVAL
;
addr
=
psin
->
sin_addr
.
s_addr
;
if
(
!
MULTICAST
(
addr
))
return
-
EINVAL
;
rtnl_shlock
();
err
=
-
EADDRNOTAVAIL
;
for
(
pmc
=
inet
->
mc_list
;
pmc
;
pmc
=
pmc
->
next
)
{
if
(
pmc
->
multi
.
imr_multiaddr
.
s_addr
==
addr
&&
pmc
->
multi
.
imr_ifindex
==
gsf
->
gf_interface
)
break
;
}
if
(
!
pmc
)
/* must have a prior join */
goto
done
;
gsf
->
gf_fmode
=
pmc
->
sfmode
;
psl
=
pmc
->
sflist
;
rtnl_shunlock
();
count
=
psl
?
psl
->
sl_count
:
0
;
copycount
=
count
<
gsf
->
gf_numsrc
?
count
:
gsf
->
gf_numsrc
;
gsf
->
gf_numsrc
=
count
;
if
(
put_user
(
GROUP_FILTER_SIZE
(
copycount
),
optlen
)
||
copy_to_user
((
void
*
)
optval
,
gsf
,
GROUP_FILTER_SIZE
(
0
)))
{
return
-
EFAULT
;
}
for
(
i
=
0
;
i
<
copycount
;
i
++
)
{
struct
sockaddr_in
*
psin
;
struct
sockaddr_storage
ss
;
psin
=
(
struct
sockaddr_in
*
)
&
ss
;
memset
(
&
ss
,
0
,
sizeof
(
ss
));
psin
->
sin_family
=
AF_INET
;
psin
->
sin_addr
.
s_addr
=
psl
->
sl_addr
[
i
];
if
(
copy_to_user
((
void
*
)
&
optval
->
gf_slist
[
i
],
&
ss
,
sizeof
(
ss
)))
return
-
EFAULT
;
}
return
0
;
done:
rtnl_shunlock
();
return
err
;
}
/*
* check if a multicast source filter allows delivery for a given <src,dst,intf>
*/
...
...
@@ -1892,6 +1991,9 @@ int ip_mc_sf_allow(struct sock *sk, u32 loc_addr, u32 rmt_addr, int dif)
struct
ip_sf_socklist
*
psl
;
int
i
;
if
(
!
MULTICAST
(
loc_addr
))
return
1
;
for
(
pmc
=
inet
->
mc_list
;
pmc
;
pmc
=
pmc
->
next
)
{
if
(
pmc
->
multi
.
imr_multiaddr
.
s_addr
==
loc_addr
&&
pmc
->
multi
.
imr_ifindex
==
dif
)
...
...
@@ -1972,8 +2074,6 @@ int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
}
#ifdef CONFIG_IP_MULTICAST
int
ip_mc_procinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
off_t
pos
=
0
,
begin
=
0
;
...
...
@@ -1991,7 +2091,9 @@ int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length)
if
(
in_dev
==
NULL
)
continue
;
#ifdef CONFIG_IP_MULTICAST
querier
=
IGMP_V1_SEEN
(
in_dev
)
?
"V1"
:
"V2"
;
#endif
len
+=
sprintf
(
buffer
+
len
,
"%d
\t
%-10s: %5d %7s
\n
"
,
dev
->
ifindex
,
dev
->
name
,
dev
->
mc_count
,
querier
);
...
...
@@ -2049,11 +2151,8 @@ int ip_mcf_procinfo(char *buffer, char **start, off_t offset, int length)
for
(
imc
=
in_dev
->
mc_list
;
imc
;
imc
=
imc
->
next
)
{
struct
ip_sf_list
*
psf
;
unsigned
long
icount
,
xcount
;
spin_lock_bh
(
&
imc
->
lock
);
icount
=
imc
->
sfcount
[
MCAST_INCLUDE
];
xcount
=
imc
->
sfcount
[
MCAST_EXCLUDE
];
for
(
psf
=
imc
->
sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
...
...
@@ -2080,33 +2179,6 @@ int ip_mcf_procinfo(char *buffer, char **start, off_t offset, int length)
in_dev_put
(
in_dev
);
goto
done
;
}
icount
-=
psf
->
sf_count
[
MCAST_INCLUDE
];
xcount
-=
psf
->
sf_count
[
MCAST_EXCLUDE
];
}
if
(
icount
>
0
||
xcount
>
0
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
"%10s %10s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"MCA"
,
"SRC"
,
"INC"
,
"EXC"
);
first
=
0
;
}
len
+=
sprintf
(
buffer
+
len
,
"%3d %6.6s 0x%08x "
"%10s %6lu %6lu
\n
"
,
dev
->
ifindex
,
dev
->
name
,
ntohl
(
imc
->
multiaddr
),
"NONE"
,
icount
,
xcount
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
spin_unlock_bh
(
&
imc
->
lock
);
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
goto
done
;
}
}
spin_unlock_bh
(
&
imc
->
lock
);
}
...
...
@@ -2125,5 +2197,3 @@ int ip_mcf_procinfo(char *buffer, char **start, off_t offset, int length)
return
len
;
}
#endif
net/ipv4/ip_output.c
View file @
70ced8bf
...
...
@@ -1312,6 +1312,6 @@ void __init ip_init(void)
#ifdef CONFIG_IP_MULTICAST
proc_net_create
(
"igmp"
,
0
,
ip_mc_procinfo
);
proc_net_create
(
"mcfilter"
,
0
,
ip_mcf_procinfo
);
#endif
proc_net_create
(
"mcfilter"
,
0
,
ip_mcf_procinfo
);
}
net/ipv4/ip_sockglue.c
View file @
70ced8bf
...
...
@@ -631,7 +631,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
kfree
(
msf
);
break
;
}
err
=
ip_mc_msfilter
(
sk
,
msf
);
err
=
ip_mc_msfilter
(
sk
,
msf
,
0
);
kfree
(
msf
);
break
;
}
...
...
@@ -670,7 +670,142 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
omode
=
MCAST_INCLUDE
;
add
=
0
;
}
err
=
ip_mc_source
(
add
,
omode
,
sk
,
&
mreqs
);
err
=
ip_mc_source
(
add
,
omode
,
sk
,
&
mreqs
,
0
);
break
;
}
case
MCAST_JOIN_GROUP
:
case
MCAST_LEAVE_GROUP
:
{
struct
group_req
greq
;
struct
sockaddr_in
*
psin
;
struct
ip_mreqn
mreq
;
if
(
optlen
<
sizeof
(
struct
group_req
))
goto
e_inval
;
err
=
-
EFAULT
;
if
(
copy_from_user
(
&
greq
,
optval
,
sizeof
(
greq
)))
break
;
psin
=
(
struct
sockaddr_in
*
)
&
greq
.
gr_group
;
if
(
psin
->
sin_family
!=
AF_INET
)
goto
e_inval
;
memset
(
&
mreq
,
0
,
sizeof
(
mreq
));
mreq
.
imr_multiaddr
=
psin
->
sin_addr
;
mreq
.
imr_ifindex
=
greq
.
gr_interface
;
if
(
optname
==
MCAST_JOIN_GROUP
)
err
=
ip_mc_join_group
(
sk
,
&
mreq
);
else
err
=
ip_mc_leave_group
(
sk
,
&
mreq
);
break
;
}
case
MCAST_JOIN_SOURCE_GROUP
:
case
MCAST_LEAVE_SOURCE_GROUP
:
case
MCAST_BLOCK_SOURCE
:
case
MCAST_UNBLOCK_SOURCE
:
{
struct
group_source_req
greqs
;
struct
ip_mreq_source
mreqs
;
struct
sockaddr_in
*
psin
;
int
omode
,
add
;
if
(
optlen
!=
sizeof
(
struct
group_source_req
))
goto
e_inval
;
if
(
copy_from_user
(
&
greqs
,
optval
,
sizeof
(
greqs
)))
{
err
=
-
EFAULT
;
break
;
}
if
(
greqs
.
gsr_group
.
ss_family
!=
AF_INET
||
greqs
.
gsr_source
.
ss_family
!=
AF_INET
)
{
err
=
-
EADDRNOTAVAIL
;
break
;
}
psin
=
(
struct
sockaddr_in
*
)
&
greqs
.
gsr_group
;
mreqs
.
imr_multiaddr
=
psin
->
sin_addr
.
s_addr
;
psin
=
(
struct
sockaddr_in
*
)
&
greqs
.
gsr_source
;
mreqs
.
imr_sourceaddr
=
psin
->
sin_addr
.
s_addr
;
mreqs
.
imr_interface
=
0
;
/* use index for mc_source */
if
(
optname
==
MCAST_BLOCK_SOURCE
)
{
omode
=
MCAST_EXCLUDE
;
add
=
1
;
}
else
if
(
optname
==
MCAST_UNBLOCK_SOURCE
)
{
omode
=
MCAST_EXCLUDE
;
add
=
0
;
}
else
if
(
optname
==
MCAST_JOIN_SOURCE_GROUP
)
{
struct
ip_mreqn
mreq
;
psin
=
(
struct
sockaddr_in
*
)
&
greqs
.
gsr_group
;
mreq
.
imr_multiaddr
=
psin
->
sin_addr
;
mreq
.
imr_address
.
s_addr
=
0
;
mreq
.
imr_ifindex
=
greqs
.
gsr_interface
;
err
=
ip_mc_join_group
(
sk
,
&
mreq
);
if
(
err
)
break
;
omode
=
MCAST_INCLUDE
;
add
=
1
;
}
else
/* MCAST_LEAVE_SOURCE_GROUP */
{
omode
=
MCAST_INCLUDE
;
add
=
0
;
}
err
=
ip_mc_source
(
add
,
omode
,
sk
,
&
mreqs
,
greqs
.
gsr_interface
);
break
;
}
case
MCAST_MSFILTER
:
{
struct
sockaddr_in
*
psin
;
struct
ip_msfilter
*
msf
=
0
;
struct
group_filter
*
gsf
=
0
;
int
msize
,
i
,
ifindex
;
if
(
optlen
<
GROUP_FILTER_SIZE
(
0
))
goto
e_inval
;
gsf
=
(
struct
group_filter
*
)
kmalloc
(
optlen
,
GFP_KERNEL
);
if
(
gsf
==
0
)
{
err
=
-
ENOBUFS
;
break
;
}
err
=
-
EFAULT
;
if
(
copy_from_user
(
gsf
,
optval
,
optlen
))
{
goto
mc_msf_out
;
}
if
(
GROUP_FILTER_SIZE
(
gsf
->
gf_numsrc
)
<
optlen
)
{
err
=
EINVAL
;
goto
mc_msf_out
;
}
msize
=
IP_MSFILTER_SIZE
(
gsf
->
gf_numsrc
);
msf
=
(
struct
ip_msfilter
*
)
kmalloc
(
msize
,
GFP_KERNEL
);
if
(
msf
==
0
)
{
err
=
-
ENOBUFS
;
goto
mc_msf_out
;
}
ifindex
=
gsf
->
gf_interface
;
psin
=
(
struct
sockaddr_in
*
)
&
gsf
->
gf_group
;
if
(
psin
->
sin_family
!=
AF_INET
)
{
err
=
-
EADDRNOTAVAIL
;
goto
mc_msf_out
;
}
msf
->
imsf_multiaddr
=
psin
->
sin_addr
.
s_addr
;
msf
->
imsf_interface
=
0
;
msf
->
imsf_fmode
=
gsf
->
gf_fmode
;
msf
->
imsf_numsrc
=
gsf
->
gf_numsrc
;
err
=
-
EADDRNOTAVAIL
;
for
(
i
=
0
;
i
<
gsf
->
gf_numsrc
;
++
i
)
{
psin
=
(
struct
sockaddr_in
*
)
&
gsf
->
gf_slist
[
i
];
if
(
psin
->
sin_family
!=
AF_INET
)
goto
mc_msf_out
;
msf
->
imsf_slist
[
i
]
=
psin
->
sin_addr
.
s_addr
;
}
kfree
(
gsf
);
gsf
=
0
;
err
=
ip_mc_msfilter
(
sk
,
msf
,
ifindex
);
mc_msf_out:
if
(
msf
)
kfree
(
msf
);
if
(
gsf
)
kfree
(
gsf
);
break
;
}
case
IP_ROUTER_ALERT
:
...
...
@@ -826,15 +961,37 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
struct
ip_msfilter
msf
;
int
err
;
if
(
len
<
IP_MSFILTER_SIZE
(
0
))
if
(
len
<
IP_MSFILTER_SIZE
(
0
))
{
release_sock
(
sk
);
return
-
EINVAL
;
if
(
copy_from_user
(
&
msf
,
optval
,
IP_MSFILTER_SIZE
(
0
)))
}
if
(
copy_from_user
(
&
msf
,
optval
,
IP_MSFILTER_SIZE
(
0
)))
{
release_sock
(
sk
);
return
-
EFAULT
;
}
err
=
ip_mc_msfget
(
sk
,
&
msf
,
(
struct
ip_msfilter
*
)
optval
,
optlen
);
release_sock
(
sk
);
return
err
;
}
case
MCAST_MSFILTER
:
{
struct
group_filter
gsf
;
int
err
;
if
(
len
<
GROUP_FILTER_SIZE
(
0
))
{
release_sock
(
sk
);
return
-
EINVAL
;
}
if
(
copy_from_user
(
&
gsf
,
optval
,
GROUP_FILTER_SIZE
(
0
)))
{
release_sock
(
sk
);
return
-
EFAULT
;
}
err
=
ip_mc_gsfget
(
sk
,
&
gsf
,
(
struct
group_filter
*
)
optval
,
optlen
);
release_sock
(
sk
);
return
err
;
}
case
IP_PKTOPTIONS
:
{
struct
msghdr
msg
;
...
...
net/ipv4/netfilter/Kconfig
View file @
70ced8bf
...
...
@@ -48,7 +48,7 @@ config IP_NF_IRC
<file:Documentation/modules.txt>. If unsure, say `Y'.
config IP_NF_TFTP
tristate "TFTP prtocol support"
tristate "TFTP pr
o
tocol support"
depends on IP_NF_CONNTRACK
help
TFTP connection tracking helper, this is required depending
...
...
net/ipv6/ipv6_sockglue.c
View file @
70ced8bf
...
...
@@ -120,6 +120,12 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
return
0
;
}
extern
int
ip6_mc_source
(
int
add
,
int
omode
,
struct
sock
*
sk
,
struct
group_source_req
*
pgsr
);
extern
int
ip6_mc_msfilter
(
struct
sock
*
sk
,
struct
group_filter
*
gsf
);
extern
int
ip6_mc_msfget
(
struct
sock
*
sk
,
struct
group_filter
*
gsf
,
struct
group_filter
*
optval
,
int
*
optlen
);
int
ipv6_setsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
...
...
@@ -393,12 +399,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
break
;
}
psin6
=
(
struct
sockaddr_in6
*
)
&
greq
.
gr_group
;
if
(
optname
==
IPV6_ADD_MEMBERSHI
P
)
if
(
optname
==
MCAST_JOIN_GROU
P
)
retv
=
ipv6_sock_mc_join
(
sk
,
greq
.
gr_interface
,
&
psin6
->
sin6_addr
);
else
retv
=
ipv6_sock_mc_drop
(
sk
,
greq
.
gr_interface
,
&
psin6
->
sin6_addr
);
break
;
}
case
MCAST_JOIN_SOURCE_GROUP
:
case
MCAST_LEAVE_SOURCE_GROUP
:
...
...
@@ -414,7 +421,8 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
retv
=
-
EFAULT
;
break
;
}
if
(
greqs
.
gsr_group
.
ss_family
!=
AF_INET6
)
{
if
(
greqs
.
gsr_group
.
ss_family
!=
AF_INET6
||
greqs
.
gsr_source
.
ss_family
!=
AF_INET6
)
{
retv
=
-
EADDRNOTAVAIL
;
break
;
}
...
...
net/ipv6/mcast.c
View file @
70ced8bf
...
...
@@ -768,7 +768,7 @@ static void mld_clear_delrec(struct inet6_dev *idev)
psf
=
pmc
->
mca_tomb
;
pmc
->
mca_tomb
=
0
;
spin_unlock_bh
(
&
pmc
->
mca_lock
);
for
(
psf
=
pmc
->
mca_tomb
;
psf
;
psf
=
psf_next
)
{
for
(;
psf
;
psf
=
psf_next
)
{
psf_next
=
psf
->
sf_next
;
kfree
(
psf
);
}
...
...
@@ -1042,6 +1042,8 @@ int igmp6_event_query(struct sk_buff *skb)
mld_clear_delrec
(
idev
);
}
else
if
(
len
>=
28
)
{
max_delay
=
MLDV2_MRC
(
ntohs
(
mlh2
->
mrc
))
*
(
HZ
/
10
);
if
(
!
max_delay
)
max_delay
=
1
;
idev
->
mc_maxdelay
=
max_delay
;
if
(
mlh2
->
qrv
)
idev
->
mc_qrv
=
mlh2
->
qrv
;
...
...
@@ -2096,8 +2098,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset,
unsigned
long
icount
,
xcount
,
i
;
spin_lock_bh
(
&
imc
->
mca_lock
);
icount
=
imc
->
mca_sfcount
[
MCAST_INCLUDE
];
xcount
=
imc
->
mca_sfcount
[
MCAST_EXCLUDE
];
for
(
psf
=
imc
->
mca_sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
...
...
@@ -2130,36 +2130,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset,
in6_dev_put
(
idev
);
goto
done
;
}
icount
-=
psf
->
sf_count
[
MCAST_INCLUDE
];
xcount
-=
psf
->
sf_count
[
MCAST_EXCLUDE
];
}
if
(
icount
>
0
||
xcount
>
0
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
"%32s %32s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"Multicast Address"
,
"Source Address"
,
"INC"
,
"EXC"
);
first
=
0
;
}
len
+=
sprintf
(
buffer
+
len
,
"%3d %6.6s "
,
dev
->
ifindex
,
dev
->
name
);
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
imc
->
mca_addr
.
s6_addr
[
i
]);
len
+=
sprintf
(
buffer
+
len
,
" %32s %6lu %6lu
\n
"
,
"NONE"
,
icount
,
xcount
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
spin_unlock_bh
(
&
imc
->
mca_lock
);
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
goto
done
;
}
}
spin_unlock_bh
(
&
imc
->
mca_lock
);
}
...
...
net/ipv6/ndisc.c
View file @
70ced8bf
...
...
@@ -427,7 +427,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
len
=
sizeof
(
struct
icmp6hdr
)
+
sizeof
(
struct
in6_addr
);
rt
=
ndisc_get_dummy_rt
();
rt
=
ip6_dst_alloc
();
if
(
!
rt
)
return
;
...
...
@@ -524,7 +524,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
saddr
=
&
addr_buf
;
}
rt
=
ndisc_get_dummy_rt
();
rt
=
ip6_dst_alloc
();
if
(
!
rt
)
return
;
...
...
@@ -595,7 +595,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
int
len
;
int
err
;
rt
=
ndisc_get_dummy_rt
();
rt
=
ip6_dst_alloc
();
if
(
!
rt
)
return
;
...
...
net/ipv6/route.c
View file @
70ced8bf
...
...
@@ -130,12 +130,17 @@ struct fib6_node ip6_routing_table = {
rwlock_t
rt6_lock
=
RW_LOCK_UNLOCKED
;
/*
Dummy rt for ndisc
*/
st
ruct
rt6_info
*
ndisc_get_dummy_rt
(
)
/*
allocate dst with ip6_dst_ops
*/
st
atic
__inline__
struct
rt6_info
*
__ip6_dst_alloc
(
void
)
{
return
dst_alloc
(
&
ip6_dst_ops
);
}
struct
rt6_info
*
ip6_dst_alloc
(
void
)
{
return
__ip6_dst_alloc
();
}
/*
* Route lookup. Any rt6_lock is implied.
*/
...
...
@@ -640,7 +645,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
if
(
rtmsg
->
rtmsg_metric
==
0
)
rtmsg
->
rtmsg_metric
=
IP6_RT_PRIO_USER
;
rt
=
dst_alloc
(
&
ip6_dst_ops
);
rt
=
__ip6_dst_alloc
(
);
if
(
rt
==
NULL
)
return
-
ENOMEM
;
...
...
@@ -1035,9 +1040,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
static
struct
rt6_info
*
ip6_rt_copy
(
struct
rt6_info
*
ort
)
{
struct
rt6_info
*
rt
;
rt
=
dst_alloc
(
&
ip6_dst_ops
);
struct
rt6_info
*
rt
=
__ip6_dst_alloc
();
if
(
rt
)
{
rt
->
u
.
dst
.
input
=
ort
->
u
.
dst
.
input
;
...
...
@@ -1181,9 +1184,8 @@ int ip6_pkt_discard(struct sk_buff *skb)
int
ip6_rt_addr_add
(
struct
in6_addr
*
addr
,
struct
net_device
*
dev
)
{
struct
rt6_info
*
rt
;
struct
rt6_info
*
rt
=
__ip6_dst_alloc
()
;
rt
=
dst_alloc
(
&
ip6_dst_ops
);
if
(
rt
==
NULL
)
return
-
ENOMEM
;
...
...
net/netlink/af_netlink.c
View file @
70ced8bf
...
...
@@ -1052,6 +1052,7 @@ struct proto_ops netlink_ops = {
struct
net_proto_family
netlink_family_ops
=
{
.
family
=
PF_NETLINK
,
.
create
=
netlink_create
,
.
owner
=
THIS_MODULE
,
/* for consistency 8) */
};
static
int
__init
netlink_proto_init
(
void
)
...
...
@@ -1065,6 +1066,11 @@ static int __init netlink_proto_init(void)
sock_register
(
&
netlink_family_ops
);
#ifdef CONFIG_PROC_FS
create_proc_read_entry
(
"net/netlink"
,
0
,
0
,
netlink_read_proc
,
NULL
);
#endif
/* The netlink device handler may be needed early. */
rtnetlink_init
();
#ifdef CONFIG_NETLINK_DEV
init_netlink
();
#endif
return
0
;
}
...
...
@@ -1075,7 +1081,7 @@ static void __exit netlink_proto_exit(void)
remove_proc_entry
(
"net/netlink"
,
NULL
);
}
module_init
(
netlink_proto_init
);
subsys_initcall
(
netlink_proto_init
);
module_exit
(
netlink_proto_exit
);
MODULE_LICENSE
(
"GPL"
);
net/socket.c
View file @
70ced8bf
...
...
@@ -69,8 +69,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/wanrouter.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_bridge.h>
#include <linux/init.h>
#include <linux/poll.h>
...
...
@@ -143,6 +141,36 @@ static struct file_operations socket_file_ops = {
static
struct
net_proto_family
*
net_families
[
NPROTO
];
static
__inline__
void
net_family_bug
(
int
family
)
{
printk
(
KERN_ERR
"%d is not yet sock_registered!
\n
"
,
family
);
BUG
();
}
int
net_family_get
(
int
family
)
{
struct
net_proto_family
*
prot
=
net_families
[
family
];
int
rc
=
1
;
barrier
();
if
(
likely
(
prot
!=
NULL
))
rc
=
try_module_get
(
prot
->
owner
);
else
net_family_bug
(
family
);
return
rc
;
}
void
net_family_put
(
int
family
)
{
struct
net_proto_family
*
prot
=
net_families
[
family
];
barrier
();
if
(
likely
(
prot
!=
NULL
))
module_put
(
prot
->
owner
);
else
net_family_bug
(
family
);
}
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static
atomic_t
net_family_lockct
=
ATOMIC_INIT
(
0
);
static
spinlock_t
net_family_lock
=
SPIN_LOCK_UNLOCKED
;
...
...
@@ -511,7 +539,7 @@ void sock_release(struct socket *sock)
sock
->
ops
->
release
(
sock
);
sock
->
ops
=
NULL
;
module_put
(
net_families
[
family
]
->
owner
);
net_family_put
(
family
);
}
if
(
sock
->
fasync_list
)
...
...
@@ -1064,7 +1092,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
sock
->
type
=
type
;
i
=
-
EBUSY
;
if
(
!
try_module_get
(
net_families
[
family
]
->
owner
))
if
(
!
net_family_get
(
family
))
goto
out_release
;
if
((
i
=
net_families
[
family
]
->
create
(
sock
,
protocol
))
<
0
)
...
...
@@ -1953,17 +1981,6 @@ void __init sock_init(void)
* do_initcalls is run.
*/
/*
* The netlink device handler may be needed early.
*/
#ifdef CONFIG_NET
rtnetlink_init
();
#endif
#ifdef CONFIG_NETLINK_DEV
init_netlink
();
#endif
#ifdef CONFIG_NETFILTER
netfilter_init
();
#endif
...
...
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