Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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