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
36b609df
Commit
36b609df
authored
Jun 25, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/jmorris/net-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
3cee4c3f
9e9d4917
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
110 additions
and
114 deletions
+110
-114
include/linux/mroute.h
include/linux/mroute.h
+0
-1
net/ipv4/igmp.c
net/ipv4/igmp.c
+18
-12
net/ipv4/ipmr.c
net/ipv4/ipmr.c
+66
-86
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+26
-15
No files found.
include/linux/mroute.h
View file @
36b609df
...
@@ -217,7 +217,6 @@ struct pimreghdr
...
@@ -217,7 +217,6 @@ struct pimreghdr
__u32
flags
;
__u32
flags
;
};
};
extern
int
pim_rcv
(
struct
sk_buff
*
);
extern
int
pim_rcv_v1
(
struct
sk_buff
*
);
extern
int
pim_rcv_v1
(
struct
sk_buff
*
);
struct
rtmsg
;
struct
rtmsg
;
...
...
net/ipv4/igmp.c
View file @
36b609df
...
@@ -757,9 +757,10 @@ static void igmp_heard_report(struct in_device *in_dev, u32 group)
...
@@ -757,9 +757,10 @@ static void igmp_heard_report(struct in_device *in_dev, u32 group)
read_unlock
(
&
in_dev
->
lock
);
read_unlock
(
&
in_dev
->
lock
);
}
}
static
void
igmp_heard_query
(
struct
in_device
*
in_dev
,
struct
igmphdr
*
ih
,
static
void
igmp_heard_query
(
struct
in_device
*
in_dev
,
struct
sk_buff
*
skb
,
int
len
)
int
len
)
{
{
struct
igmphdr
*
ih
=
skb
->
h
.
igmph
;
struct
igmpv3_query
*
ih3
=
(
struct
igmpv3_query
*
)
ih
;
struct
igmpv3_query
*
ih3
=
(
struct
igmpv3_query
*
)
ih
;
struct
ip_mc_list
*
im
;
struct
ip_mc_list
*
im
;
u32
group
=
ih
->
group
;
u32
group
=
ih
->
group
;
...
@@ -790,6 +791,17 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
...
@@ -790,6 +791,17 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
}
else
if
(
len
<
12
)
{
}
else
if
(
len
<
12
)
{
return
;
/* ignore bogus packet; freed by caller */
return
;
/* ignore bogus packet; freed by caller */
}
else
{
/* v3 */
}
else
{
/* v3 */
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
struct
igmpv3_query
)))
return
;
ih3
=
(
struct
igmpv3_query
*
)
skb
->
h
.
raw
;
if
(
ih3
->
nsrcs
)
{
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
struct
igmpv3_query
)
+
ntohs
(
ih3
->
nsrcs
)
*
sizeof
(
__u32
)))
return
;
ih3
=
(
struct
igmpv3_query
*
)
skb
->
h
.
raw
;
}
max_delay
=
IGMPV3_MRC
(
ih3
->
code
)
*
(
HZ
/
IGMP_TIMER_SCALE
);
max_delay
=
IGMPV3_MRC
(
ih3
->
code
)
*
(
HZ
/
IGMP_TIMER_SCALE
);
if
(
!
max_delay
)
if
(
!
max_delay
)
max_delay
=
1
;
/* can't mod w/ 0 */
max_delay
=
1
;
/* can't mod w/ 0 */
...
@@ -838,7 +850,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
...
@@ -838,7 +850,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
int
igmp_rcv
(
struct
sk_buff
*
skb
)
int
igmp_rcv
(
struct
sk_buff
*
skb
)
{
{
/* This basically follows the spec line by line -- see RFC1112 */
/* This basically follows the spec line by line -- see RFC1112 */
struct
igmphdr
*
ih
=
skb
->
h
.
igmph
;
struct
igmphdr
*
ih
;
struct
in_device
*
in_dev
=
in_dev_get
(
skb
->
dev
);
struct
in_device
*
in_dev
=
in_dev_get
(
skb
->
dev
);
int
len
=
skb
->
len
;
int
len
=
skb
->
len
;
...
@@ -847,23 +859,17 @@ int igmp_rcv(struct sk_buff *skb)
...
@@ -847,23 +859,17 @@ int igmp_rcv(struct sk_buff *skb)
return
0
;
return
0
;
}
}
if
(
skb_is_nonlinear
(
skb
))
{
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
struct
igmphdr
))
||
if
(
skb_linearize
(
skb
,
GFP_ATOMIC
)
!=
0
)
{
(
u16
)
csum_fold
(
skb_checksum
(
skb
,
0
,
len
,
0
)))
{
kfree_skb
(
skb
);
return
-
ENOMEM
;
}
ih
=
skb
->
h
.
igmph
;
}
if
(
len
<
sizeof
(
struct
igmphdr
)
||
ip_compute_csum
((
void
*
)
ih
,
len
))
{
in_dev_put
(
in_dev
);
in_dev_put
(
in_dev
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
0
;
return
0
;
}
}
ih
=
skb
->
h
.
igmph
;
switch
(
ih
->
type
)
{
switch
(
ih
->
type
)
{
case
IGMP_HOST_MEMBERSHIP_QUERY
:
case
IGMP_HOST_MEMBERSHIP_QUERY
:
igmp_heard_query
(
in_dev
,
ih
,
len
);
igmp_heard_query
(
in_dev
,
skb
,
len
);
break
;
break
;
case
IGMP_HOST_MEMBERSHIP_REPORT
:
case
IGMP_HOST_MEMBERSHIP_REPORT
:
case
IGMPV2_HOST_MEMBERSHIP_REPORT
:
case
IGMPV2_HOST_MEMBERSHIP_REPORT
:
...
...
net/ipv4/ipmr.c
View file @
36b609df
...
@@ -83,13 +83,13 @@ static int maxvif;
...
@@ -83,13 +83,13 @@ static int maxvif;
#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL)
#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL)
int
mroute_do_assert
;
/* Set in PIM assert */
static
int
mroute_do_assert
;
/* Set in PIM assert */
int
mroute_do_pim
;
static
int
mroute_do_pim
;
static
struct
mfc_cache
*
mfc_cache_array
[
MFC_LINES
];
/* Forwarding cache */
static
struct
mfc_cache
*
mfc_cache_array
[
MFC_LINES
];
/* Forwarding cache */
static
struct
mfc_cache
*
mfc_unres_queue
;
/* Queue of unresolved entries */
static
struct
mfc_cache
*
mfc_unres_queue
;
/* Queue of unresolved entries */
atomic_t
cache_resolve_queue_len
;
/* Size of unresolved */
static
atomic_t
cache_resolve_queue_len
;
/* Size of unresolved */
/* Special spinlock for queue of unresolved entries */
/* Special spinlock for queue of unresolved entries */
static
spinlock_t
mfc_unres_lock
=
SPIN_LOCK_UNLOCKED
;
static
spinlock_t
mfc_unres_lock
=
SPIN_LOCK_UNLOCKED
;
...
@@ -102,7 +102,7 @@ static spinlock_t mfc_unres_lock = SPIN_LOCK_UNLOCKED;
...
@@ -102,7 +102,7 @@ static spinlock_t mfc_unres_lock = SPIN_LOCK_UNLOCKED;
In this case data path is free of exclusive locks at all.
In this case data path is free of exclusive locks at all.
*/
*/
kmem_cache_t
*
mrt_cachep
;
static
kmem_cache_t
*
mrt_cachep
;
static
int
ip_mr_forward
(
struct
sk_buff
*
skb
,
struct
mfc_cache
*
cache
,
int
local
);
static
int
ip_mr_forward
(
struct
sk_buff
*
skb
,
struct
mfc_cache
*
cache
,
int
local
);
static
int
ipmr_cache_report
(
struct
sk_buff
*
pkt
,
vifi_t
vifi
,
int
assert
);
static
int
ipmr_cache_report
(
struct
sk_buff
*
pkt
,
vifi_t
vifi
,
int
assert
);
...
@@ -158,6 +158,10 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
...
@@ -158,6 +158,10 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
return
dev
;
return
dev
;
failure:
failure:
/* allow the register to be completed before unregistering. */
rtnl_unlock
();
rtnl_lock
();
unregister_netdevice
(
dev
);
unregister_netdevice
(
dev
);
return
NULL
;
return
NULL
;
}
}
...
@@ -182,35 +186,23 @@ static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
...
@@ -182,35 +186,23 @@ static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
return
(
struct
net_device_stats
*
)
dev
->
priv
;
return
(
struct
net_device_stats
*
)
dev
->
priv
;
}
}
static
void
vif_dev_destructor
(
struct
net_device
*
dev
)
static
void
reg_vif_setup
(
struct
net_device
*
dev
)
{
{
kfree
(
dev
);
dev
->
type
=
ARPHRD_PIMREG
;
dev
->
mtu
=
1500
-
sizeof
(
struct
iphdr
)
-
8
;
dev
->
flags
=
IFF_NOARP
;
dev
->
hard_start_xmit
=
reg_vif_xmit
;
dev
->
get_stats
=
reg_vif_get_stats
;
dev
->
destructor
=
(
void
(
*
)(
struct
net_device
*
))
kfree
;
}
}
static
static
struct
net_device
*
ipmr_reg_vif
(
void
)
struct
net_device
*
ipmr_reg_vif
(
struct
vifctl
*
v
)
{
{
struct
net_device
*
dev
;
struct
net_device
*
dev
;
struct
in_device
*
in_dev
;
struct
in_device
*
in_dev
;
int
size
;
size
=
sizeof
(
*
dev
)
+
sizeof
(
struct
net_device_stats
);
dev
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
dev
)
return
NULL
;
memset
(
dev
,
0
,
size
);
dev
->
priv
=
dev
+
1
;
dev
=
alloc_netdev
(
sizeof
(
struct
net_device_stats
),
"pimreg"
,
reg_vif_setup
);
strcpy
(
dev
->
name
,
"pimreg"
);
dev
->
type
=
ARPHRD_PIMREG
;
dev
->
mtu
=
1500
-
sizeof
(
struct
iphdr
)
-
8
;
dev
->
flags
=
IFF_NOARP
;
dev
->
hard_start_xmit
=
reg_vif_xmit
;
dev
->
get_stats
=
reg_vif_get_stats
;
dev
->
destructor
=
vif_dev_destructor
;
if
(
register_netdevice
(
dev
))
{
if
(
register_netdevice
(
dev
))
{
kfree
(
dev
);
kfree
(
dev
);
...
@@ -229,6 +221,10 @@ struct net_device *ipmr_reg_vif(struct vifctl *v)
...
@@ -229,6 +221,10 @@ struct net_device *ipmr_reg_vif(struct vifctl *v)
return
dev
;
return
dev
;
failure:
failure:
/* allow the register to be completed before unregistering. */
rtnl_unlock
();
rtnl_lock
();
unregister_netdevice
(
dev
);
unregister_netdevice
(
dev
);
return
NULL
;
return
NULL
;
}
}
...
@@ -316,7 +312,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c)
...
@@ -316,7 +312,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c)
/* Single timer process for all the unresolved queue. */
/* Single timer process for all the unresolved queue. */
void
ipmr_expire_process
(
unsigned
long
dummy
)
static
void
ipmr_expire_process
(
unsigned
long
dummy
)
{
{
unsigned
long
now
;
unsigned
long
now
;
unsigned
long
expires
;
unsigned
long
expires
;
...
@@ -335,9 +331,8 @@ void ipmr_expire_process(unsigned long dummy)
...
@@ -335,9 +331,8 @@ void ipmr_expire_process(unsigned long dummy)
cp
=
&
mfc_unres_queue
;
cp
=
&
mfc_unres_queue
;
while
((
c
=*
cp
)
!=
NULL
)
{
while
((
c
=*
cp
)
!=
NULL
)
{
long
interval
=
c
->
mfc_un
.
unres
.
expires
-
now
;
if
(
time_after
(
c
->
mfc_un
.
unres
.
expires
,
now
))
{
unsigned
long
interval
=
c
->
mfc_un
.
unres
.
expires
-
now
;
if
(
interval
>
0
)
{
if
(
interval
<
expires
)
if
(
interval
<
expires
)
expires
=
interval
;
expires
=
interval
;
cp
=
&
c
->
next
;
cp
=
&
c
->
next
;
...
@@ -397,7 +392,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
...
@@ -397,7 +392,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
*/
*/
if
(
reg_vif_num
>=
0
)
if
(
reg_vif_num
>=
0
)
return
-
EADDRINUSE
;
return
-
EADDRINUSE
;
dev
=
ipmr_reg_vif
(
vifc
);
dev
=
ipmr_reg_vif
();
if
(
!
dev
)
if
(
!
dev
)
return
-
ENOBUFS
;
return
-
ENOBUFS
;
break
;
break
;
...
@@ -683,7 +678,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
...
@@ -683,7 +678,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
* MFC cache manipulation by user space mroute daemon
* MFC cache manipulation by user space mroute daemon
*/
*/
int
ipmr_mfc_delete
(
struct
mfcctl
*
mfc
)
static
int
ipmr_mfc_delete
(
struct
mfcctl
*
mfc
)
{
{
int
line
;
int
line
;
struct
mfc_cache
*
c
,
**
cp
;
struct
mfc_cache
*
c
,
**
cp
;
...
@@ -704,7 +699,7 @@ int ipmr_mfc_delete(struct mfcctl *mfc)
...
@@ -704,7 +699,7 @@ int ipmr_mfc_delete(struct mfcctl *mfc)
return
-
ENOENT
;
return
-
ENOENT
;
}
}
int
ipmr_mfc_add
(
struct
mfcctl
*
mfc
,
int
mrtsock
)
static
int
ipmr_mfc_add
(
struct
mfcctl
*
mfc
,
int
mrtsock
)
{
{
int
line
;
int
line
;
struct
mfc_cache
*
uc
,
*
c
,
**
cp
;
struct
mfc_cache
*
uc
,
*
c
,
**
cp
;
...
@@ -1078,9 +1073,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
...
@@ -1078,9 +1073,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
static
struct
notifier_block
ip_mr_notifier
=
{
static
struct
notifier_block
ip_mr_notifier
=
{
ipmr_device_event
,
.
notifier_call
=
ipmr_device_event
,
NULL
,
0
};
};
/*
/*
...
@@ -1234,7 +1227,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
...
@@ -1234,7 +1227,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
ipmr_forward_finish
);
ipmr_forward_finish
);
}
}
int
ipmr_find_vif
(
struct
net_device
*
dev
)
static
int
ipmr_find_vif
(
struct
net_device
*
dev
)
{
{
int
ct
;
int
ct
;
for
(
ct
=
maxvif
-
1
;
ct
>=
0
;
ct
--
)
{
for
(
ct
=
maxvif
-
1
;
ct
>=
0
;
ct
--
)
{
...
@@ -1246,7 +1239,7 @@ int ipmr_find_vif(struct net_device *dev)
...
@@ -1246,7 +1239,7 @@ int ipmr_find_vif(struct net_device *dev)
/* "local" means that we should preserve one skb (for local delivery) */
/* "local" means that we should preserve one skb (for local delivery) */
int
ip_mr_forward
(
struct
sk_buff
*
skb
,
struct
mfc_cache
*
cache
,
int
local
)
static
int
ip_mr_forward
(
struct
sk_buff
*
skb
,
struct
mfc_cache
*
cache
,
int
local
)
{
{
int
psend
=
-
1
;
int
psend
=
-
1
;
int
vif
,
ct
;
int
vif
,
ct
;
...
@@ -1286,7 +1279,8 @@ int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local)
...
@@ -1286,7 +1279,8 @@ int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local)
large chunk of pimd to kernel. Ough... --ANK
large chunk of pimd to kernel. Ough... --ANK
*/
*/
(
mroute_do_pim
||
cache
->
mfc_un
.
res
.
ttls
[
true_vifi
]
<
255
)
&&
(
mroute_do_pim
||
cache
->
mfc_un
.
res
.
ttls
[
true_vifi
]
<
255
)
&&
jiffies
-
cache
->
mfc_un
.
res
.
last_assert
>
MFC_ASSERT_THRESH
)
{
time_after
(
jiffies
,
cache
->
mfc_un
.
res
.
last_assert
+
MFC_ASSERT_THRESH
))
{
cache
->
mfc_un
.
res
.
last_assert
=
jiffies
;
cache
->
mfc_un
.
res
.
last_assert
=
jiffies
;
ipmr_cache_report
(
skb
,
true_vifi
,
IGMPMSG_WRONGVIF
);
ipmr_cache_report
(
skb
,
true_vifi
,
IGMPMSG_WRONGVIF
);
}
}
...
@@ -1406,24 +1400,19 @@ int ip_mr_input(struct sk_buff *skb)
...
@@ -1406,24 +1400,19 @@ int ip_mr_input(struct sk_buff *skb)
int
pim_rcv_v1
(
struct
sk_buff
*
skb
)
int
pim_rcv_v1
(
struct
sk_buff
*
skb
)
{
{
struct
igmphdr
*
pim
=
(
struct
igmphdr
*
)
skb
->
h
.
raw
;
struct
igmphdr
*
pim
;
struct
iphdr
*
encap
;
struct
iphdr
*
encap
;
struct
net_device
*
reg_dev
=
NULL
;
struct
net_device
*
reg_dev
=
NULL
;
if
(
skb_is_nonlinear
(
skb
))
{
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
*
pim
)
+
sizeof
(
*
encap
)))
if
(
skb_linearize
(
skb
,
GFP_ATOMIC
)
!=
0
)
{
goto
drop
;
kfree_skb
(
skb
);
return
-
ENOMEM
;
}
pim
=
(
struct
igmphdr
*
)
skb
->
h
.
raw
;
pim
=
(
struct
igmphdr
*
)
skb
->
h
.
raw
;
}
if
(
!
mroute_do_pim
||
if
(
!
mroute_do_pim
||
skb
->
len
<
sizeof
(
*
pim
)
+
sizeof
(
*
encap
)
||
skb
->
len
<
sizeof
(
*
pim
)
+
sizeof
(
*
encap
)
||
pim
->
group
!=
PIM_V1_VERSION
||
pim
->
code
!=
PIM_V1_REGISTER
)
{
pim
->
group
!=
PIM_V1_VERSION
||
pim
->
code
!=
PIM_V1_REGISTER
)
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
encap
=
(
struct
iphdr
*
)(
skb
->
h
.
raw
+
sizeof
(
struct
igmphdr
));
encap
=
(
struct
iphdr
*
)(
skb
->
h
.
raw
+
sizeof
(
struct
igmphdr
));
/*
/*
...
@@ -1433,11 +1422,9 @@ int pim_rcv_v1(struct sk_buff * skb)
...
@@ -1433,11 +1422,9 @@ int pim_rcv_v1(struct sk_buff * skb)
c. packet is not truncated
c. packet is not truncated
*/
*/
if
(
!
MULTICAST
(
encap
->
daddr
)
||
if
(
!
MULTICAST
(
encap
->
daddr
)
||
ntohs
(
encap
->
tot_len
)
==
0
||
encap
->
tot_len
==
0
||
ntohs
(
encap
->
tot_len
)
+
sizeof
(
*
pim
)
>
skb
->
len
)
{
ntohs
(
encap
->
tot_len
)
+
sizeof
(
*
pim
)
>
skb
->
len
)
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
read_lock
(
&
mrt_lock
);
read_lock
(
&
mrt_lock
);
if
(
reg_vif_num
>=
0
)
if
(
reg_vif_num
>=
0
)
...
@@ -1446,10 +1433,8 @@ int pim_rcv_v1(struct sk_buff * skb)
...
@@ -1446,10 +1433,8 @@ int pim_rcv_v1(struct sk_buff * skb)
dev_hold
(
reg_dev
);
dev_hold
(
reg_dev
);
read_unlock
(
&
mrt_lock
);
read_unlock
(
&
mrt_lock
);
if
(
reg_dev
==
NULL
)
{
if
(
reg_dev
==
NULL
)
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
skb
->
mac
.
raw
=
skb
->
nh
.
raw
;
skb
->
mac
.
raw
=
skb
->
nh
.
raw
;
skb_pull
(
skb
,
(
u8
*
)
encap
-
skb
->
data
);
skb_pull
(
skb
,
(
u8
*
)
encap
-
skb
->
data
);
...
@@ -1470,41 +1455,35 @@ int pim_rcv_v1(struct sk_buff * skb)
...
@@ -1470,41 +1455,35 @@ int pim_rcv_v1(struct sk_buff * skb)
netif_rx
(
skb
);
netif_rx
(
skb
);
dev_put
(
reg_dev
);
dev_put
(
reg_dev
);
return
0
;
return
0
;
drop:
kfree_skb
(
skb
);
return
0
;
}
}
#endif
#endif
#ifdef CONFIG_IP_PIMSM_V2
#ifdef CONFIG_IP_PIMSM_V2
int
pim_rcv
(
struct
sk_buff
*
skb
)
static
int
pim_rcv
(
struct
sk_buff
*
skb
)
{
{
struct
pimreghdr
*
pim
=
(
struct
pimreghdr
*
)
skb
->
h
.
raw
;
struct
pimreghdr
*
pim
;
struct
iphdr
*
encap
;
struct
iphdr
*
encap
;
struct
net_device
*
reg_dev
=
NULL
;
struct
net_device
*
reg_dev
=
NULL
;
if
(
skb_is_nonlinear
(
skb
))
{
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
*
pim
)
+
sizeof
(
*
encap
)))
if
(
skb_linearize
(
skb
,
GFP_ATOMIC
)
!=
0
)
{
goto
drop
;
kfree_skb
(
skb
);
return
-
ENOMEM
;
}
pim
=
(
struct
pimreghdr
*
)
skb
->
h
.
raw
;
}
if
(
skb
->
len
<
sizeof
(
*
pim
)
+
sizeof
(
*
encap
)
||
pim
=
(
struct
pimreghdr
*
)
skb
->
h
.
raw
;
pim
->
type
!=
((
PIM_VERSION
<<
4
)
|
(
PIM_REGISTER
))
||
if
(
pim
->
type
!=
((
PIM_VERSION
<<
4
)
|
(
PIM_REGISTER
))
||
(
pim
->
flags
&
PIM_NULL_REGISTER
)
||
(
pim
->
flags
&
PIM_NULL_REGISTER
)
||
(
ip_compute_csum
((
void
*
)
pim
,
sizeof
(
*
pim
))
!=
0
&&
(
ip_compute_csum
((
void
*
)
pim
,
sizeof
(
*
pim
))
!=
0
&&
ip_compute_csum
((
void
*
)
pim
,
skb
->
len
)))
{
(
u16
)
csum_fold
(
skb_checksum
(
skb
,
0
,
skb
->
len
,
0
))))
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
/* check if the inner packet is destined to mcast group */
/* check if the inner packet is destined to mcast group */
encap
=
(
struct
iphdr
*
)(
skb
->
h
.
raw
+
sizeof
(
struct
pimreghdr
));
encap
=
(
struct
iphdr
*
)(
skb
->
h
.
raw
+
sizeof
(
struct
pimreghdr
));
if
(
!
MULTICAST
(
encap
->
daddr
)
||
if
(
!
MULTICAST
(
encap
->
daddr
)
||
ntohs
(
encap
->
tot_len
)
==
0
||
encap
->
tot_len
==
0
||
ntohs
(
encap
->
tot_len
)
+
sizeof
(
*
pim
)
>
skb
->
len
)
{
ntohs
(
encap
->
tot_len
)
+
sizeof
(
*
pim
)
>
skb
->
len
)
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
read_lock
(
&
mrt_lock
);
read_lock
(
&
mrt_lock
);
if
(
reg_vif_num
>=
0
)
if
(
reg_vif_num
>=
0
)
...
@@ -1513,10 +1492,8 @@ int pim_rcv(struct sk_buff * skb)
...
@@ -1513,10 +1492,8 @@ int pim_rcv(struct sk_buff * skb)
dev_hold
(
reg_dev
);
dev_hold
(
reg_dev
);
read_unlock
(
&
mrt_lock
);
read_unlock
(
&
mrt_lock
);
if
(
reg_dev
==
NULL
)
{
if
(
reg_dev
==
NULL
)
kfree_skb
(
skb
);
goto
drop
;
return
-
EINVAL
;
}
skb
->
mac
.
raw
=
skb
->
nh
.
raw
;
skb
->
mac
.
raw
=
skb
->
nh
.
raw
;
skb_pull
(
skb
,
(
u8
*
)
encap
-
skb
->
data
);
skb_pull
(
skb
,
(
u8
*
)
encap
-
skb
->
data
);
...
@@ -1537,6 +1514,9 @@ int pim_rcv(struct sk_buff * skb)
...
@@ -1537,6 +1514,9 @@ int pim_rcv(struct sk_buff * skb)
netif_rx
(
skb
);
netif_rx
(
skb
);
dev_put
(
reg_dev
);
dev_put
(
reg_dev
);
return
0
;
return
0
;
drop:
kfree_skb
(
skb
);
return
0
;
}
}
#endif
#endif
...
...
net/ipv6/ndisc.c
View file @
36b609df
...
@@ -713,6 +713,7 @@ void ndisc_recv_ns(struct sk_buff *skb)
...
@@ -713,6 +713,7 @@ void ndisc_recv_ns(struct sk_buff *skb)
struct
net_device
*
dev
=
skb
->
dev
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
inet6_ifaddr
*
ifp
;
struct
inet6_ifaddr
*
ifp
;
struct
neighbour
*
neigh
;
struct
neighbour
*
neigh
;
int
addr_type
=
ipv6_addr_type
(
saddr
);
if
(
ipv6_addr_type
(
&
msg
->
target
)
&
IPV6_ADDR_MULTICAST
)
{
if
(
ipv6_addr_type
(
&
msg
->
target
)
&
IPV6_ADDR_MULTICAST
)
{
if
(
net_ratelimit
())
if
(
net_ratelimit
())
...
@@ -720,6 +721,20 @@ void ndisc_recv_ns(struct sk_buff *skb)
...
@@ -720,6 +721,20 @@ void ndisc_recv_ns(struct sk_buff *skb)
return
;
return
;
}
}
/*
* RFC2461 7.1.1:
* DAD has to be destined for solicited node multicast address.
*/
if
(
addr_type
==
IPV6_ADDR_ANY
&&
!
(
daddr
->
s6_addr32
[
0
]
==
htonl
(
0xff020000
)
&&
daddr
->
s6_addr32
[
1
]
==
htonl
(
0x00000000
)
&&
daddr
->
s6_addr32
[
2
]
==
htonl
(
0x00000001
)
&&
daddr
->
s6_addr
[
12
]
==
0xff
))
{
if
(
net_ratelimit
())
printk
(
KERN_DEBUG
"ICMP6 NS: bad DAD packet (wrong destination)
\n
"
);
return
;
}
if
(
!
ndisc_parse_options
(
msg
->
opt
,
ndoptlen
,
&
ndopts
))
{
if
(
!
ndisc_parse_options
(
msg
->
opt
,
ndoptlen
,
&
ndopts
))
{
if
(
net_ratelimit
())
if
(
net_ratelimit
())
printk
(
KERN_WARNING
"ICMP NS: invalid ND option, ignored.
\n
"
);
printk
(
KERN_WARNING
"ICMP NS: invalid ND option, ignored.
\n
"
);
...
@@ -734,23 +749,20 @@ void ndisc_recv_ns(struct sk_buff *skb)
...
@@ -734,23 +749,20 @@ void ndisc_recv_ns(struct sk_buff *skb)
printk
(
KERN_WARNING
"ICMP NS: bad lladdr length.
\n
"
);
printk
(
KERN_WARNING
"ICMP NS: bad lladdr length.
\n
"
);
return
;
return
;
}
}
}
/* XXX: RFC2461 7.1.1:
* If the IP source address is the unspecified address, there
* MUST NOT be source link-layer address option in the message.
*
* NOTE! Linux kernel < 2.4.4 broke this rule.
*/
/* XXX: RFC2461 7.1.1:
/* XXX: RFC2461 7.1.1:
* If the IP source address is the unspecified address, the IP
* If the IP source address is the unspecified address,
* destination address MUST be a solicited-node multicast address.
* there MUST NOT be source link-layer address option
* in the message.
*/
*/
if
(
addr_type
==
IPV6_ADDR_ANY
)
{
if
(
net_ratelimit
())
printk
(
KERN_WARNING
"ICMP6 NS: bad DAD packet (link-layer address option)
\n
"
);
return
;
}
}
if
((
ifp
=
ipv6_get_ifaddr
(
&
msg
->
target
,
dev
))
!=
NULL
)
{
if
((
ifp
=
ipv6_get_ifaddr
(
&
msg
->
target
,
dev
))
!=
NULL
)
{
int
addr_type
=
ipv6_addr_type
(
saddr
);
if
(
ifp
->
flags
&
IFA_F_TENTATIVE
)
{
if
(
ifp
->
flags
&
IFA_F_TENTATIVE
)
{
/* Address is tentative. If the source
/* Address is tentative. If the source
is unspecified address, it is someone
is unspecified address, it is someone
...
@@ -816,7 +828,6 @@ void ndisc_recv_ns(struct sk_buff *skb)
...
@@ -816,7 +828,6 @@ void ndisc_recv_ns(struct sk_buff *skb)
in6_ifa_put
(
ifp
);
in6_ifa_put
(
ifp
);
}
else
if
(
ipv6_chk_acast_addr
(
dev
,
&
msg
->
target
))
{
}
else
if
(
ipv6_chk_acast_addr
(
dev
,
&
msg
->
target
))
{
struct
inet6_dev
*
idev
=
in6_dev_get
(
dev
);
struct
inet6_dev
*
idev
=
in6_dev_get
(
dev
);
int
addr_type
=
ipv6_addr_type
(
saddr
);
/* anycast */
/* anycast */
...
...
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