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
cc0142de
Commit
cc0142de
authored
Apr 25, 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
00d412d2
cab9315c
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
438 additions
and
320 deletions
+438
-320
include/linux/list.h
include/linux/list.h
+15
-0
include/net/if_inet6.h
include/net/if_inet6.h
+8
-0
include/net/ipv6.h
include/net/ipv6.h
+31
-7
include/net/snmp.h
include/net/snmp.h
+2
-0
net/bridge/br_device.c
net/bridge/br_device.c
+4
-16
net/bridge/br_forward.c
net/bridge/br_forward.c
+13
-13
net/bridge/br_if.c
net/bridge/br_if.c
+39
-44
net/bridge/br_input.c
net/bridge/br_input.c
+20
-43
net/bridge/br_ioctl.c
net/bridge/br_ioctl.c
+17
-17
net/bridge/br_notify.c
net/bridge/br_notify.c
+6
-6
net/bridge/br_private.h
net/bridge/br_private.h
+7
-5
net/bridge/br_stp.c
net/bridge/br_stp.c
+10
-33
net/bridge/br_stp_bpdu.c
net/bridge/br_stp_bpdu.c
+14
-11
net/bridge/br_stp_if.c
net/bridge/br_stp_if.c
+10
-18
net/bridge/br_stp_timer.c
net/bridge/br_stp_timer.c
+6
-12
net/ipv6/addrconf.c
net/ipv6/addrconf.c
+10
-0
net/ipv6/af_inet6.c
net/ipv6/af_inet6.c
+54
-59
net/ipv6/icmp.c
net/ipv6/icmp.c
+23
-8
net/ipv6/ipv6_syms.c
net/ipv6/ipv6_syms.c
+1
-0
net/ipv6/mcast.c
net/ipv6/mcast.c
+13
-4
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+28
-8
net/ipv6/proc.c
net/ipv6/proc.c
+98
-13
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+1
-1
net/sctp/ipv6.c
net/sctp/ipv6.c
+8
-2
No files found.
include/linux/list.h
View file @
cc0142de
...
...
@@ -320,6 +320,21 @@ static inline void list_splice_init(struct list_head *list,
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
/**
* list_for_each_entry_rcu - iterate over rcu list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_rcu(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member), \
({ smp_read_barrier_depends(); 0;}), \
prefetch(pos->member.next))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
...
...
include/net/if_inet6.h
View file @
cc0142de
...
...
@@ -15,6 +15,8 @@
#ifndef _NET_IF_INET6_H
#define _NET_IF_INET6_H
#include <net/snmp.h>
#define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10
...
...
@@ -152,6 +154,11 @@ struct ipv6_devconf
void
*
sysctl
;
};
struct
ipv6_devstat
{
struct
proc_dir_entry
*
proc_dir_entry
;
DEFINE_SNMP_STAT
(
struct
icmpv6_mib
,
icmpv6
);
};
struct
inet6_dev
{
struct
net_device
*
dev
;
...
...
@@ -185,6 +192,7 @@ struct inet6_dev
struct
neigh_parms
*
nd_parms
;
struct
inet6_dev
*
next
;
struct
ipv6_devconf
cnf
;
struct
ipv6_devstat
stats
;
};
extern
struct
ipv6_devconf
ipv6_devconf
;
...
...
include/net/ipv6.h
View file @
cc0142de
...
...
@@ -106,24 +106,48 @@ struct frag_hdr {
/* sysctls */
extern
int
sysctl_ipv6_bindv6only
;
/* MIBs */
DECLARE_SNMP_STAT
(
struct
ipv6_mib
,
ipv6_statistics
);
#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field)
DECLARE_SNMP_STAT
(
struct
icmpv6_mib
,
icmpv6_statistics
);
#define ICMP6_INC_STATS(field) SNMP_INC_STATS(icmpv6_statistics, field)
#define ICMP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpv6_statistics, field)
#define ICMP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpv6_statistics, field)
#define ICMP6_STATS_PTR_BH(field) \
(& \
((per_cpu_ptr(icmpv6_statistics[0], smp_processor_id()))-> \
field))
#define ICMP6_INC_STATS(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS(idev->stats.icmpv6, field); \
SNMP_INC_STATS(icmpv6_statistics, field); \
})
#define ICMP6_INC_STATS_BH(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS_BH((_idev)->stats.icmpv6, field); \
SNMP_INC_STATS_BH(icmpv6_statistics, field); \
})
#define ICMP6_INC_STATS_USER(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS_USER(_idev->stats.icmpv6, field); \
SNMP_INC_STATS_USER(icmpv6_statistics, field); \
})
#define ICMP6_INC_STATS_OFFSET_BH(idev, field, offset) ({ \
struct inet6_dev *_idev = idev; \
__typeof__(offset) _offset = (offset); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS_OFFSET_BH(_idev->stats.icmpv6, field, _offset); \
SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \
})
DECLARE_SNMP_STAT
(
struct
udp_mib
,
udp_stats_in6
);
#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field)
#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field)
#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
extern
atomic_t
inet6_sock_nr
;
int
snmp6_register_dev
(
struct
inet6_dev
*
idev
);
int
snmp6_unregister_dev
(
struct
inet6_dev
*
idev
);
int
snmp6_mib_init
(
void
*
ptr
[
2
],
size_t
mibsize
);
void
snmp6_mib_free
(
void
*
ptr
[
2
]);
struct
ip6_ra_chain
{
struct
ip6_ra_chain
*
next
;
...
...
include/net/snmp.h
View file @
cc0142de
...
...
@@ -304,6 +304,8 @@ struct linux_mib
#define SNMP_INC_STATS_BH(mib, field) \
(per_cpu_ptr(mib[0], smp_processor_id())->field++)
#define SNMP_INC_STATS_OFFSET_BH(mib, field, offset) \
((*((&per_cpu_ptr(mib[0], smp_processor_id())->field) + (offset)))++)
#define SNMP_INC_STATS_USER(mib, field) \
(per_cpu_ptr(mib[1], smp_processor_id())->field++)
#define SNMP_INC_STATS(mib, field) \
...
...
net/bridge/br_device.c
View file @
cc0142de
...
...
@@ -74,27 +74,20 @@ static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
int
br_dev_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
net_bridge
*
br
;
int
ret
;
br
=
dev
->
priv
;
read_lock
(
&
br
->
lock
);
rcu_read_lock
();
ret
=
__br_dev_xmit
(
skb
,
dev
);
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
return
ret
;
}
static
int
br_dev_open
(
struct
net_device
*
dev
)
{
struct
net_bridge
*
br
;
netif_start_queue
(
dev
);
br
=
dev
->
priv
;
write_lock
(
&
br
->
lock
);
br_stp_enable_bridge
(
br
);
write_unlock
(
&
br
->
lock
);
br_stp_enable_bridge
(
dev
->
priv
);
return
0
;
}
...
...
@@ -105,12 +98,7 @@ static void br_dev_set_multicast_list(struct net_device *dev)
static
int
br_dev_stop
(
struct
net_device
*
dev
)
{
struct
net_bridge
*
br
;
br
=
dev
->
priv
;
write_lock
(
&
br
->
lock
);
br_stp_disable_bridge
(
br
);
write_unlock
(
&
br
->
lock
);
br_stp_disable_bridge
(
dev
->
priv
);
netif_stop_queue
(
dev
);
...
...
net/bridge/br_forward.c
View file @
cc0142de
...
...
@@ -21,7 +21,8 @@
#include <linux/netfilter_bridge.h>
#include "br_private.h"
static
inline
int
should_deliver
(
struct
net_bridge_port
*
p
,
struct
sk_buff
*
skb
)
static
inline
int
should_deliver
(
const
struct
net_bridge_port
*
p
,
const
struct
sk_buff
*
skb
)
{
if
(
skb
->
dev
==
p
->
dev
||
p
->
state
!=
BR_STATE_FORWARDING
)
...
...
@@ -52,7 +53,7 @@ int br_forward_finish(struct sk_buff *skb)
return
0
;
}
static
void
__br_deliver
(
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
static
void
__br_deliver
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
{
skb
->
dev
=
to
->
dev
;
#ifdef CONFIG_NETFILTER_DEBUG
...
...
@@ -62,7 +63,7 @@ static void __br_deliver(struct net_bridge_port *to, struct sk_buff *skb)
br_forward_finish
);
}
static
void
__br_forward
(
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
static
void
__br_forward
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
{
struct
net_device
*
indev
;
...
...
@@ -73,8 +74,8 @@ static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb)
br_forward_finish
);
}
/* called
under bridge
lock */
void
br_deliver
(
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
/* called
with rcu_read_
lock */
void
br_deliver
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
{
if
(
should_deliver
(
to
,
skb
))
{
__br_deliver
(
to
,
skb
);
...
...
@@ -84,8 +85,8 @@ void br_deliver(struct net_bridge_port *to, struct sk_buff *skb)
kfree_skb
(
skb
);
}
/* called
under bridge
lock */
void
br_forward
(
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
/* called
with rcu_read_
lock */
void
br_forward
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
)
{
if
(
should_deliver
(
to
,
skb
))
{
__br_forward
(
to
,
skb
);
...
...
@@ -97,7 +98,8 @@ void br_forward(struct net_bridge_port *to, struct sk_buff *skb)
/* called under bridge lock */
static
void
br_flood
(
struct
net_bridge
*
br
,
struct
sk_buff
*
skb
,
int
clone
,
void
(
*
__packet_hook
)(
struct
net_bridge_port
*
p
,
struct
sk_buff
*
skb
))
void
(
*
__packet_hook
)(
const
struct
net_bridge_port
*
p
,
struct
sk_buff
*
skb
))
{
struct
net_bridge_port
*
p
;
struct
net_bridge_port
*
prev
;
...
...
@@ -115,8 +117,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
prev
=
NULL
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry_rcu
(
p
,
&
br
->
port_list
,
list
)
{
if
(
should_deliver
(
p
,
skb
))
{
if
(
prev
!=
NULL
)
{
struct
sk_buff
*
skb2
;
...
...
@@ -132,8 +133,6 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
prev
=
p
;
}
p
=
p
->
next
;
}
if
(
prev
!=
NULL
)
{
...
...
@@ -144,7 +143,8 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
kfree_skb
(
skb
);
}
/* called under bridge lock */
/* called with rcu_read_lock */
void
br_flood_deliver
(
struct
net_bridge
*
br
,
struct
sk_buff
*
skb
,
int
clone
)
{
br_flood
(
br
,
skb
,
clone
,
__br_deliver
);
...
...
net/bridge/br_if.c
View file @
cc0142de
...
...
@@ -18,8 +18,8 @@
#include <linux/if_bridge.h>
#include <linux/inetdevice.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/brlock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include "br_private.h"
...
...
@@ -38,45 +38,39 @@ static int br_initial_port_cost(struct net_device *dev)
return
100
;
}
/* called under BR_NETPROTO_LOCK and bridge lock */
static
int
__br_del_if
(
struct
net_bridge
*
br
,
struct
net_device
*
dev
)
static
void
destroy_nbp
(
void
*
arg
)
{
struct
net_bridge_port
*
p
;
struct
net_bridge_port
**
pptr
;
struct
net_bridge_port
*
p
=
arg
;
dev_put
(
p
->
dev
);
kfree
(
p
);
}
if
((
p
=
dev
->
br_port
)
==
NULL
)
return
-
EINVAL
;
/* called under bridge lock */
static
void
del_nbp
(
struct
net_bridge_port
*
p
)
{
struct
net_device
*
dev
=
p
->
dev
;
br_stp_disable_port
(
p
);
dev_set_promiscuity
(
dev
,
-
1
);
dev
->
br_port
=
NULL
;
pptr
=
&
br
->
port_list
;
while
(
*
pptr
!=
NULL
)
{
if
(
*
pptr
==
p
)
{
*
pptr
=
p
->
next
;
break
;
}
list_del_rcu
(
&
p
->
list
);
pptr
=
&
((
*
pptr
)
->
next
);
}
br_fdb_delete_by_port
(
p
->
br
,
p
);
br_fdb_delete_by_port
(
br
,
p
);
kfree
(
p
);
dev_put
(
dev
);
return
0
;
call_rcu
(
&
p
->
rcu
,
destroy_nbp
,
p
);
}
static
void
del_ifs
(
struct
net_bridge
*
br
)
{
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
write_lock
(
&
br
->
lock
);
while
(
br
->
port_list
!=
NULL
)
__br_del_if
(
br
,
br
->
port_list
->
dev
);
write_unlock
(
&
br
->
lock
);
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
struct
list_head
*
p
,
*
n
;
spin_lock_bh
(
&
br
->
lock
);
list_for_each_safe
(
p
,
n
,
&
br
->
port_list
)
{
del_nbp
(
list_entry
(
p
,
struct
net_bridge_port
,
list
));
}
spin_unlock_bh
(
&
br
->
lock
);
}
static
struct
net_bridge
*
new_nb
(
const
char
*
name
)
...
...
@@ -98,7 +92,8 @@ static struct net_bridge *new_nb(const char *name)
ether_setup
(
dev
);
br_dev_setup
(
dev
);
br
->
lock
=
RW_LOCK_UNLOCKED
;
br
->
lock
=
SPIN_LOCK_UNLOCKED
;
INIT_LIST_HEAD
(
&
br
->
port_list
);
br
->
hash_lock
=
RW_LOCK_UNLOCKED
;
br
->
bridge_id
.
prio
[
0
]
=
0x80
;
...
...
@@ -155,8 +150,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
br_init_port
(
p
);
p
->
state
=
BR_STATE_DISABLED
;
p
->
next
=
br
->
port_list
;
br
->
port_list
=
p
;
list_add_rcu
(
&
p
->
list
,
&
br
->
port_list
);
return
p
;
}
...
...
@@ -218,9 +212,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
return
-
ELOOP
;
dev_hold
(
dev
);
write
_lock_bh
(
&
br
->
lock
);
spin
_lock_bh
(
&
br
->
lock
);
if
((
p
=
new_nbp
(
br
,
dev
))
==
NULL
)
{
write
_unlock_bh
(
&
br
->
lock
);
spin
_unlock_bh
(
&
br
->
lock
);
dev_put
(
dev
);
return
-
EXFULL
;
}
...
...
@@ -231,21 +225,24 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
br_fdb_insert
(
br
,
p
,
dev
->
dev_addr
,
1
);
if
((
br
->
dev
.
flags
&
IFF_UP
)
&&
(
dev
->
flags
&
IFF_UP
))
br_stp_enable_port
(
p
);
write
_unlock_bh
(
&
br
->
lock
);
spin
_unlock_bh
(
&
br
->
lock
);
return
0
;
}
int
br_del_if
(
struct
net_bridge
*
br
,
struct
net_device
*
dev
)
{
int
retval
;
struct
net_bridge_port
*
p
;
int
retval
=
0
;
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
write_lock
(
&
br
->
lock
);
retval
=
__br_del_if
(
br
,
dev
);
br_stp_recalculate_bridge_id
(
br
);
write_unlock
(
&
br
->
lock
);
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
spin_lock_bh
(
&
br
->
lock
);
if
((
p
=
dev
->
br_port
)
==
NULL
||
p
->
br
!=
br
)
retval
=
-
EINVAL
;
else
{
del_nbp
(
p
);
br_stp_recalculate_bridge_id
(
br
);
}
spin_unlock_bh
(
&
br
->
lock
);
return
retval
;
}
...
...
@@ -269,13 +266,11 @@ void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
{
struct
net_bridge_port
*
p
;
read_lock
(
&
br
->
lock
);
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
rcu_read_lock
();
list_for_each_entry_rcu
(
p
,
&
br
->
port_list
,
list
)
{
ifindices
[
p
->
port_no
]
=
p
->
dev
->
ifindex
;
p
=
p
->
next
;
}
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
}
...
...
net/bridge/br_input.c
View file @
cc0142de
...
...
@@ -59,15 +59,16 @@ int br_handle_frame_finish(struct sk_buff *skb)
dest
=
skb
->
mac
.
ethernet
->
h_dest
;
rcu_read_lock
();
p
=
skb
->
dev
->
br_port
;
if
(
p
==
NULL
)
goto
err_nolock
;
smp_read_barrier_depends
();
br
=
p
->
br
;
read_lock
(
&
br
->
lock
);
if
(
skb
->
dev
->
br_port
==
NULL
)
goto
err
;
if
(
p
==
NULL
||
p
->
state
==
BR_STATE_DISABLED
)
{
kfree
(
skb
);
goto
out
;
}
br
=
p
->
br
;
passedup
=
0
;
if
(
br
->
dev
.
flags
&
IFF_PROMISC
)
{
struct
sk_buff
*
skb2
;
...
...
@@ -105,35 +106,20 @@ int br_handle_frame_finish(struct sk_buff *skb)
br_flood_forward
(
br
,
skb
,
0
);
out:
read_unlock
(
&
br
->
lock
);
return
0
;
err:
read_unlock
(
&
br
->
lock
);
err_nolock:
kfree_skb
(
skb
);
rcu_read_unlock
();
return
0
;
}
int
br_handle_frame
(
struct
sk_buff
*
skb
)
{
struct
net_bridge
*
br
;
unsigned
char
*
dest
;
struct
net_bridge_port
*
p
;
dest
=
skb
->
mac
.
ethernet
->
h_dest
;
rcu_read_lock
();
p
=
skb
->
dev
->
br_port
;
if
(
p
==
NULL
)
goto
err_nolock
;
br
=
p
->
br
;
read_lock
(
&
br
->
lock
);
if
(
skb
->
dev
->
br_port
==
NULL
)
goto
err
;
if
(
!
(
br
->
dev
.
flags
&
IFF_UP
)
||
p
->
state
==
BR_STATE_DISABLED
)
if
(
p
==
NULL
||
p
->
state
==
BR_STATE_DISABLED
)
goto
err
;
if
(
skb
->
mac
.
ethernet
->
h_source
[
0
]
&
1
)
...
...
@@ -141,39 +127,30 @@ int br_handle_frame(struct sk_buff *skb)
if
(
p
->
state
==
BR_STATE_LEARNING
||
p
->
state
==
BR_STATE_FORWARDING
)
br_fdb_insert
(
br
,
p
,
skb
->
mac
.
ethernet
->
h_source
,
0
);
br_fdb_insert
(
p
->
br
,
p
,
skb
->
mac
.
ethernet
->
h_source
,
0
);
if
(
br
->
stp_enabled
&&
if
(
p
->
br
->
stp_enabled
&&
!
memcmp
(
dest
,
bridge_ula
,
5
)
&&
!
(
dest
[
5
]
&
0xF0
))
goto
handle_special_frame
;
!
(
dest
[
5
]
&
0xF0
))
{
if
(
!
dest
[
5
])
br_stp_handle_bpdu
(
skb
);
goto
err
;
}
if
(
p
->
state
==
BR_STATE_FORWARDING
)
{
if
(
br_should_route_hook
&&
br_should_route_hook
(
&
skb
))
{
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
return
-
1
;
}
NF_HOOK
(
PF_BRIDGE
,
NF_BR_PRE_ROUTING
,
skb
,
skb
->
dev
,
NULL
,
br_handle_frame_finish
);
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
return
0
;
}
err:
read_unlock
(
&
br
->
lock
);
err_nolock:
kfree_skb
(
skb
);
return
0
;
handle_special_frame:
if
(
!
dest
[
5
])
{
br_stp_handle_bpdu
(
skb
);
read_unlock
(
&
br
->
lock
);
return
0
;
}
rcu_read_unlock
();
kfree_skb
(
skb
);
read_unlock
(
&
br
->
lock
);
return
0
;
}
net/bridge/br_ioctl.c
View file @
cc0142de
...
...
@@ -68,8 +68,8 @@ static int br_ioctl_device(struct net_bridge *br,
{
struct
__bridge_info
b
;
read_lock
(
&
br
->
lock
);
memset
(
&
b
,
0
,
sizeof
(
struct
__bridge_info
));
rcu_read_lock
();
memcpy
(
&
b
.
designated_root
,
&
br
->
designated_root
,
8
);
memcpy
(
&
b
.
bridge_id
,
&
br
->
bridge_id
,
8
);
b
.
root_path_cost
=
br
->
root_path_cost
;
...
...
@@ -89,7 +89,7 @@ static int br_ioctl_device(struct net_bridge *br,
b
.
tcn_timer_value
=
timer_residue
(
&
br
->
tcn_timer
);
b
.
topology_change_timer_value
=
timer_residue
(
&
br
->
topology_change_timer
);
b
.
gc_timer_value
=
timer_residue
(
&
br
->
gc_timer
);
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
if
(
copy_to_user
((
void
*
)
arg0
,
&
b
,
sizeof
(
b
)))
return
-
EFAULT
;
...
...
@@ -116,27 +116,27 @@ static int br_ioctl_device(struct net_bridge *br,
}
case
BRCTL_SET_BRIDGE_FORWARD_DELAY
:
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
br
->
bridge_forward_delay
=
user_to_ticks
(
arg0
);
if
(
br_is_root_bridge
(
br
))
br
->
forward_delay
=
br
->
bridge_forward_delay
;
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
0
;
case
BRCTL_SET_BRIDGE_HELLO_TIME
:
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
br
->
bridge_hello_time
=
user_to_ticks
(
arg0
);
if
(
br_is_root_bridge
(
br
))
br
->
hello_time
=
br
->
bridge_hello_time
;
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
0
;
case
BRCTL_SET_BRIDGE_MAX_AGE
:
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
br
->
bridge_max_age
=
user_to_ticks
(
arg0
);
if
(
br_is_root_bridge
(
br
))
br
->
max_age
=
br
->
bridge_max_age
;
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
0
;
case
BRCTL_SET_AGEING_TIME
:
...
...
@@ -152,9 +152,9 @@ static int br_ioctl_device(struct net_bridge *br,
struct
__port_info
p
;
struct
net_bridge_port
*
pt
;
r
ead_lock
(
&
br
->
lock
);
r
cu_read_lock
(
);
if
((
pt
=
br_get_port
(
br
,
arg1
))
==
NULL
)
{
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
return
-
EINVAL
;
}
...
...
@@ -172,7 +172,7 @@ static int br_ioctl_device(struct net_bridge *br,
p
.
forward_delay_timer_value
=
timer_residue
(
&
pt
->
forward_delay_timer
);
p
.
hold_timer_value
=
timer_residue
(
&
pt
->
hold_timer
);
r
ead_unlock
(
&
br
->
lock
);
r
cu_read_unlock
(
);
if
(
copy_to_user
((
void
*
)
arg0
,
&
p
,
sizeof
(
p
)))
return
-
EFAULT
;
...
...
@@ -185,9 +185,9 @@ static int br_ioctl_device(struct net_bridge *br,
return
0
;
case
BRCTL_SET_BRIDGE_PRIORITY
:
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
br_stp_set_bridge_priority
(
br
,
arg0
);
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
0
;
case
BRCTL_SET_PORT_PRIORITY
:
...
...
@@ -195,12 +195,12 @@ static int br_ioctl_device(struct net_bridge *br,
struct
net_bridge_port
*
p
;
int
ret
=
0
;
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
if
((
p
=
br_get_port
(
br
,
arg0
))
==
NULL
)
ret
=
-
EINVAL
;
else
br_stp_set_port_priority
(
p
,
arg1
);
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
ret
;
}
...
...
@@ -209,12 +209,12 @@ static int br_ioctl_device(struct net_bridge *br,
struct
net_bridge_port
*
p
;
int
ret
=
0
;
write_lock
(
&
br
->
lock
);
spin_lock_bh
(
&
br
->
lock
);
if
((
p
=
br_get_port
(
br
,
arg0
))
==
NULL
)
ret
=
-
EINVAL
;
else
br_stp_set_path_cost
(
p
,
arg1
);
write_unlock
(
&
br
->
lock
);
spin_unlock_bh
(
&
br
->
lock
);
return
ret
;
}
...
...
net/bridge/br_notify.c
View file @
cc0142de
...
...
@@ -41,10 +41,10 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
switch
(
event
)
{
case
NETDEV_CHANGEADDR
:
write
_lock_bh
(
&
br
->
lock
);
spin
_lock_bh
(
&
br
->
lock
);
br_fdb_changeaddr
(
p
,
dev
->
dev_addr
);
br_stp_recalculate_bridge_id
(
br
);
write
_unlock_bh
(
&
br
->
lock
);
spin
_unlock_bh
(
&
br
->
lock
);
break
;
case
NETDEV_GOING_DOWN
:
...
...
@@ -53,17 +53,17 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
case
NETDEV_DOWN
:
if
(
br
->
dev
.
flags
&
IFF_UP
)
{
write
_lock_bh
(
&
br
->
lock
);
spin
_lock_bh
(
&
br
->
lock
);
br_stp_disable_port
(
p
);
write
_unlock_bh
(
&
br
->
lock
);
spin
_unlock_bh
(
&
br
->
lock
);
}
break
;
case
NETDEV_UP
:
if
(
!
(
br
->
dev
.
flags
&
IFF_UP
))
{
write
_lock_bh
(
&
br
->
lock
);
spin
_lock_bh
(
&
br
->
lock
);
br_stp_enable_port
(
p
);
write
_unlock_bh
(
&
br
->
lock
);
spin
_unlock_bh
(
&
br
->
lock
);
}
break
;
...
...
net/bridge/br_private.h
View file @
cc0142de
...
...
@@ -55,9 +55,9 @@ struct net_bridge_fdb_entry
struct
net_bridge_port
{
struct
net_bridge_port
*
next
;
struct
net_bridge
*
br
;
struct
net_device
*
dev
;
struct
list_head
list
;
int
port_no
;
/* STP */
...
...
@@ -75,12 +75,14 @@ struct net_bridge_port
struct
br_timer
forward_delay_timer
;
struct
br_timer
hold_timer
;
struct
br_timer
message_age_timer
;
struct
rcu_head
rcu
;
};
struct
net_bridge
{
rw
lock_t
lock
;
struct
net_bridge_port
*
port_list
;
spin
lock_t
lock
;
struct
list_head
port_list
;
struct
net_device
dev
;
struct
net_device_stats
statistics
;
rwlock_t
hash_lock
;
...
...
@@ -137,10 +139,10 @@ extern void br_fdb_insert(struct net_bridge *br,
int
is_local
);
/* br_forward.c */
extern
void
br_deliver
(
struct
net_bridge_port
*
to
,
extern
void
br_deliver
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
);
extern
int
br_dev_queue_push_xmit
(
struct
sk_buff
*
skb
);
extern
void
br_forward
(
struct
net_bridge_port
*
to
,
extern
void
br_forward
(
const
struct
net_bridge_port
*
to
,
struct
sk_buff
*
skb
);
extern
int
br_forward_finish
(
struct
sk_buff
*
skb
);
extern
void
br_flood_deliver
(
struct
net_bridge
*
br
,
...
...
net/bridge/br_stp.c
View file @
cc0142de
...
...
@@ -22,7 +22,7 @@
/* called under
ioctl_lock or
bridge lock */
/* called under bridge lock */
int
br_is_root_bridge
(
struct
net_bridge
*
br
)
{
return
!
memcmp
(
&
br
->
bridge_id
,
&
br
->
designated_root
,
8
);
...
...
@@ -35,17 +35,14 @@ int br_is_designated_port(struct net_bridge_port *p)
(
p
->
designated_port
==
p
->
port_id
);
}
/* called under
ioctl_lock or
bridge lock */
/* called under bridge lock */
struct
net_bridge_port
*
br_get_port
(
struct
net_bridge
*
br
,
int
port_no
)
{
struct
net_bridge_port
*
p
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
port_no
==
port_no
)
return
p
;
p
=
p
->
next
;
}
return
NULL
;
...
...
@@ -109,12 +106,10 @@ static void br_root_selection(struct net_bridge *br)
root_port
=
0
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
br_should_become_root_port
(
p
,
root_port
))
root_port
=
p
->
port_no
;
p
=
p
->
next
;
}
br
->
root_port
=
root_port
;
...
...
@@ -241,13 +236,11 @@ static void br_designated_port_selection(struct net_bridge *br)
{
struct
net_bridge_port
*
p
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
&&
br_should_become_designated_port
(
p
))
br_become_designated_port
(
p
);
p
=
p
->
next
;
}
}
...
...
@@ -313,13 +306,10 @@ void br_config_bpdu_generation(struct net_bridge *br)
{
struct
net_bridge_port
*
p
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
&&
br_is_designated_port
(
p
))
br_transmit_config
(
p
);
p
=
p
->
next
;
}
}
...
...
@@ -391,8 +381,7 @@ void br_port_state_selection(struct net_bridge *br)
{
struct
net_bridge_port
*
p
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
)
{
if
(
p
->
port_no
==
br
->
root_port
)
{
p
->
config_pending
=
0
;
...
...
@@ -407,8 +396,6 @@ void br_port_state_selection(struct net_bridge *br)
br_make_blocking
(
p
);
}
}
p
=
p
->
next
;
}
}
...
...
@@ -419,18 +406,13 @@ static void br_topology_change_acknowledge(struct net_bridge_port *p)
br_transmit_config
(
p
);
}
/*
lock-safe
*/
/*
called under bridge lock
*/
void
br_received_config_bpdu
(
struct
net_bridge_port
*
p
,
struct
br_config_bpdu
*
bpdu
)
{
struct
net_bridge
*
br
;
int
was_root
;
if
(
p
->
state
==
BR_STATE_DISABLED
)
return
;
br
=
p
->
br
;
read_lock
(
&
br
->
lock
);
was_root
=
br_is_root_bridge
(
br
);
if
(
br_supersedes_port_info
(
p
,
bpdu
))
{
br_record_config_information
(
p
,
bpdu
);
...
...
@@ -455,21 +437,16 @@ void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *b
}
else
if
(
br_is_designated_port
(
p
))
{
br_reply
(
p
);
}
read_unlock
(
&
br
->
lock
);
}
/*
lock-safe
*/
/*
called under bridge lock
*/
void
br_received_tcn_bpdu
(
struct
net_bridge_port
*
p
)
{
read_lock
(
&
p
->
br
->
lock
);
if
(
p
->
state
!=
BR_STATE_DISABLED
&&
br_is_designated_port
(
p
))
{
if
(
br_is_designated_port
(
p
))
{
printk
(
KERN_INFO
"%s: received tcn bpdu on port %i(%s)
\n
"
,
p
->
br
->
dev
.
name
,
p
->
port_no
,
p
->
dev
->
name
);
br_topology_change_detection
(
p
->
br
);
br_topology_change_acknowledge
(
p
);
}
read_unlock
(
&
p
->
br
->
lock
);
}
net/bridge/br_stp_bpdu.c
View file @
cc0142de
...
...
@@ -132,18 +132,23 @@ void br_send_tcn_bpdu(struct net_bridge_port *p)
static
unsigned
char
header
[
6
]
=
{
0x42
,
0x42
,
0x03
,
0x00
,
0x00
,
0x00
};
/*
called under bridge lock
*/
/*
NO locks
*/
void
br_stp_handle_bpdu
(
struct
sk_buff
*
skb
)
{
unsigned
char
*
buf
;
struct
net_bridge_port
*
p
;
struct
net_bridge
*
br
;
buf
=
skb
->
mac
.
raw
+
14
;
p
=
skb
->
dev
->
br_port
;
if
(
!
p
->
br
->
stp_enabled
||
memcmp
(
buf
,
header
,
6
))
{
kfree_skb
(
skb
);
return
;
}
br
=
p
->
br
;
spin_lock_bh
(
&
br
->
lock
);
if
(
p
->
state
==
BR_STATE_DISABLED
||
!
(
br
->
dev
.
flags
&
IFF_UP
)
||
!
br
->
stp_enabled
||
memcmp
(
buf
,
header
,
6
))
goto
out
;
if
(
buf
[
6
]
==
BPDU_TYPE_CONFIG
)
{
struct
br_config_bpdu
bpdu
;
...
...
@@ -178,16 +183,14 @@ void br_stp_handle_bpdu(struct sk_buff *skb)
bpdu
.
hello_time
=
br_get_ticks
(
buf
+
34
);
bpdu
.
forward_delay
=
br_get_ticks
(
buf
+
36
);
kfree_skb
(
skb
);
br_received_config_bpdu
(
p
,
&
bpdu
);
return
;
goto
out
;
}
if
(
buf
[
6
]
==
BPDU_TYPE_TCN
)
{
br_received_tcn_bpdu
(
p
);
kfree_skb
(
skb
);
return
;
goto
out
;
}
kfree_skb
(
skb
);
out:
spin_unlock_bh
(
&
br
->
lock
);
}
net/bridge/br_stp_if.c
View file @
cc0142de
...
...
@@ -44,6 +44,7 @@ void br_stp_enable_bridge(struct net_bridge *br)
struct
net_bridge_port
*
p
;
struct
timer_list
*
timer
=
&
br
->
tick
;
spin_lock_bh
(
&
br
->
lock
);
init_timer
(
timer
);
timer
->
data
=
(
unsigned
long
)
br
;
timer
->
function
=
br_tick
;
...
...
@@ -53,22 +54,21 @@ void br_stp_enable_bridge(struct net_bridge *br)
br_timer_set
(
&
br
->
hello_timer
,
jiffies
);
br_config_bpdu_generation
(
br
);
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
dev
->
flags
&
IFF_UP
)
br_stp_enable_port
(
p
);
p
=
p
->
next
;
}
br_timer_set
(
&
br
->
gc_timer
,
jiffies
);
spin_unlock_bh
(
&
br
->
lock
);
}
/*
called under bridge lock
*/
/*
NO locks held
*/
void
br_stp_disable_bridge
(
struct
net_bridge
*
br
)
{
struct
net_bridge_port
*
p
;
spin_lock_bh
(
&
br
->
lock
);
br
->
topology_change
=
0
;
br
->
topology_change_detected
=
0
;
br_timer_clear
(
&
br
->
hello_timer
);
...
...
@@ -77,13 +77,11 @@ void br_stp_disable_bridge(struct net_bridge *br)
br_timer_clear
(
&
br
->
gc_timer
);
br_fdb_cleanup
(
br
);
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
)
br_stp_disable_port
(
p
);
p
=
p
->
next
;
}
spin_unlock_bh
(
&
br
->
lock
);
del_timer_sync
(
&
br
->
tick
);
}
...
...
@@ -133,15 +131,13 @@ static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
memcpy
(
br
->
bridge_id
.
addr
,
addr
,
ETH_ALEN
);
memcpy
(
br
->
dev
.
dev_addr
,
addr
,
ETH_ALEN
);
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
!
memcmp
(
p
->
designated_bridge
.
addr
,
oldaddr
,
ETH_ALEN
))
memcpy
(
p
->
designated_bridge
.
addr
,
addr
,
ETH_ALEN
);
if
(
!
memcmp
(
p
->
designated_root
.
addr
,
oldaddr
,
ETH_ALEN
))
memcpy
(
p
->
designated_root
.
addr
,
addr
,
ETH_ALEN
);
p
=
p
->
next
;
}
br_configuration_update
(
br
);
...
...
@@ -160,13 +156,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
addr
=
br_mac_zero
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
addr
==
br_mac_zero
||
memcmp
(
p
->
dev
->
dev_addr
,
addr
,
ETH_ALEN
)
<
0
)
addr
=
p
->
dev
->
dev_addr
;
p
=
p
->
next
;
}
if
(
memcmp
(
br
->
bridge_id
.
addr
,
addr
,
ETH_ALEN
))
...
...
@@ -181,15 +175,13 @@ void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
wasroot
=
br_is_root_bridge
(
br
);
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
&&
br_is_designated_port
(
p
))
{
p
->
designated_bridge
.
prio
[
0
]
=
(
newprio
>>
8
)
&
0xFF
;
p
->
designated_bridge
.
prio
[
1
]
=
newprio
&
0xFF
;
}
p
=
p
->
next
;
}
br
->
bridge_id
.
prio
[
0
]
=
(
newprio
>>
8
)
&
0xFF
;
...
...
net/bridge/br_stp_timer.c
View file @
cc0142de
...
...
@@ -32,13 +32,10 @@ static int br_is_designated_for_some_port(struct net_bridge *br)
{
struct
net_bridge_port
*
p
;
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
&&
!
memcmp
(
&
p
->
designated_bridge
,
&
br
->
bridge_id
,
8
))
return
1
;
p
=
p
->
next
;
}
return
0
;
...
...
@@ -162,12 +159,9 @@ static void br_check_timers(struct net_bridge *br)
br_topology_change_timer_expired
(
br
);
}
p
=
br
->
port_list
;
while
(
p
!=
NULL
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
p
->
state
!=
BR_STATE_DISABLED
)
br_check_port_timers
(
p
);
p
=
p
->
next
;
}
}
...
...
@@ -175,10 +169,10 @@ void br_tick(unsigned long __data)
{
struct
net_bridge
*
br
=
(
struct
net_bridge
*
)
__data
;
read_lock
(
&
br
->
lock
);
br_check_timers
(
br
);
read_unlock
(
&
br
->
lock
);
if
(
spin_trylock_bh
(
&
br
->
lock
))
{
br_check_timers
(
br
);
spin_unlock_bh
(
&
br
->
lock
);
}
br
->
tick
.
expires
=
jiffies
+
1
;
add_timer
(
&
br
->
tick
);
}
net/ipv6/addrconf.c
View file @
cc0142de
...
...
@@ -300,6 +300,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
printk
(
"Freeing alive inet6 device %p
\n
"
,
idev
);
return
;
}
snmp6_unregister_dev
(
idev
);
inet6_dev_count
--
;
kfree
(
idev
);
}
...
...
@@ -332,6 +333,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* We refer to the device */
dev_hold
(
dev
);
if
(
snmp6_register_dev
(
ndev
)
<
0
)
{
ADBG
((
KERN_WARNING
"%s(): cannot create /proc/net/dev_snmp6/%s
\n
"
,
__FUNCTION__
,
dev
->
name
));
neigh_parms_release
(
&
nd_tbl
,
ndev
->
nd_parms
);
in6_dev_finish_destroy
(
ndev
);
return
NULL
;
}
#ifdef CONFIG_IPV6_PRIVACY
get_random_bytes
(
ndev
->
rndid
,
sizeof
(
ndev
->
rndid
));
get_random_bytes
(
ndev
->
entropy
,
sizeof
(
ndev
->
entropy
));
...
...
net/ipv6/af_inet6.c
View file @
cc0142de
...
...
@@ -631,79 +631,72 @@ inet6_unregister_protosw(struct inet_protosw *p)
inet_unregister_protosw
(
p
);
}
static
int
__init
init_ipv6_mibs
(
void
)
int
snmp6_mib_init
(
void
*
ptr
[
2
],
size_t
mibsize
)
{
int
i
;
ipv6_statistics
[
0
]
=
kmalloc_percpu
(
sizeof
(
struct
ipv6_mib
),
GFP_KERNEL
);
if
(
!
ipv6_statistics
[
0
])
goto
err_ip_mib0
;
ipv6_statistics
[
1
]
=
kmalloc_percpu
(
sizeof
(
struct
ipv6_mib
),
GFP_KERNEL
);
if
(
!
ipv6_statistics
[
1
])
goto
err_ip_mib1
;
icmpv6_statistics
[
0
]
=
kmalloc_percpu
(
sizeof
(
struct
icmpv6_mib
),
GFP_KERNEL
);
if
(
!
icmpv6_statistics
[
0
])
goto
err_icmp_mib0
;
icmpv6_statistics
[
1
]
=
kmalloc_percpu
(
sizeof
(
struct
icmpv6_mib
),
GFP_KERNEL
);
if
(
!
icmpv6_statistics
[
1
])
goto
err_icmp_mib1
;
udp_stats_in6
[
0
]
=
kmalloc_percpu
(
sizeof
(
struct
udp_mib
),
GFP_KERNEL
);
if
(
!
udp_stats_in6
[
0
])
goto
err_udp_mib0
;
udp_stats_in6
[
1
]
=
kmalloc_percpu
(
sizeof
(
struct
udp_mib
),
GFP_KERNEL
);
if
(
!
udp_stats_in6
[
1
])
goto
err_udp_mib1
;
/* Zero all percpu versions of the mibs */
if
(
ptr
==
NULL
)
return
-
EINVAL
;
ptr
[
0
]
=
kmalloc_percpu
(
mibsize
,
GFP_KERNEL
);
if
(
!
ptr
[
0
])
goto
err0
;
ptr
[
1
]
=
kmalloc_percpu
(
mibsize
,
GFP_KERNEL
);
if
(
!
ptr
[
1
])
goto
err1
;
/* Zero percpu version of the mibs */
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
cpu_possible
(
i
))
{
memset
(
per_cpu_ptr
(
ipv6_statistics
[
0
],
i
),
0
,
sizeof
(
struct
ipv6_mib
));
memset
(
per_cpu_ptr
(
ipv6_statistics
[
1
],
i
),
0
,
sizeof
(
struct
ipv6_mib
));
memset
(
per_cpu_ptr
(
icmpv6_statistics
[
0
],
i
),
0
,
sizeof
(
struct
icmpv6_mib
));
memset
(
per_cpu_ptr
(
icmpv6_statistics
[
1
],
i
),
0
,
sizeof
(
struct
icmpv6_mib
));
memset
(
per_cpu_ptr
(
udp_stats_in6
[
0
],
i
),
0
,
sizeof
(
struct
udp_mib
));
memset
(
per_cpu_ptr
(
udp_stats_in6
[
1
],
i
),
0
,
sizeof
(
struct
udp_mib
));
memset
(
per_cpu_ptr
(
ptr
[
0
],
i
),
0
,
mibsize
);
memset
(
per_cpu_ptr
(
ptr
[
1
],
i
),
0
,
mibsize
);
}
}
return
0
;
err_udp_mib1:
kfree_percpu
(
udp_stats_in6
[
0
]);
err_udp_mib0:
kfree_percpu
(
icmpv6_statistics
[
1
]);
err_icmp_mib1:
kfree_percpu
(
icmpv6_statistics
[
0
]);
err_icmp_mib0:
kfree_percpu
(
ipv6_statistics
[
1
]);
err_ip_mib1:
kfree_percpu
(
ipv6_statistics
[
0
]);
err_ip_mib0:
err1:
kfree_percpu
(
ptr
[
0
]);
ptr
[
0
]
=
NULL
;
err0:
return
-
ENOMEM
;
}
void
snmp6_mib_free
(
void
*
ptr
[
2
])
{
if
(
ptr
==
NULL
)
return
;
kfree_percpu
(
ptr
[
0
]);
kfree_percpu
(
ptr
[
1
]);
ptr
[
0
]
=
ptr
[
1
]
=
NULL
;
}
static
int
__init
init_ipv6_mibs
(
void
)
{
if
(
snmp6_mib_init
((
void
**
)
ipv6_statistics
,
sizeof
(
struct
ipv6_mib
))
<
0
)
goto
err_ip_mib
;
if
(
snmp6_mib_init
((
void
**
)
icmpv6_statistics
,
sizeof
(
struct
icmpv6_mib
))
<
0
)
goto
err_icmp_mib
;
if
(
snmp6_mib_init
((
void
**
)
udp_stats_in6
,
sizeof
(
struct
udp_mib
))
<
0
)
goto
err_udp_mib
;
return
0
;
err_udp_mib:
snmp6_mib_free
((
void
**
)
icmpv6_statistics
);
err_icmp_mib:
snmp6_mib_free
((
void
**
)
ipv6_statistics
);
err_ip_mib:
return
-
ENOMEM
;
}
static
void
cleanup_ipv6_mibs
(
void
)
{
kfree_percpu
(
ipv6_statistics
[
0
]);
kfree_percpu
(
ipv6_statistics
[
1
]);
kfree_percpu
(
icmpv6_statistics
[
0
]);
kfree_percpu
(
icmpv6_statistics
[
1
]);
kfree_percpu
(
udp_stats_in6
[
0
]);
kfree_percpu
(
udp_stats_in6
[
1
]);
snmp6_mib_free
((
void
**
)
ipv6_statistics
);
snmp6_mib_free
((
void
**
)
icmpv6_statistics
);
snmp6_mib_free
((
void
**
)
udp_stats_in6
);
}
extern
int
ipv6_misc_proc_init
(
void
);
...
...
@@ -819,6 +812,7 @@ static int __init inet6_init(void)
#ifdef CONFIG_PROC_FS
proc_anycast6_fail:
proc_net_remove
(
"snmp6"
);
proc_net_remove
(
"dev_snmp6"
);
proc_net_remove
(
"sockstat6"
);
proc_misc6_fail:
proc_net_remove
(
"udp6"
);
...
...
@@ -854,6 +848,7 @@ static void inet6_exit(void)
proc_net_remove
(
"tcp6"
);
proc_net_remove
(
"udp6"
);
proc_net_remove
(
"sockstat6"
);
proc_net_remove
(
"dev_snmp6"
);
proc_net_remove
(
"snmp6"
);
proc_net_remove
(
"anycast6"
);
#endif
...
...
net/ipv6/icmp.c
View file @
cc0142de
...
...
@@ -26,6 +26,8 @@
* yoshfuji : ensure to sent parameter problem for
* fragments.
* YOSHIFUJI Hideaki @USAGI: added sysctl for icmp rate limit.
* Randy Dunlap and
* YOSHIFUJI Hideaki @USAGI: Per-interface statistics support
*/
#include <linux/module.h>
...
...
@@ -247,6 +249,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
void
icmpv6_send
(
struct
sk_buff
*
skb
,
int
type
,
int
code
,
__u32
info
,
struct
net_device
*
dev
)
{
struct
inet6_dev
*
idev
;
struct
ipv6hdr
*
hdr
=
skb
->
nh
.
ipv6h
;
struct
sock
*
sk
=
icmpv6_socket
->
sk
;
struct
in6_addr
*
saddr
=
NULL
;
...
...
@@ -351,11 +354,16 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
msg
.
len
=
len
;
idev
=
in6_dev_get
(
skb
->
dev
);
ip6_build_xmit
(
sk
,
icmpv6_getfrag
,
&
msg
,
&
fl
,
len
,
NULL
,
-
1
,
MSG_DONTWAIT
);
if
(
type
>=
ICMPV6_DEST_UNREACH
&&
type
<=
ICMPV6_PARAMPROB
)
ICMP6_STATS_PTR_BH
(
Icmp6OutDestUnreachs
)
[
type
-
ICMPV6_DEST_UNREACH
]
++
;
ICMP6_INC_STATS_BH
(
Icmp6OutMsgs
);
ICMP6_INC_STATS_OFFSET_BH
(
idev
,
Icmp6OutDestUnreachs
,
type
-
ICMPV6_DEST_UNREACH
);
ICMP6_INC_STATS_BH
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
out:
icmpv6_xmit_unlock
();
}
...
...
@@ -363,6 +371,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
static
void
icmpv6_echo_reply
(
struct
sk_buff
*
skb
)
{
struct
sock
*
sk
=
icmpv6_socket
->
sk
;
struct
inet6_dev
*
idev
;
struct
icmp6hdr
*
icmph
=
(
struct
icmp6hdr
*
)
skb
->
h
.
raw
;
struct
in6_addr
*
saddr
;
struct
icmpv6_msg
msg
;
...
...
@@ -394,14 +403,19 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
fl
.
fl_icmp_type
=
ICMPV6_ECHO_REPLY
;
fl
.
fl_icmp_code
=
0
;
idev
=
in6_dev_get
(
skb
->
dev
);
icmpv6_xmit_lock
();
ip6_build_xmit
(
sk
,
icmpv6_getfrag
,
&
msg
,
&
fl
,
msg
.
len
,
NULL
,
-
1
,
MSG_DONTWAIT
);
ICMP6_INC_STATS_BH
(
Icmp6OutEchoReplies
);
ICMP6_INC_STATS_BH
(
Icmp6OutMsgs
);
ICMP6_INC_STATS_BH
(
idev
,
Icmp6OutEchoReplies
);
ICMP6_INC_STATS_BH
(
idev
,
Icmp6OutMsgs
);
icmpv6_xmit_unlock
();
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
static
void
icmpv6_notify
(
struct
sk_buff
*
skb
,
int
type
,
int
code
,
u32
info
)
...
...
@@ -464,12 +478,13 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
inet6_dev
*
idev
=
__in6_dev_get
(
dev
);
struct
in6_addr
*
saddr
,
*
daddr
;
struct
ipv6hdr
*
orig_hdr
;
struct
icmp6hdr
*
hdr
;
int
type
;
ICMP6_INC_STATS_BH
(
Icmp6InMsgs
);
ICMP6_INC_STATS_BH
(
idev
,
Icmp6InMsgs
);
saddr
=
&
skb
->
nh
.
ipv6h
->
saddr
;
daddr
=
&
skb
->
nh
.
ipv6h
->
daddr
;
...
...
@@ -517,9 +532,9 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
type
=
hdr
->
icmp6_type
;
if
(
type
>=
ICMPV6_DEST_UNREACH
&&
type
<=
ICMPV6_PARAMPROB
)
ICMP6_
STATS_PTR_BH
(
Icmp6InDestUnreachs
)[
type
-
ICMPV6_DEST_UNREACH
]
++
;
ICMP6_
INC_STATS_OFFSET_BH
(
idev
,
Icmp6InDestUnreachs
,
type
-
ICMPV6_DEST_UNREACH
)
;
else
if
(
type
>=
ICMPV6_ECHO_REQUEST
&&
type
<=
NDISC_REDIRECT
)
ICMP6_
STATS_PTR_BH
(
Icmp6InEchos
)[
type
-
ICMPV6_ECHO_REQUEST
]
++
;
ICMP6_
INC_STATS_OFFSET_BH
(
idev
,
Icmp6InEchos
,
type
-
ICMPV6_ECHO_REQUEST
)
;
switch
(
type
)
{
case
ICMPV6_ECHO_REQUEST
:
...
...
@@ -597,7 +612,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
return
0
;
discard_it:
ICMP6_INC_STATS_BH
(
Icmp6InErrors
);
ICMP6_INC_STATS_BH
(
idev
,
Icmp6InErrors
);
kfree_skb
(
skb
);
return
0
;
}
...
...
net/ipv6/ipv6_syms.c
View file @
cc0142de
...
...
@@ -34,5 +34,6 @@ EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL
(
ipv6_chk_addr
);
EXPORT_SYMBOL
(
in6addr_any
);
EXPORT_SYMBOL
(
in6addr_loopback
);
EXPORT_SYMBOL
(
in6_dev_finish_destroy
);
EXPORT_SYMBOL
(
xfrm6_rcv
);
EXPORT_SYMBOL
(
xfrm6_clear_mutable_options
);
net/ipv6/mcast.c
View file @
cc0142de
...
...
@@ -1253,6 +1253,7 @@ static void mld_sendpack(struct sk_buff *skb)
struct
ipv6hdr
*
pip6
=
skb
->
nh
.
ipv6h
;
struct
mld2_report
*
pmr
=
(
struct
mld2_report
*
)
skb
->
h
.
raw
;
int
payload_len
,
mldlen
;
struct
inet6_dev
*
idev
=
in6_dev_get
(
skb
->
dev
);
payload_len
=
skb
->
tail
-
(
unsigned
char
*
)
skb
->
nh
.
ipv6h
-
sizeof
(
struct
ipv6hdr
);
...
...
@@ -1262,7 +1263,9 @@ static void mld_sendpack(struct sk_buff *skb)
pmr
->
csum
=
csum_ipv6_magic
(
&
pip6
->
saddr
,
&
pip6
->
daddr
,
mldlen
,
IPPROTO_ICMPV6
,
csum_partial
(
skb
->
h
.
raw
,
mldlen
,
0
));
dev_queue_xmit
(
skb
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
static
int
grec_size
(
struct
ifmcaddr6
*
pmc
,
int
type
,
int
gdel
,
int
sdel
)
...
...
@@ -1520,6 +1523,7 @@ static void mld_send_cr(struct inet6_dev *idev)
static
void
igmp6_send
(
struct
in6_addr
*
addr
,
struct
net_device
*
dev
,
int
type
)
{
struct
sock
*
sk
=
igmp6_socket
->
sk
;
struct
inet6_dev
*
idev
;
struct
sk_buff
*
skb
;
struct
icmp6hdr
*
hdr
;
struct
in6_addr
*
snd_addr
;
...
...
@@ -1577,12 +1581,17 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
IPPROTO_ICMPV6
,
csum_partial
((
__u8
*
)
hdr
,
len
,
0
));
idev
=
in6_dev_get
(
skb
->
dev
);
dev_queue_xmit
(
skb
);
if
(
type
==
ICMPV6_MGM_REDUCTION
)
ICMP6_INC_STATS
(
Icmp6OutGroupMembReductions
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutGroupMembReductions
);
else
ICMP6_INC_STATS
(
Icmp6OutGroupMembResponses
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutGroupMembResponses
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
return
;
out:
...
...
net/ipv6/ndisc.c
View file @
cc0142de
...
...
@@ -415,6 +415,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
{
static
struct
in6_addr
tmpaddr
;
struct
inet6_ifaddr
*
ifp
;
struct
inet6_dev
*
idev
;
struct
flowi
fl
;
struct
rt6_info
*
rt
=
NULL
;
struct
dst_entry
*
dst
;
...
...
@@ -497,10 +498,14 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
dst_clone
(
dst
);
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
ICMP6_INC_STATS
(
Icmp6OutNeighborAdvertisements
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutNeighborAdvertisements
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
void
ndisc_send_ns
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
,
...
...
@@ -510,6 +515,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
struct
flowi
fl
;
struct
rt6_info
*
rt
=
NULL
;
struct
dst_entry
*
dst
;
struct
inet6_dev
*
idev
;
struct
sock
*
sk
=
ndisc_socket
->
sk
;
struct
sk_buff
*
skb
;
struct
nd_msg
*
msg
;
...
...
@@ -576,10 +582,14 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
/* send it! */
dst_clone
(
dst
);
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
ICMP6_INC_STATS
(
Icmp6OutNeighborSolicits
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutNeighborSolicits
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
void
ndisc_send_rs
(
struct
net_device
*
dev
,
struct
in6_addr
*
saddr
,
...
...
@@ -588,6 +598,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
struct
flowi
fl
;
struct
rt6_info
*
rt
=
NULL
;
struct
dst_entry
*
dst
;
struct
inet6_dev
*
idev
;
struct
sock
*
sk
=
ndisc_socket
->
sk
;
struct
sk_buff
*
skb
;
struct
icmp6hdr
*
hdr
;
...
...
@@ -644,10 +655,14 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
/* send it! */
dst_clone
(
dst
);
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
ICMP6_INC_STATS
(
Icmp6OutRouterSolicits
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutRouterSolicits
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
...
...
@@ -1271,6 +1286,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
struct
net_device
*
dev
;
struct
rt6_info
*
rt
;
struct
dst_entry
*
dst
;
struct
inet6_dev
*
idev
;
struct
flowi
fl
;
u8
*
opt
;
int
rd_len
;
...
...
@@ -1379,10 +1395,14 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
csum_partial
((
u8
*
)
icmph
,
len
,
0
));
skb
->
dst
=
dst
;
idev
=
in6_dev_get
(
dst
->
dev
);
dst_output
(
skb
);
ICMP6_INC_STATS
(
Icmp6OutRedirects
);
ICMP6_INC_STATS
(
Icmp6OutMsgs
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutRedirects
);
ICMP6_INC_STATS
(
idev
,
Icmp6OutMsgs
);
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
static
void
pndisc_redo
(
struct
sk_buff
*
skb
)
...
...
net/ipv6/proc.c
View file @
cc0142de
...
...
@@ -10,12 +10,14 @@
* Version: $Id: proc.c,v 1.17 2002/02/01 22:01:04 davem Exp $
*
* Authors: David S. Miller (davem@caip.rutgers.edu)
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/net.h>
...
...
@@ -28,6 +30,10 @@
#include <net/transp_v6.h>
#include <net/ipv6.h>
#ifdef CONFIG_PROC_FS
static
struct
proc_dir_entry
*
proc_net_devsnmp6
;
#endif
static
int
fold_prot_inuse
(
struct
proto
*
proto
)
{
int
res
=
0
;
...
...
@@ -53,14 +59,16 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
}
st
atic
st
ruct
snmp6_item
struct
snmp6_item
{
char
*
name
;
void
**
mib
;
int
offset
;
}
snmp6_list
[]
=
{
};
#define SNMP6_SENTINEL { .name = NULL, .offset = 0 }
static
struct
snmp6_item
snmp6_ipv6_list
[]
=
{
/* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */
#define SNMP6_GEN(x) {
#x , (void **)ipv6_statistics,
offsetof(struct ipv6_mib, x) }
#define SNMP6_GEN(x) {
.name = #x , .offset =
offsetof(struct ipv6_mib, x) }
SNMP6_GEN
(
Ip6InReceives
),
SNMP6_GEN
(
Ip6InHdrErrors
),
SNMP6_GEN
(
Ip6InTooBigErrors
),
...
...
@@ -84,6 +92,10 @@ static struct snmp6_item
SNMP6_GEN
(
Ip6InMcastPkts
),
SNMP6_GEN
(
Ip6OutMcastPkts
),
#undef SNMP6_GEN
SNMP6_SENTINEL
};
static
struct
snmp6_item
snmp6_icmp6_list
[]
=
{
/* icmpv6 mib according to draft-ietf-ipngwg-ipv6-icmp-mib-02
Exceptions: {In|Out}AdminProhibs are removed, because I see
...
...
@@ -94,7 +106,7 @@ static struct snmp6_item
OutRouterAdvertisements too.
OutGroupMembQueries too.
*/
#define SNMP6_GEN(x) {
#x , (void **)icmpv6_statistics,
offsetof(struct icmpv6_mib, x) }
#define SNMP6_GEN(x) {
.name = #x , .offset =
offsetof(struct icmpv6_mib, x) }
SNMP6_GEN
(
Icmp6InMsgs
),
SNMP6_GEN
(
Icmp6InErrors
),
SNMP6_GEN
(
Icmp6InDestUnreachs
),
...
...
@@ -124,12 +136,17 @@ static struct snmp6_item
SNMP6_GEN
(
Icmp6OutGroupMembResponses
),
SNMP6_GEN
(
Icmp6OutGroupMembReductions
),
#undef SNMP6_GEN
#define SNMP6_GEN(x) { "Udp6" #x , (void **)udp_stats_in6, offsetof(struct udp_mib, Udp##x) }
SNMP6_SENTINEL
};
static
struct
snmp6_item
snmp6_udp6_list
[]
=
{
#define SNMP6_GEN(x) { .name = "Udp6" #x , .offset = offsetof(struct udp_mib, Udp##x) }
SNMP6_GEN
(
InDatagrams
),
SNMP6_GEN
(
NoPorts
),
SNMP6_GEN
(
InErrors
),
SNMP6_GEN
(
OutDatagrams
)
SNMP6_GEN
(
OutDatagrams
)
,
#undef SNMP6_GEN
SNMP6_SENTINEL
};
static
unsigned
long
...
...
@@ -151,18 +168,30 @@ fold_field(void *mib[], int offt)
return
res
;
}
static
int
snmp6_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
static
inline
void
snmp6_seq_show_item
(
struct
seq_file
*
seq
,
void
**
mib
,
struct
snmp6_item
*
itemlist
)
{
int
i
;
for
(
i
=
0
;
itemlist
[
i
].
name
;
i
++
)
seq_printf
(
seq
,
"%-32s
\t
%lu
\n
"
,
itemlist
[
i
].
name
,
fold_field
(
mib
,
itemlist
[
i
].
offset
));
}
for
(
i
=
0
;
i
<
sizeof
(
snmp6_list
)
/
sizeof
(
snmp6_list
[
0
]);
i
++
)
seq_printf
(
seq
,
"%-32s
\t
%lu
\n
"
,
snmp6_list
[
i
].
name
,
fold_field
(
snmp6_list
[
i
].
mib
,
snmp6_list
[
i
].
offset
))
;
static
int
snmp6_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
inet6_dev
*
idev
=
(
struct
inet6_dev
*
)
seq
->
private
;
if
(
idev
)
{
seq_printf
(
seq
,
"%-32s
\t
%u
\n
"
,
"ifIndex"
,
idev
->
dev
->
ifindex
);
snmp6_seq_show_item
(
seq
,
(
void
**
)
idev
->
stats
.
icmpv6
,
snmp6_icmp6_list
);
}
else
{
snmp6_seq_show_item
(
seq
,
(
void
**
)
ipv6_statistics
,
snmp6_ipv6_list
);
snmp6_seq_show_item
(
seq
,
(
void
**
)
icmpv6_statistics
,
snmp6_icmp6_list
);
snmp6_seq_show_item
(
seq
,
(
void
**
)
udp_stats_in6
,
snmp6_udp6_list
);
}
return
0
;
}
static
int
sockstat6_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
sockstat6_seq_show
,
NULL
);
...
...
@@ -177,7 +206,7 @@ static struct file_operations sockstat6_seq_fops = {
static
int
snmp6_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
snmp6_seq_show
,
NULL
);
return
single_open
(
file
,
snmp6_seq_show
,
PDE
(
inode
)
->
data
);
}
static
struct
file_operations
snmp6_seq_fops
=
{
...
...
@@ -187,6 +216,57 @@ static struct file_operations snmp6_seq_fops = {
.
release
=
single_release
,
};
int
snmp6_register_dev
(
struct
inet6_dev
*
idev
)
{
int
err
=
-
ENOMEM
;
#ifdef CONFIG_PROC_FS
struct
proc_dir_entry
*
p
;
#endif
if
(
!
idev
||
!
idev
->
dev
)
return
-
EINVAL
;
if
(
snmp6_mib_init
((
void
**
)
idev
->
stats
.
icmpv6
,
sizeof
(
struct
icmpv6_mib
))
<
0
)
goto
err_icmp
;
#ifdef CONFIG_PROC_FS
if
(
!
proc_net_devsnmp6
)
{
err
=
-
ENOENT
;
goto
err_proc
;
}
p
=
create_proc_entry
(
idev
->
dev
->
name
,
S_IRUGO
,
proc_net_devsnmp6
);
if
(
!
p
)
goto
err_proc
;
p
->
data
=
idev
;
p
->
proc_fops
=
&
snmp6_seq_fops
;
idev
->
stats
.
proc_dir_entry
=
p
;
#endif
return
0
;
#ifdef CONFIG_PROC_FS
err_proc:
snmp6_mib_free
((
void
**
)
idev
->
stats
.
icmpv6
);
#endif
err_icmp:
return
err
;
}
int
snmp6_unregister_dev
(
struct
inet6_dev
*
idev
)
{
#ifdef CONFIG_PROC_FS
if
(
!
proc_net_devsnmp6
)
return
-
ENOENT
;
if
(
!
idev
||
!
idev
->
stats
.
proc_dir_entry
)
return
-
EINVAL
;
remove_proc_entry
(
idev
->
stats
.
proc_dir_entry
->
name
,
proc_net_devsnmp6
);
#endif
snmp6_mib_free
((
void
**
)
idev
->
stats
.
icmpv6
);
return
0
;
}
int
__init
ipv6_misc_proc_init
(
void
)
{
int
rc
=
0
;
...
...
@@ -197,6 +277,9 @@ int __init ipv6_misc_proc_init(void)
goto
proc_snmp6_fail
;
else
p
->
proc_fops
=
&
snmp6_seq_fops
;
proc_net_devsnmp6
=
proc_mkdir
(
"dev_snmp6"
,
proc_net
);
if
(
!
proc_net_devsnmp6
)
goto
proc_dev_snmp6_fail
;
p
=
create_proc_entry
(
"sockstat6"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
proc_sockstat6_fail
;
...
...
@@ -206,6 +289,8 @@ int __init ipv6_misc_proc_init(void)
return
rc
;
proc_sockstat6_fail:
remove_proc_entry
(
"dev_snmp6"
,
proc_net
);
proc_dev_snmp6_fail:
remove_proc_entry
(
"snmp6"
,
proc_net
);
proc_snmp6_fail:
rc
=
-
ENOMEM
;
...
...
net/ipv6/tcp_ipv6.c
View file @
cc0142de
...
...
@@ -751,7 +751,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
sk
=
tcp_v6_lookup
(
&
hdr
->
daddr
,
th
->
dest
,
&
hdr
->
saddr
,
th
->
source
,
skb
->
dev
->
ifindex
);
if
(
sk
==
NULL
)
{
ICMP6_INC_STATS_BH
(
Icmp6InErrors
);
ICMP6_INC_STATS_BH
(
__in6_dev_get
(
skb
->
dev
),
Icmp6InErrors
);
return
;
}
...
...
net/sctp/ipv6.c
View file @
cc0142de
...
...
@@ -92,6 +92,7 @@ extern struct notifier_block sctp_inetaddr_notifier;
void
sctp_v6_err
(
struct
sk_buff
*
skb
,
struct
inet6_skb_parm
*
opt
,
int
type
,
int
code
,
int
offset
,
__u32
info
)
{
struct
inet6_dev
*
idev
;
struct
ipv6hdr
*
iph
=
(
struct
ipv6hdr
*
)
skb
->
data
;
struct
sctphdr
*
sh
=
(
struct
sctphdr
*
)(
skb
->
data
+
offset
);
struct
sock
*
sk
;
...
...
@@ -102,6 +103,8 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
char
*
saveip
,
*
savesctp
;
int
err
;
idev
=
in6_dev_get
(
skb
->
dev
);
/* Fix up skb to look at the embedded net header. */
saveip
=
skb
->
nh
.
raw
;
savesctp
=
skb
->
h
.
raw
;
...
...
@@ -112,8 +115,8 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
skb
->
nh
.
raw
=
saveip
;
skb
->
h
.
raw
=
savesctp
;
if
(
!
sk
)
{
ICMP6_INC_STATS_BH
(
Icmp6InErrors
);
return
;
ICMP6_INC_STATS_BH
(
idev
,
Icmp6InErrors
);
goto
out
;
}
/* Warning: The sock lock is held. Remember to call
...
...
@@ -139,6 +142,9 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
out_unlock:
sctp_err_finish
(
sk
,
ep
,
asoc
);
out:
if
(
likely
(
idev
!=
NULL
))
in6_dev_put
(
idev
);
}
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
...
...
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