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
be67585e
Commit
be67585e
authored
Jul 10, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV6]: Fix leaks of ndisc DST entries.
parent
531066f2
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
76 additions
and
39 deletions
+76
-39
include/net/ip6_route.h
include/net/ip6_route.h
+5
-1
net/ipv6/ip6_fib.c
net/ipv6/ip6_fib.c
+7
-0
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+6
-29
net/ipv6/route.c
net/ipv6/route.c
+58
-9
No files found.
include/net/ip6_route.h
View file @
be67585e
...
@@ -61,7 +61,11 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
...
@@ -61,7 +61,11 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
struct
in6_addr
*
saddr
,
struct
in6_addr
*
saddr
,
int
oif
,
int
flags
);
int
oif
,
int
flags
);
extern
struct
rt6_info
*
ip6_dst_alloc
(
void
);
extern
struct
dst_entry
*
ndisc_dst_alloc
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
,
int
(
*
output
)(
struct
sk_buff
*
));
extern
int
ndisc_dst_gc
(
int
*
more
);
extern
void
fib6_force_start_gc
(
void
);
/*
/*
* support functions for ND
* support functions for ND
...
...
net/ipv6/ip6_fib.c
View file @
be67585e
...
@@ -496,6 +496,12 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt)
...
@@ -496,6 +496,12 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt)
mod_timer
(
&
ip6_fib_timer
,
jiffies
+
ip6_rt_gc_interval
);
mod_timer
(
&
ip6_fib_timer
,
jiffies
+
ip6_rt_gc_interval
);
}
}
void
fib6_force_start_gc
(
void
)
{
if
(
ip6_fib_timer
.
expires
==
0
)
mod_timer
(
&
ip6_fib_timer
,
jiffies
+
ip6_rt_gc_interval
);
}
/*
/*
* Add routing information to the routing tree.
* Add routing information to the routing tree.
* <destination addr>/<source addr>
* <destination addr>/<source addr>
...
@@ -1214,6 +1220,7 @@ void fib6_run_gc(unsigned long dummy)
...
@@ -1214,6 +1220,7 @@ void fib6_run_gc(unsigned long dummy)
write_lock_bh
(
&
rt6_lock
);
write_lock_bh
(
&
rt6_lock
);
ndisc_dst_gc
(
&
gc_args
.
more
);
fib6_clean_tree
(
&
ip6_routing_table
,
fib6_age
,
0
,
NULL
);
fib6_clean_tree
(
&
ip6_routing_table
,
fib6_age
,
0
,
NULL
);
write_unlock_bh
(
&
rt6_lock
);
write_unlock_bh
(
&
rt6_lock
);
...
...
net/ipv6/ndisc.c
View file @
be67585e
...
@@ -402,25 +402,6 @@ static int ndisc_output(struct sk_buff *skb)
...
@@ -402,25 +402,6 @@ static int ndisc_output(struct sk_buff *skb)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
static
inline
struct
dst_entry
*
ndisc_dst_alloc
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
)
{
struct
rt6_info
*
rt
=
ip6_dst_alloc
();
if
(
unlikely
(
rt
==
NULL
))
goto
out
;
rt
->
rt6i_dev
=
dev
;
rt
->
rt6i_nexthop
=
neigh
;
rt
->
rt6i_expires
=
0
;
rt
->
rt6i_flags
=
RTF_LOCAL
;
rt
->
rt6i_metric
=
0
;
rt
->
u
.
dst
.
metrics
[
RTAX_HOPLIMIT
-
1
]
=
255
;
rt
->
u
.
dst
.
output
=
ndisc_output
;
out:
return
(
struct
dst_entry
*
)
rt
;
}
static
inline
void
ndisc_flow_init
(
struct
flowi
*
fl
,
u8
type
,
static
inline
void
ndisc_flow_init
(
struct
flowi
*
fl
,
u8
type
,
struct
in6_addr
*
saddr
,
struct
in6_addr
*
daddr
)
struct
in6_addr
*
saddr
,
struct
in6_addr
*
daddr
)
{
{
...
@@ -463,13 +444,13 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
...
@@ -463,13 +444,13 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_ADVERTISEMENT
,
src_addr
,
daddr
);
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_ADVERTISEMENT
,
src_addr
,
daddr
);
dst
=
ndisc_dst_alloc
(
dev
,
neigh
);
dst
=
ndisc_dst_alloc
(
dev
,
neigh
,
ndisc_output
);
if
(
!
dst
)
if
(
!
dst
)
return
;
return
;
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
dst_
fre
e
(
dst
);
dst_
releas
e
(
dst
);
return
;
return
;
}
}
...
@@ -485,7 +466,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
...
@@ -485,7 +466,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
ND_PRINTK1
(
"send_na: alloc skb failed
\n
"
);
ND_PRINTK1
(
"send_na: alloc skb failed
\n
"
);
dst_
fre
e
(
dst
);
dst_
releas
e
(
dst
);
return
;
return
;
}
}
...
@@ -515,7 +496,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
...
@@ -515,7 +496,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
csum_partial
((
__u8
*
)
msg
,
csum_partial
((
__u8
*
)
msg
,
len
,
0
));
len
,
0
));
dst_clone
(
dst
);
skb
->
dst
=
dst
;
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
dst_output
(
skb
);
...
@@ -550,10 +530,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
...
@@ -550,10 +530,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_SOLICITATION
,
saddr
,
daddr
);
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_SOLICITATION
,
saddr
,
daddr
);
dst
=
ndisc_dst_alloc
(
dev
,
neigh
);
dst
=
ndisc_dst_alloc
(
dev
,
neigh
,
ndisc_output
);
if
(
!
dst
)
if
(
!
dst
)
return
;
return
;
dst_clone
(
dst
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
...
@@ -570,6 +549,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
...
@@ -570,6 +549,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
1
,
&
err
);
1
,
&
err
);
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
ND_PRINTK1
(
"send_ns: alloc skb failed
\n
"
);
ND_PRINTK1
(
"send_ns: alloc skb failed
\n
"
);
dst_release
(
dst
);
return
;
return
;
}
}
...
@@ -595,7 +575,6 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
...
@@ -595,7 +575,6 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
csum_partial
((
__u8
*
)
msg
,
csum_partial
((
__u8
*
)
msg
,
len
,
0
));
len
,
0
));
/* send it! */
/* send it! */
dst_clone
(
dst
);
skb
->
dst
=
dst
;
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
dst_output
(
skb
);
...
@@ -622,10 +601,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
...
@@ -622,10 +601,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
ndisc_flow_init
(
&
fl
,
NDISC_ROUTER_SOLICITATION
,
saddr
,
daddr
);
ndisc_flow_init
(
&
fl
,
NDISC_ROUTER_SOLICITATION
,
saddr
,
daddr
);
dst
=
ndisc_dst_alloc
(
dev
,
NULL
);
dst
=
ndisc_dst_alloc
(
dev
,
NULL
,
ndisc_output
);
if
(
!
dst
)
if
(
!
dst
)
return
;
return
;
dst_clone
(
dst
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
...
@@ -664,7 +642,6 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
...
@@ -664,7 +642,6 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
csum_partial
((
__u8
*
)
hdr
,
len
,
0
));
csum_partial
((
__u8
*
)
hdr
,
len
,
0
));
/* send it! */
/* send it! */
dst_clone
(
dst
);
skb
->
dst
=
dst
;
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
dst_output
(
skb
);
...
...
net/ipv6/route.c
View file @
be67585e
...
@@ -131,16 +131,11 @@ rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
...
@@ -131,16 +131,11 @@ rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
/* allocate dst with ip6_dst_ops */
/* allocate dst with ip6_dst_ops */
static
__inline__
struct
rt6_info
*
__
ip6_dst_alloc
(
void
)
static
__inline__
struct
rt6_info
*
ip6_dst_alloc
(
void
)
{
{
return
dst_alloc
(
&
ip6_dst_ops
);
return
dst_alloc
(
&
ip6_dst_ops
);
}
}
struct
rt6_info
*
ip6_dst_alloc
(
void
)
{
return
__ip6_dst_alloc
();
}
/*
/*
* Route lookup. Any rt6_lock is implied.
* Route lookup. Any rt6_lock is implied.
*/
*/
...
@@ -560,6 +555,60 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
...
@@ -560,6 +555,60 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
}
}
}
}
/* Protected by rt6_lock. */
static
struct
dst_entry
*
ndisc_dst_gc_list
;
struct
dst_entry
*
ndisc_dst_alloc
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
,
int
(
*
output
)(
struct
sk_buff
*
))
{
struct
rt6_info
*
rt
=
ip6_dst_alloc
();
if
(
unlikely
(
rt
==
NULL
))
goto
out
;
rt
->
rt6i_dev
=
dev
;
rt
->
rt6i_nexthop
=
neigh
;
rt
->
rt6i_expires
=
0
;
rt
->
rt6i_flags
=
RTF_LOCAL
;
rt
->
rt6i_metric
=
0
;
atomic_set
(
&
rt
->
u
.
dst
.
__refcnt
,
1
);
rt
->
u
.
dst
.
metrics
[
RTAX_HOPLIMIT
-
1
]
=
255
;
rt
->
u
.
dst
.
output
=
output
;
write_lock_bh
(
&
rt6_lock
);
rt
->
u
.
dst
.
next
=
ndisc_dst_gc_list
;
ndisc_dst_gc_list
=
&
rt
->
u
.
dst
;
write_unlock_bh
(
&
rt6_lock
);
fib6_force_start_gc
();
out:
return
(
struct
dst_entry
*
)
rt
;
}
int
ndisc_dst_gc
(
int
*
more
)
{
struct
dst_entry
*
dst
,
*
next
,
**
pprev
;
int
freed
;
next
=
NULL
;
pprev
=
&
ndisc_dst_gc_list
;
freed
=
0
;
while
((
dst
=
*
pprev
)
!=
NULL
)
{
if
(
!
atomic_read
(
&
dst
->
__refcnt
))
{
*
pprev
=
dst
->
next
;
dst_free
(
dst
);
freed
++
;
}
else
{
pprev
=
&
dst
->
next
;
(
*
more
)
++
;
}
}
return
freed
;
}
static
int
ip6_dst_gc
(
void
)
static
int
ip6_dst_gc
(
void
)
{
{
static
unsigned
expire
=
30
*
HZ
;
static
unsigned
expire
=
30
*
HZ
;
...
@@ -655,7 +704,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
...
@@ -655,7 +704,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
if
(
rtmsg
->
rtmsg_metric
==
0
)
if
(
rtmsg
->
rtmsg_metric
==
0
)
rtmsg
->
rtmsg_metric
=
IP6_RT_PRIO_USER
;
rtmsg
->
rtmsg_metric
=
IP6_RT_PRIO_USER
;
rt
=
__
ip6_dst_alloc
();
rt
=
ip6_dst_alloc
();
if
(
rt
==
NULL
)
if
(
rt
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -1066,7 +1115,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
...
@@ -1066,7 +1115,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
static
struct
rt6_info
*
ip6_rt_copy
(
struct
rt6_info
*
ort
)
static
struct
rt6_info
*
ip6_rt_copy
(
struct
rt6_info
*
ort
)
{
{
struct
rt6_info
*
rt
=
__
ip6_dst_alloc
();
struct
rt6_info
*
rt
=
ip6_dst_alloc
();
if
(
rt
)
{
if
(
rt
)
{
rt
->
u
.
dst
.
input
=
ort
->
u
.
dst
.
input
;
rt
->
u
.
dst
.
input
=
ort
->
u
.
dst
.
input
;
...
@@ -1209,7 +1258,7 @@ int ip6_pkt_discard(struct sk_buff *skb)
...
@@ -1209,7 +1258,7 @@ int ip6_pkt_discard(struct sk_buff *skb)
int
ip6_rt_addr_add
(
struct
in6_addr
*
addr
,
struct
net_device
*
dev
)
int
ip6_rt_addr_add
(
struct
in6_addr
*
addr
,
struct
net_device
*
dev
)
{
{
struct
rt6_info
*
rt
=
__
ip6_dst_alloc
();
struct
rt6_info
*
rt
=
ip6_dst_alloc
();
if
(
rt
==
NULL
)
if
(
rt
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
...
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