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
d524ab44
Commit
d524ab44
authored
Jun 30, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/davem/net-2.5
into home.osdl.org:/home/torvalds/v2.5/linux
parents
0aafd44a
ba61d50f
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
942 additions
and
392 deletions
+942
-392
include/net/addrconf.h
include/net/addrconf.h
+2
-0
include/net/ip.h
include/net/ip.h
+1
-2
net/bridge/br_fdb.c
net/bridge/br_fdb.c
+15
-2
net/bridge/br_if.c
net/bridge/br_if.c
+1
-1
net/bridge/br_input.c
net/bridge/br_input.c
+7
-4
net/bridge/br_private.h
net/bridge/br_private.h
+1
-1
net/bridge/br_stp_bpdu.c
net/bridge/br_stp_bpdu.c
+52
-42
net/ipv4/igmp.c
net/ipv4/igmp.c
+317
-98
net/ipv4/ip_output.c
net/ipv4/ip_output.c
+1
-2
net/ipv4/raw.c
net/ipv4/raw.c
+19
-2
net/ipv6/addrconf.c
net/ipv6/addrconf.c
+40
-2
net/ipv6/af_inet6.c
net/ipv6/af_inet6.c
+5
-4
net/ipv6/anycast.c
net/ipv6/anycast.c
+144
-40
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_flowlabel.c
+20
-2
net/ipv6/mcast.c
net/ipv6/mcast.c
+298
-109
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+0
-1
net/ipv6/raw.c
net/ipv6/raw.c
+17
-2
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+0
-37
net/ipv6/udp.c
net/ipv6/udp.c
+1
-38
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_input.c
+1
-3
No files found.
include/net/addrconf.h
View file @
d524ab44
...
...
@@ -68,6 +68,8 @@ extern int ipv6_dev_get_saddr(struct net_device *dev,
struct
in6_addr
*
saddr
,
int
onlink
);
extern
int
ipv6_get_lladdr
(
struct
net_device
*
dev
,
struct
in6_addr
*
);
extern
int
ipv6_rcv_saddr_equal
(
const
struct
sock
*
sk
,
const
struct
sock
*
sk2
);
extern
void
addrconf_join_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
extern
void
addrconf_leave_solict
(
struct
net_device
*
dev
,
...
...
include/net/ip.h
View file @
d524ab44
...
...
@@ -79,8 +79,7 @@ extern rwlock_t ip_ra_lock;
extern
void
ip_mc_dropsocket
(
struct
sock
*
);
extern
void
ip_mc_dropdevice
(
struct
net_device
*
dev
);
extern
int
ip_mc_procinfo
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
ip_mcf_procinfo
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
igmp_mc_proc_init
(
void
);
/*
* Functions provided by ip.c
...
...
net/bridge/br_fdb.c
View file @
d524ab44
...
...
@@ -251,8 +251,21 @@ void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
write_lock_bh
(
&
br
->
hash_lock
);
hlist_for_each
(
h
,
&
br
->
hash
[
hash
])
{
fdb
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
if
(
!
fdb
->
is_local
&&
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
if
(
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
/* attempt to update an entry for a local interface */
if
(
unlikely
(
fdb
->
is_local
))
{
if
(
is_local
)
printk
(
KERN_INFO
"%s: attempt to add"
" interface with same source address.
\n
"
,
source
->
dev
->
name
);
else
if
(
net_ratelimit
())
printk
(
KERN_WARNING
"%s: received packet with "
" own address as source address
\n
"
,
source
->
dev
->
name
);
goto
out
;
}
if
(
likely
(
!
fdb
->
is_static
||
is_local
))
{
/* move to end of age list */
list_del
(
&
fdb
->
age_list
);
...
...
net/bridge/br_if.c
View file @
d524ab44
...
...
@@ -95,7 +95,7 @@ static struct net_bridge *new_nb(const char *name)
br
->
bridge_id
.
prio
[
1
]
=
0x00
;
memset
(
br
->
bridge_id
.
addr
,
0
,
ETH_ALEN
);
br
->
stp_enabled
=
1
;
br
->
stp_enabled
=
0
;
br
->
designated_root
=
br
->
bridge_id
;
br
->
root_path_cost
=
0
;
br
->
root_port
=
0
;
...
...
net/bridge/br_input.c
View file @
d524ab44
...
...
@@ -129,12 +129,15 @@ int br_handle_frame(struct sk_buff *skb)
if
(
p
->
br
->
stp_enabled
&&
!
memcmp
(
dest
,
bridge_ula
,
5
)
&&
!
(
dest
[
5
]
&
0xF0
))
{
if
(
!
dest
[
5
])
br_stp_handle_bpdu
(
skb
);
goto
err
;
if
(
!
dest
[
5
])
{
NF_HOOK
(
PF_BRIDGE
,
NF_BR_LOCAL_IN
,
skb
,
skb
->
dev
,
NULL
,
br_stp_handle_bpdu
);
rcu_read_unlock
();
return
0
;
}
}
if
(
p
->
state
==
BR_STATE_FORWARDING
)
{
else
if
(
p
->
state
==
BR_STATE_FORWARDING
)
{
if
(
br_should_route_hook
&&
br_should_route_hook
(
&
skb
))
{
rcu_read_unlock
();
return
-
1
;
...
...
net/bridge/br_private.h
View file @
d524ab44
...
...
@@ -206,7 +206,7 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p,
int
path_cost
);
/* br_stp_bpdu.c */
extern
void
br_stp_handle_bpdu
(
struct
sk_buff
*
skb
);
extern
int
br_stp_handle_bpdu
(
struct
sk_buff
*
skb
);
/* br_stp_timer.c */
extern
void
br_stp_timer_init
(
struct
net_bridge
*
br
);
...
...
net/bridge/br_stp_bpdu.c
View file @
d524ab44
...
...
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/if_ether.h>
#include <linux/if_bridge.h>
#include <linux/netfilter_bridge.h>
#include "br_private.h"
#include "br_private_stp.h"
...
...
@@ -53,7 +54,8 @@ static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int len
memcpy
(
skb
->
nh
.
raw
,
data
,
length
);
memset
(
skb
->
nh
.
raw
+
length
,
0xa5
,
size
-
length
-
2
*
ETH_ALEN
-
2
);
dev_queue_xmit
(
skb
);
NF_HOOK
(
PF_BRIDGE
,
NF_BR_LOCAL_OUT
,
skb
,
NULL
,
skb
->
dev
,
dev_queue_xmit
);
}
static
__inline__
void
br_set_ticks
(
unsigned
char
*
dest
,
int
jiff
)
...
...
@@ -130,67 +132,75 @@ void br_send_tcn_bpdu(struct net_bridge_port *p)
br_send_bpdu
(
p
,
buf
,
7
);
}
static
unsigned
char
header
[
6
]
=
{
0x42
,
0x42
,
0x03
,
0x00
,
0x00
,
0x00
};
static
const
unsigned
char
header
[
6
]
=
{
0x42
,
0x42
,
0x03
,
0x00
,
0x00
,
0x00
};
/* NO locks */
void
br_stp_handle_bpdu
(
struct
sk_buff
*
skb
)
int
br_stp_handle_bpdu
(
struct
sk_buff
*
skb
)
{
struct
net_bridge_port
*
p
=
skb
->
dev
->
br_port
;
struct
net_bridge
*
br
=
p
->
br
;
unsigned
char
*
buf
;
struct
net_bridge_port
*
p
;
struct
net_bridge
*
br
;
buf
=
skb
->
mac
.
raw
+
14
;
p
=
skb
->
dev
->
br_port
;
br
=
p
->
br
;
/* need at least the 802 and STP headers */
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
header
)
+
1
)
||
memcmp
(
skb
->
data
,
header
,
sizeof
(
header
)))
goto
err
;
buf
=
skb_pull
(
skb
,
sizeof
(
header
));
spin_lock_bh
(
&
br
->
lock
);
if
(
p
->
state
==
BR_STATE_DISABLED
||
!
(
br
->
dev
->
flags
&
IFF_UP
)
||
!
br
->
stp_enabled
||
memcmp
(
buf
,
header
,
6
))
||
!
br
->
stp_enabled
)
goto
out
;
if
(
buf
[
6
]
==
BPDU_TYPE_CONFIG
)
{
if
(
buf
[
0
]
==
BPDU_TYPE_CONFIG
)
{
struct
br_config_bpdu
bpdu
;
bpdu
.
topology_change
=
(
buf
[
7
]
&
0x01
)
?
1
:
0
;
bpdu
.
topology_change_ack
=
(
buf
[
7
]
&
0x80
)
?
1
:
0
;
bpdu
.
root
.
prio
[
0
]
=
buf
[
8
];
bpdu
.
root
.
prio
[
1
]
=
buf
[
9
];
bpdu
.
root
.
addr
[
0
]
=
buf
[
10
];
bpdu
.
root
.
addr
[
1
]
=
buf
[
11
];
bpdu
.
root
.
addr
[
2
]
=
buf
[
12
];
bpdu
.
root
.
addr
[
3
]
=
buf
[
13
];
bpdu
.
root
.
addr
[
4
]
=
buf
[
14
];
bpdu
.
root
.
addr
[
5
]
=
buf
[
15
];
if
(
!
pskb_may_pull
(
skb
,
32
))
goto
out
;
buf
=
skb
->
data
;
bpdu
.
topology_change
=
(
buf
[
1
]
&
0x01
)
?
1
:
0
;
bpdu
.
topology_change_ack
=
(
buf
[
1
]
&
0x80
)
?
1
:
0
;
bpdu
.
root
.
prio
[
0
]
=
buf
[
2
];
bpdu
.
root
.
prio
[
1
]
=
buf
[
3
];
bpdu
.
root
.
addr
[
0
]
=
buf
[
4
];
bpdu
.
root
.
addr
[
1
]
=
buf
[
5
];
bpdu
.
root
.
addr
[
2
]
=
buf
[
6
];
bpdu
.
root
.
addr
[
3
]
=
buf
[
7
];
bpdu
.
root
.
addr
[
4
]
=
buf
[
8
];
bpdu
.
root
.
addr
[
5
]
=
buf
[
9
];
bpdu
.
root_path_cost
=
(
buf
[
1
6
]
<<
24
)
|
(
buf
[
1
7
]
<<
16
)
|
(
buf
[
1
8
]
<<
8
)
|
buf
[
1
9
];
bpdu
.
bridge_id
.
prio
[
0
]
=
buf
[
20
];
bpdu
.
bridge_id
.
prio
[
1
]
=
buf
[
21
];
bpdu
.
bridge_id
.
addr
[
0
]
=
buf
[
22
];
bpdu
.
bridge_id
.
addr
[
1
]
=
buf
[
23
];
bpdu
.
bridge_id
.
addr
[
2
]
=
buf
[
24
];
bpdu
.
bridge_id
.
addr
[
3
]
=
buf
[
25
];
bpdu
.
bridge_id
.
addr
[
4
]
=
buf
[
2
6
];
bpdu
.
bridge_id
.
addr
[
5
]
=
buf
[
2
7
];
bpdu
.
port_id
=
(
buf
[
2
8
]
<<
8
)
|
buf
[
29
];
bpdu
.
message_age
=
br_get_ticks
(
buf
+
30
);
bpdu
.
max_age
=
br_get_ticks
(
buf
+
32
);
bpdu
.
hello_time
=
br_get_ticks
(
buf
+
34
);
bpdu
.
forward_delay
=
br_get_ticks
(
buf
+
3
6
);
(
buf
[
1
0
]
<<
24
)
|
(
buf
[
1
1
]
<<
16
)
|
(
buf
[
1
2
]
<<
8
)
|
buf
[
1
3
];
bpdu
.
bridge_id
.
prio
[
0
]
=
buf
[
14
];
bpdu
.
bridge_id
.
prio
[
1
]
=
buf
[
15
];
bpdu
.
bridge_id
.
addr
[
0
]
=
buf
[
16
];
bpdu
.
bridge_id
.
addr
[
1
]
=
buf
[
17
];
bpdu
.
bridge_id
.
addr
[
2
]
=
buf
[
18
];
bpdu
.
bridge_id
.
addr
[
3
]
=
buf
[
19
];
bpdu
.
bridge_id
.
addr
[
4
]
=
buf
[
2
0
];
bpdu
.
bridge_id
.
addr
[
5
]
=
buf
[
2
1
];
bpdu
.
port_id
=
(
buf
[
2
2
]
<<
8
)
|
buf
[
23
];
bpdu
.
message_age
=
br_get_ticks
(
buf
+
24
);
bpdu
.
max_age
=
br_get_ticks
(
buf
+
26
);
bpdu
.
hello_time
=
br_get_ticks
(
buf
+
28
);
bpdu
.
forward_delay
=
br_get_ticks
(
buf
+
3
0
);
br_received_config_bpdu
(
p
,
&
bpdu
);
goto
out
;
}
if
(
buf
[
6
]
==
BPDU_TYPE_TCN
)
{
else
if
(
buf
[
0
]
==
BPDU_TYPE_TCN
)
{
br_received_tcn_bpdu
(
p
);
goto
out
;
}
out:
spin_unlock_bh
(
&
br
->
lock
);
err:
kfree
(
skb
);
return
0
;
}
net/ipv4/igmp.c
View file @
d524ab44
...
...
@@ -99,7 +99,10 @@
#ifdef CONFIG_IP_MROUTE
#include <linux/mroute.h>
#endif
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#define IP_MAX_MEMBERSHIPS 20
...
...
@@ -2090,127 +2093,343 @@ int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
return
rv
;
}
#if defined(CONFIG_PROC_FS)
struct
igmp_mc_iter_state
{
struct
net_device
*
dev
;
struct
in_device
*
in_dev
;
};
#define igmp_mc_seq_private(seq) ((struct igmp_mc_iter_state *)&seq->private)
int
ip_mc_procinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
inline
struct
ip_mc_list
*
igmp_mc_get_first
(
struct
seq_file
*
seq
)
{
off_t
pos
=
0
,
begin
=
0
;
struct
ip_mc_list
*
im
;
int
len
=
0
;
struct
net_device
*
dev
;
struct
ip_mc_list
*
im
=
NULL
;
struct
igmp_mc_iter_state
*
state
=
igmp_mc_seq_private
(
seq
);
len
=
sprintf
(
buffer
,
"Idx
\t
Device : Count Querier
\t
Group Users Timer
\t
Reporter
\n
"
);
for
(
state
->
dev
=
dev_base
,
state
->
in_dev
=
NULL
;
state
->
dev
;
state
->
dev
=
state
->
dev
->
next
)
{
struct
in_device
*
in_dev
;
in_dev
=
in_dev_get
(
state
->
dev
);
if
(
!
in_dev
)
continue
;
read_lock
(
&
in_dev
->
lock
);
im
=
in_dev
->
mc_list
;
if
(
im
)
{
state
->
in_dev
=
in_dev
;
break
;
}
read_unlock
(
&
in_dev
->
lock
);
}
return
im
;
}
static
struct
ip_mc_list
*
igmp_mc_get_next
(
struct
seq_file
*
seq
,
struct
ip_mc_list
*
im
)
{
struct
igmp_mc_iter_state
*
state
=
igmp_mc_seq_private
(
seq
);
im
=
im
->
next
;
while
(
!
im
)
{
if
(
likely
(
state
->
in_dev
!=
NULL
))
{
read_unlock
(
&
state
->
in_dev
->
lock
);
in_dev_put
(
state
->
in_dev
);
}
state
->
dev
=
state
->
dev
->
next
;
if
(
!
state
->
dev
)
{
state
->
in_dev
=
NULL
;
break
;
}
state
->
in_dev
=
in_dev_get
(
state
->
dev
);
if
(
!
state
->
in_dev
)
continue
;
read_lock
(
&
state
->
in_dev
->
lock
);
im
=
state
->
in_dev
->
mc_list
;
}
return
im
;
}
static
struct
ip_mc_list
*
igmp_mc_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
ip_mc_list
*
im
=
igmp_mc_get_first
(
seq
);
if
(
im
)
while
(
pos
&&
(
im
=
igmp_mc_get_next
(
seq
,
im
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
im
;
}
static
void
*
igmp_mc_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
in_device
*
in_dev
=
in_dev_get
(
dev
);
char
*
querier
=
"NONE"
;
return
*
pos
?
igmp_mc_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
if
(
in_dev
==
NULL
)
continue
;
static
void
*
igmp_mc_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ip_mc_list
*
im
;
if
(
v
==
(
void
*
)
1
)
im
=
igmp_mc_get_first
(
seq
);
else
im
=
igmp_mc_get_next
(
seq
,
v
);
++*
pos
;
return
im
;
}
static
void
igmp_mc_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
igmp_mc_iter_state
*
state
=
igmp_mc_seq_private
(
seq
);
if
(
likely
(
state
->
in_dev
!=
NULL
))
{
read_unlock
(
&
state
->
in_dev
->
lock
);
in_dev_put
(
state
->
in_dev
);
}
read_unlock
(
&
dev_base_lock
);
}
static
int
igmp_mc_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
if
(
v
==
(
void
*
)
1
)
seq_printf
(
seq
,
"Idx
\t
Device : Count Querier
\t
Group Users Timer
\t
Reporter
\n
"
);
else
{
struct
ip_mc_list
*
im
=
(
struct
ip_mc_list
*
)
v
;
struct
igmp_mc_iter_state
*
state
=
igmp_mc_seq_private
(
seq
);
char
*
querier
;
#ifdef CONFIG_IP_MULTICAST
querier
=
IGMP_V1_SEEN
(
in_dev
)
?
"V1"
:
"V2"
;
querier
=
IGMP_V1_SEEN
(
state
->
in_dev
)
?
"V1"
:
"V2"
;
#else
querier
=
"NONE"
;
#endif
len
+=
sprintf
(
buffer
+
len
,
"%d
\t
%-10s: %5d %7s
\n
"
,
dev
->
ifindex
,
dev
->
name
,
dev
->
mc_count
,
querier
);
read_lock
(
&
in_dev
->
lock
);
for
(
im
=
in_dev
->
mc_list
;
im
;
im
=
im
->
next
)
{
len
+=
sprintf
(
buffer
+
len
,
"
\t\t\t\t
%08lX %5d %d:%08lX
\t\t
%d
\n
"
,
im
->
multiaddr
,
im
->
users
,
im
->
tm_running
,
im
->
timer
.
expires
-
jiffies
,
im
->
reporter
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
goto
done
;
}
if
(
state
->
in_dev
->
mc_list
==
im
)
{
seq_printf
(
seq
,
"%d
\t
%-10s: %5d %7s
\n
"
,
state
->
dev
->
ifindex
,
state
->
dev
->
name
,
state
->
dev
->
mc_count
,
querier
);
}
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
}
done:
read_unlock
(
&
dev_base_lock
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
seq_printf
(
seq
,
"
\t\t\t\t
%08lX %5d %d:%08lX
\t\t
%d
\n
"
,
im
->
multiaddr
,
im
->
users
,
im
->
tm_running
,
im
->
timer
.
expires
-
jiffies
,
im
->
reporter
);
}
return
0
;
}
int
ip_mcf_procinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
struct
seq_operations
igmp_mc_seq_ops
=
{
.
start
=
igmp_mc_seq_start
,
.
next
=
igmp_mc_seq_next
,
.
stop
=
igmp_mc_seq_stop
,
.
show
=
igmp_mc_seq_show
,
};
static
int
igmp_mc_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
off_t
pos
=
0
,
begin
=
0
;
int
len
=
0
;
int
first
=
1
;
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
igmp_mc_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
igmp_mc_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
igmp_mc_seq_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
igmp_mc_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
struct
igmp_mcf_iter_state
{
struct
net_device
*
dev
;
struct
in_device
*
idev
;
struct
ip_mc_list
*
im
;
};
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
in_device
*
in_dev
=
in_dev_get
(
dev
);
struct
ip_mc_list
*
imc
;
#define igmp_mcf_seq_private(seq) ((struct igmp_mcf_iter_state *)&seq->private)
if
(
in_dev
==
NULL
)
static
inline
struct
ip_sf_list
*
igmp_mcf_get_first
(
struct
seq_file
*
seq
)
{
struct
ip_sf_list
*
psf
=
NULL
;
struct
ip_mc_list
*
im
=
NULL
;
struct
igmp_mcf_iter_state
*
state
=
igmp_mcf_seq_private
(
seq
);
for
(
state
->
dev
=
dev_base
,
state
->
idev
=
NULL
,
state
->
im
=
NULL
;
state
->
dev
;
state
->
dev
=
state
->
dev
->
next
)
{
struct
in_device
*
idev
;
idev
=
in_dev_get
(
state
->
dev
);
if
(
unlikely
(
idev
==
NULL
))
continue
;
read_lock_bh
(
&
idev
->
lock
);
im
=
idev
->
mc_list
;
if
(
likely
(
im
!=
NULL
))
{
spin_lock_bh
(
&
im
->
lock
);
psf
=
im
->
sources
;
if
(
likely
(
psf
!=
NULL
))
{
state
->
im
=
im
;
state
->
idev
=
idev
;
break
;
}
spin_unlock_bh
(
&
im
->
lock
);
}
read_unlock_bh
(
&
idev
->
lock
);
}
return
psf
;
}
read_lock
(
&
in_dev
->
lock
);
for
(
imc
=
in_dev
->
mc_list
;
imc
;
imc
=
imc
->
next
)
{
struct
ip_sf_list
*
psf
;
spin_lock_bh
(
&
imc
->
lock
);
for
(
psf
=
imc
->
sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
"%10s %10s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"MCA"
,
"SRC"
,
"INC"
,
"EXC"
);
first
=
0
;
}
len
+=
sprintf
(
buffer
+
len
,
"%3d %6.6s 0x%08x "
"0x%08x %6lu %6lu
\n
"
,
dev
->
ifindex
,
dev
->
name
,
ntohl
(
imc
->
multiaddr
),
ntohl
(
psf
->
sf_inaddr
),
psf
->
sf_count
[
MCAST_INCLUDE
],
psf
->
sf_count
[
MCAST_EXCLUDE
]);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
spin_unlock_bh
(
&
imc
->
lock
);
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
goto
done
;
}
static
struct
ip_sf_list
*
igmp_mcf_get_next
(
struct
seq_file
*
seq
,
struct
ip_sf_list
*
psf
)
{
struct
igmp_mcf_iter_state
*
state
=
igmp_mcf_seq_private
(
seq
);
psf
=
psf
->
sf_next
;
while
(
!
psf
)
{
spin_unlock_bh
(
&
state
->
im
->
lock
);
state
->
im
=
state
->
im
->
next
;
while
(
!
state
->
im
)
{
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in_dev_put
(
state
->
idev
);
}
state
->
dev
=
state
->
dev
->
next
;
if
(
!
state
->
dev
)
{
state
->
idev
=
NULL
;
goto
out
;
}
spin_unlock_bh
(
&
imc
->
lock
);
state
->
idev
=
in_dev_get
(
state
->
dev
);
if
(
!
state
->
idev
)
continue
;
read_lock_bh
(
&
state
->
idev
->
lock
);
state
->
im
=
state
->
idev
->
mc_list
;
}
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
if
(
!
state
->
im
)
break
;
spin_lock_bh
(
&
state
->
im
->
lock
);
psf
=
state
->
im
->
sources
;
}
out:
return
psf
;
}
static
struct
ip_sf_list
*
igmp_mcf_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
ip_sf_list
*
psf
=
igmp_mcf_get_first
(
seq
);
if
(
psf
)
while
(
pos
&&
(
psf
=
igmp_mcf_get_next
(
seq
,
psf
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
psf
;
}
static
void
*
igmp_mcf_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
return
*
pos
?
igmp_mcf_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
static
void
*
igmp_mcf_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ip_sf_list
*
psf
;
if
(
v
==
(
void
*
)
1
)
psf
=
igmp_mcf_get_first
(
seq
);
else
psf
=
igmp_mcf_get_next
(
seq
,
v
);
++*
pos
;
return
psf
;
}
static
void
igmp_mcf_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
igmp_mcf_iter_state
*
state
=
igmp_mcf_seq_private
(
seq
);
if
(
likely
(
state
->
im
!=
NULL
))
spin_unlock_bh
(
&
state
->
im
->
lock
);
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in_dev_put
(
state
->
idev
);
}
done:
read_unlock
(
&
dev_base_lock
);
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
int
igmp_mcf_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
ip_sf_list
*
psf
=
(
struct
ip_sf_list
*
)
v
;
struct
igmp_mcf_iter_state
*
state
=
igmp_mcf_seq_private
(
seq
);
if
(
v
==
(
void
*
)
1
)
{
seq_printf
(
seq
,
"%3s %6s "
"%10s %10s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"MCA"
,
"SRC"
,
"INC"
,
"EXC"
);
}
else
{
seq_printf
(
seq
,
"%3d %6.6s 0x%08x "
"0x%08x %6lu %6lu
\n
"
,
state
->
dev
->
ifindex
,
state
->
dev
->
name
,
ntohl
(
state
->
im
->
multiaddr
),
ntohl
(
psf
->
sf_inaddr
),
psf
->
sf_count
[
MCAST_INCLUDE
],
psf
->
sf_count
[
MCAST_EXCLUDE
]);
}
return
0
;
}
static
struct
seq_operations
igmp_mcf_seq_ops
=
{
.
start
=
igmp_mcf_seq_start
,
.
next
=
igmp_mcf_seq_next
,
.
stop
=
igmp_mcf_seq_stop
,
.
show
=
igmp_mcf_seq_show
,
};
static
int
igmp_mcf_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
igmp_mcf_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
igmp_mcf_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
igmp_mcf_seq_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
igmp_mcf_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
int
__init
igmp_mc_proc_init
(
void
)
{
struct
proc_dir_entry
*
p
;
p
=
create_proc_entry
(
"igmp"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
igmp_mc_seq_fops
;
p
=
create_proc_entry
(
"mcfilter"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
igmp_mcf_seq_fops
;
return
0
;
}
#endif
net/ipv4/ip_output.c
View file @
d524ab44
...
...
@@ -1314,7 +1314,6 @@ void __init ip_init(void)
inet_initpeers
();
#ifdef CONFIG_IP_MULTICAST
proc_net_create
(
"igmp"
,
0
,
ip_mc_procinfo
);
igmp_mc_proc_init
(
);
#endif
proc_net_create
(
"mcfilter"
,
0
,
ip_mcf_procinfo
);
}
net/ipv4/raw.c
View file @
d524ab44
...
...
@@ -801,7 +801,24 @@ static struct seq_operations raw_seq_ops = {
static
int
raw_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
raw_seq_ops
);
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
raw_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
raw_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
raw_seq_fops
=
{
...
...
@@ -809,7 +826,7 @@ static struct file_operations raw_seq_fops = {
.
open
=
raw_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
.
release
=
seq_release
_private
,
};
int
__init
raw_proc_init
(
void
)
...
...
net/ipv6/addrconf.c
View file @
d524ab44
...
...
@@ -66,6 +66,7 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <linux/if_tunnel.h>
#include <linux/rtnetlink.h>
...
...
@@ -701,7 +702,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift
=
ipv6_count_addresses
(
idev
)
<
IPV6_MAX_ADDRESSES
?
ipv6_add_addr
(
idev
,
&
addr
,
tmp_plen
,
ipv6_addr_type
(
&
addr
)
&
IPV6_ADDR_SCOPE_MASK
,
IFA_F_TEMPORARY
)
:
0
;
if
(
IS_ERR
(
ift
))
{
if
(
!
ift
||
IS_ERR
(
ift
))
{
in6_dev_put
(
idev
);
in6_ifa_put
(
ifp
);
printk
(
KERN_INFO
...
...
@@ -969,6 +970,43 @@ struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *
return
ifp
;
}
int
ipv6_rcv_saddr_equal
(
const
struct
sock
*
sk
,
const
struct
sock
*
sk2
)
{
struct
ipv6_pinfo
*
np
=
inet6_sk
(
sk
);
int
addr_type
=
ipv6_addr_type
(
&
np
->
rcv_saddr
);
if
(
!
inet_sk
(
sk2
)
->
rcv_saddr
&&
!
ipv6_only_sock
(
sk
))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
ipv6_addr_any
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
&&
!
(
ipv6_only_sock
(
sk2
)
&&
addr_type
==
IPV6_ADDR_MAPPED
))
return
1
;
if
(
addr_type
==
IPV6_ADDR_ANY
&&
(
!
ipv6_only_sock
(
sk
)
||
!
(
sk2
->
sk_family
==
AF_INET6
?
(
ipv6_addr_type
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
==
IPV6_ADDR_MAPPED
)
:
1
)))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
!
ipv6_addr_cmp
(
&
np
->
rcv_saddr
,
(
sk2
->
sk_state
!=
TCP_TIME_WAIT
?
&
inet6_sk
(
sk2
)
->
rcv_saddr
:
&
tcptw_sk
(
sk
)
->
tw_v6_rcv_saddr
)))
return
1
;
if
(
addr_type
==
IPV6_ADDR_MAPPED
&&
!
ipv6_only_sock
(
sk2
)
&&
(
!
inet_sk
(
sk2
)
->
rcv_saddr
||
!
inet_sk
(
sk
)
->
rcv_saddr
||
inet_sk
(
sk
)
->
rcv_saddr
==
inet_sk
(
sk2
)
->
rcv_saddr
))
return
1
;
return
0
;
}
/* Gets referenced address, destroys ifaddr */
void
addrconf_dad_failure
(
struct
inet6_ifaddr
*
ifp
)
...
...
@@ -1372,7 +1410,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
ifp
=
ipv6_add_addr
(
in6_dev
,
&
addr
,
pinfo
->
prefix_len
,
addr_type
&
IPV6_ADDR_SCOPE_MASK
,
0
);
if
(
IS_ERR
(
ifp
))
{
if
(
!
ifp
||
IS_ERR
(
ifp
))
{
in6_dev_put
(
in6_dev
);
return
;
}
...
...
net/ipv6/af_inet6.c
View file @
d524ab44
...
...
@@ -85,7 +85,8 @@ extern int udp6_proc_init(void);
extern
void
udp6_proc_exit
(
void
);
extern
int
ipv6_misc_proc_init
(
void
);
extern
void
ipv6_misc_proc_exit
(
void
);
extern
int
anycast6_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
ac6_proc_init
(
void
);
extern
void
ac6_proc_exit
(
void
);
extern
int
if6_proc_init
(
void
);
extern
void
if6_proc_exit
(
void
);
#endif
...
...
@@ -799,7 +800,7 @@ static int __init inet6_init(void)
if
(
ipv6_misc_proc_init
())
goto
proc_misc6_fail
;
if
(
!
proc_net_create
(
"anycast6"
,
0
,
anycast6_get_info
))
if
(
ac6_proc_init
(
))
goto
proc_anycast6_fail
;
if
(
if6_proc_init
())
goto
proc_if6_fail
;
...
...
@@ -825,7 +826,7 @@ static int __init inet6_init(void)
#ifdef CONFIG_PROC_FS
proc_if6_fail:
proc_net_remove
(
"anycast6"
);
ac6_proc_exit
(
);
proc_anycast6_fail:
ipv6_misc_proc_exit
();
proc_misc6_fail:
...
...
@@ -863,7 +864,7 @@ static void inet6_exit(void)
sock_unregister
(
PF_INET6
);
#ifdef CONFIG_PROC_FS
if6_proc_exit
();
proc_net_remove
(
"anycast6"
);
ac6_proc_exit
(
);
ipv6_misc_proc_exit
();
udp6_proc_exit
();
tcp6_proc_exit
();
...
...
net/ipv6/anycast.c
View file @
d524ab44
...
...
@@ -29,6 +29,7 @@
#include <linux/route.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/snmp.h>
...
...
@@ -435,56 +436,159 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
#ifdef CONFIG_PROC_FS
int
anycast6_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
off_t
pos
=
0
,
begin
=
0
;
struct
ifacaddr6
*
im
;
int
len
=
0
;
struct
ac6_iter_state
{
struct
net_device
*
dev
;
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
inet6_dev
*
idev
;
struct
inet6_dev
*
idev
;
};
if
((
idev
=
in6_dev_get
(
dev
))
==
NULL
)
continue
;
#define ac6_seq_private(seq) ((struct ac6_iter_state *)&seq->private)
static
inline
struct
ifacaddr6
*
ac6_get_first
(
struct
seq_file
*
seq
)
{
struct
ifacaddr6
*
im
=
NULL
;
struct
ac6_iter_state
*
state
=
ac6_seq_private
(
seq
);
for
(
state
->
dev
=
dev_base
,
state
->
idev
=
NULL
;
state
->
dev
;
state
->
dev
=
state
->
dev
->
next
)
{
struct
inet6_dev
*
idev
;
idev
=
in6_dev_get
(
state
->
dev
);
if
(
!
idev
)
continue
;
read_lock_bh
(
&
idev
->
lock
);
for
(
im
=
idev
->
ac_list
;
im
;
im
=
im
->
aca_next
)
{
int
i
;
len
+=
sprintf
(
buffer
+
len
,
"%-4d %-15s "
,
dev
->
ifindex
,
dev
->
name
);
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
im
->
aca_addr
.
s6_addr
[
i
]);
len
+=
sprintf
(
buffer
+
len
,
" %5d
\n
"
,
im
->
aca_users
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
goto
done
;
}
im
=
idev
->
ac_list
;
if
(
im
)
{
state
->
idev
=
idev
;
break
;
}
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
}
return
im
;
}
static
struct
ifacaddr6
*
ac6_get_next
(
struct
seq_file
*
seq
,
struct
ifacaddr6
*
im
)
{
struct
ac6_iter_state
*
state
=
ac6_seq_private
(
seq
);
im
=
im
->
aca_next
;
while
(
!
im
)
{
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
state
->
dev
=
state
->
dev
->
next
;
if
(
!
state
->
dev
)
{
state
->
idev
=
NULL
;
break
;
}
state
->
idev
=
in6_dev_get
(
state
->
dev
);
if
(
!
state
->
idev
)
continue
;
read_lock_bh
(
&
state
->
idev
->
lock
);
im
=
state
->
idev
->
ac_list
;
}
return
im
;
}
static
struct
ifacaddr6
*
ac6_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
ifacaddr6
*
im
=
ac6_get_first
(
seq
);
if
(
im
)
while
(
pos
&&
(
im
=
ac6_get_next
(
seq
,
im
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
im
;
}
done:
static
void
*
ac6_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
return
*
pos
?
ac6_get_idx
(
seq
,
*
pos
)
:
ac6_get_first
(
seq
);
}
static
void
*
ac6_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ifacaddr6
*
im
;
im
=
ac6_get_next
(
seq
,
v
);
++*
pos
;
return
im
;
}
static
void
ac6_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
ac6_iter_state
*
state
=
ac6_seq_private
(
seq
);
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
read_unlock
(
&
dev_base_lock
);
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
int
ac6_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
ifacaddr6
*
im
=
(
struct
ifacaddr6
*
)
v
;
struct
ac6_iter_state
*
state
=
ac6_seq_private
(
seq
);
seq_printf
(
seq
,
"%-4d %-15s "
"%04x%04x%04x%04x%04x%04x%04x%04x "
"%5d
\n
"
,
state
->
dev
->
ifindex
,
state
->
dev
->
name
,
NIP6
(
im
->
aca_addr
),
im
->
aca_users
);
return
0
;
}
static
struct
seq_operations
ac6_seq_ops
=
{
.
start
=
ac6_seq_start
,
.
next
=
ac6_seq_next
,
.
stop
=
ac6_seq_stop
,
.
show
=
ac6_seq_show
,
};
static
int
ac6_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
ac6_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
ac6_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
ac6_seq_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ac6_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
int
__init
ac6_proc_init
(
void
)
{
struct
proc_dir_entry
*
p
;
p
=
create_proc_entry
(
"anycast6"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
ac6_seq_fops
;
return
0
;
}
void
ac6_proc_exit
(
void
)
{
proc_net_remove
(
"anycast6"
);
}
#endif
net/ipv6/ip6_flowlabel.c
View file @
d524ab44
...
...
@@ -657,7 +657,25 @@ static struct seq_operations ip6fl_seq_ops = {
static
int
ip6fl_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
ip6fl_seq_ops
);
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
ip6fl_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
ip6fl_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
ip6fl_seq_fops
=
{
...
...
@@ -665,7 +683,7 @@ static struct file_operations ip6fl_seq_fops = {
.
open
=
ip6fl_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
.
release
=
seq_release
_private
,
};
#endif
...
...
net/ipv6/mcast.c
View file @
d524ab44
...
...
@@ -44,6 +44,7 @@
#include <linux/route.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/snmp.h>
...
...
@@ -2039,138 +2040,317 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
}
#ifdef CONFIG_PROC_FS
static
int
igmp6_read_proc
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
*
eof
,
void
*
data
)
{
off_t
pos
=
0
,
begin
=
0
;
struct
ifmcaddr6
*
im
;
int
len
=
0
;
struct
igmp6_mc_iter_state
{
struct
net_device
*
dev
;
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
inet6_dev
*
idev
;
if
((
idev
=
in6_dev_get
(
dev
))
==
NULL
)
continue
;
struct
inet6_dev
*
idev
;
};
read_lock_bh
(
&
idev
->
lock
);
for
(
im
=
idev
->
mc_list
;
im
;
im
=
im
->
next
)
{
int
i
;
#define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)&seq->private)
len
+=
sprintf
(
buffer
+
len
,
"%-4d %-15s "
,
dev
->
ifindex
,
dev
->
name
);
static
inline
struct
ifmcaddr6
*
igmp6_mc_get_first
(
struct
seq_file
*
seq
)
{
struct
ifmcaddr6
*
im
=
NULL
;
struct
igmp6_mc_iter_state
*
state
=
igmp6_mc_seq_private
(
seq
);
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
im
->
mca_addr
.
s6_addr
[
i
]);
for
(
state
->
dev
=
dev_base
,
state
->
idev
=
NULL
;
state
->
dev
;
state
->
dev
=
state
->
dev
->
next
)
{
struct
inet6_dev
*
idev
;
idev
=
in6_dev_get
(
state
->
dev
);
if
(
!
idev
)
continue
;
read_lock_bh
(
&
idev
->
lock
);
im
=
idev
->
mc_list
;
if
(
im
)
{
state
->
idev
=
idev
;
break
;
}
read_unlock_bh
(
&
idev
->
lock
);
}
return
im
;
}
len
+=
sprintf
(
buffer
+
len
,
" %5d %08X %ld
\n
"
,
im
->
mca_users
,
im
->
mca_flags
,
(
im
->
mca_flags
&
MAF_TIMER_RUNNING
)
?
im
->
mca_timer
.
expires
-
jiffies
:
0
);
static
struct
ifmcaddr6
*
igmp6_mc_get_next
(
struct
seq_file
*
seq
,
struct
ifmcaddr6
*
im
)
{
struct
igmp6_mc_iter_state
*
state
=
igmp6_mc_seq_private
(
seq
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
goto
done
;
}
im
=
im
->
next
;
while
(
!
im
)
{
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
state
->
dev
=
state
->
dev
->
next
;
if
(
!
state
->
dev
)
{
state
->
idev
=
NULL
;
break
;
}
state
->
idev
=
in6_dev_get
(
state
->
dev
);
if
(
!
state
->
idev
)
continue
;
read_lock_bh
(
&
state
->
idev
->
lock
);
im
=
state
->
idev
->
mc_list
;
}
*
eof
=
1
;
return
im
;
}
done:
static
struct
ifmcaddr6
*
igmp6_mc_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
ifmcaddr6
*
im
=
igmp6_mc_get_first
(
seq
);
if
(
im
)
while
(
pos
&&
(
im
=
igmp6_mc_get_next
(
seq
,
im
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
im
;
}
static
void
*
igmp6_mc_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
return
*
pos
?
igmp6_mc_get_idx
(
seq
,
*
pos
)
:
igmp6_mc_get_first
(
seq
);
}
static
void
*
igmp6_mc_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ifmcaddr6
*
im
;
im
=
igmp6_mc_get_next
(
seq
,
v
);
++*
pos
;
return
im
;
}
static
void
igmp6_mc_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
igmp6_mc_iter_state
*
state
=
igmp6_mc_seq_private
(
seq
);
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
read_unlock
(
&
dev_base_lock
);
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
int
igmp6_mc_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
ifmcaddr6
*
im
=
(
struct
ifmcaddr6
*
)
v
;
struct
igmp6_mc_iter_state
*
state
=
igmp6_mc_seq_private
(
seq
);
seq_printf
(
seq
,
"%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld
\n
"
,
state
->
dev
->
ifindex
,
state
->
dev
->
name
,
NIP6
(
im
->
mca_addr
),
im
->
mca_users
,
im
->
mca_flags
,
(
im
->
mca_flags
&
MAF_TIMER_RUNNING
)
?
im
->
mca_timer
.
expires
-
jiffies
:
0
);
return
0
;
}
static
int
ip6_mcf_read_proc
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
*
eof
,
void
*
data
)
static
struct
seq_operations
igmp6_mc_seq_ops
=
{
.
start
=
igmp6_mc_seq_start
,
.
next
=
igmp6_mc_seq_next
,
.
stop
=
igmp6_mc_seq_stop
,
.
show
=
igmp6_mc_seq_show
,
};
static
int
igmp6_mc_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
off_t
pos
=
0
,
begin
=
0
;
int
len
=
0
;
int
first
=
1
;
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
igmp6_mc_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
igmp6_mc_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
igmp6_mc_seq_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
igmp6_mc_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
struct
igmp6_mcf_iter_state
{
struct
net_device
*
dev
;
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
inet6_dev
*
idev
=
in6_dev_get
(
dev
);
struct
ifmcaddr6
*
imc
;
struct
inet6_dev
*
idev
;
struct
ifmcaddr6
*
im
;
};
if
(
idev
==
NULL
)
continue
;
#define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)&seq->private)
read_lock_bh
(
&
idev
->
lock
);
static
inline
struct
ip6_sf_list
*
igmp6_mcf_get_first
(
struct
seq_file
*
seq
)
{
struct
ip6_sf_list
*
psf
=
NULL
;
struct
ifmcaddr6
*
im
=
NULL
;
struct
igmp6_mcf_iter_state
*
state
=
igmp6_mcf_seq_private
(
seq
);
for
(
imc
=
idev
->
mc_list
;
imc
;
imc
=
imc
->
next
)
{
struct
ip6_sf_list
*
psf
;
unsigned
long
i
;
spin_lock_bh
(
&
imc
->
mca_lock
);
for
(
psf
=
imc
->
mca_sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
"%32s %32s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"Multicast Address"
,
"Source Address"
,
"INC"
,
"EXC"
);
first
=
0
;
}
len
+=
sprintf
(
buffer
+
len
,
"%3d %6.6s "
,
dev
->
ifindex
,
dev
->
name
);
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
imc
->
mca_addr
.
s6_addr
[
i
]);
buffer
[
len
++
]
=
' '
;
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
psf
->
sf_addr
.
s6_addr
[
i
]);
len
+=
sprintf
(
buffer
+
len
,
" %6lu %6lu
\n
"
,
psf
->
sf_count
[
MCAST_INCLUDE
],
psf
->
sf_count
[
MCAST_EXCLUDE
]);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
{
spin_unlock_bh
(
&
imc
->
mca_lock
);
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
goto
done
;
}
for
(
state
->
dev
=
dev_base
,
state
->
idev
=
NULL
,
state
->
im
=
NULL
;
state
->
dev
;
state
->
dev
=
state
->
dev
->
next
)
{
struct
inet6_dev
*
idev
;
idev
=
in6_dev_get
(
state
->
dev
);
if
(
unlikely
(
idev
==
NULL
))
continue
;
read_lock_bh
(
&
idev
->
lock
);
im
=
idev
->
mc_list
;
if
(
likely
(
im
!=
NULL
))
{
spin_lock_bh
(
&
im
->
mca_lock
);
psf
=
im
->
mca_sources
;
if
(
likely
(
psf
!=
NULL
))
{
state
->
im
=
im
;
state
->
idev
=
idev
;
break
;
}
spin_unlock_bh
(
&
im
c
->
mca_lock
);
spin_unlock_bh
(
&
im
->
mca_lock
);
}
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
}
*
eof
=
1
;
return
psf
;
}
static
struct
ip6_sf_list
*
igmp6_mcf_get_next
(
struct
seq_file
*
seq
,
struct
ip6_sf_list
*
psf
)
{
struct
igmp6_mcf_iter_state
*
state
=
igmp6_mcf_seq_private
(
seq
);
psf
=
psf
->
sf_next
;
while
(
!
psf
)
{
spin_unlock_bh
(
&
state
->
im
->
mca_lock
);
state
->
im
=
state
->
im
->
next
;
while
(
!
state
->
im
)
{
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
state
->
dev
=
state
->
dev
->
next
;
if
(
!
state
->
dev
)
{
state
->
idev
=
NULL
;
goto
out
;
}
state
->
idev
=
in6_dev_get
(
state
->
dev
);
if
(
!
state
->
idev
)
continue
;
read_lock_bh
(
&
state
->
idev
->
lock
);
state
->
im
=
state
->
idev
->
mc_list
;
}
if
(
!
state
->
im
)
break
;
spin_lock_bh
(
&
state
->
im
->
mca_lock
);
psf
=
state
->
im
->
mca_sources
;
}
out:
return
psf
;
}
done:
static
struct
ip6_sf_list
*
igmp6_mcf_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
ip6_sf_list
*
psf
=
igmp6_mcf_get_first
(
seq
);
if
(
psf
)
while
(
pos
&&
(
psf
=
igmp6_mcf_get_next
(
seq
,
psf
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
psf
;
}
static
void
*
igmp6_mcf_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
return
*
pos
?
igmp6_mcf_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
static
void
*
igmp6_mcf_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ip6_sf_list
*
psf
;
if
(
v
==
(
void
*
)
1
)
psf
=
igmp6_mcf_get_first
(
seq
);
else
psf
=
igmp6_mcf_get_next
(
seq
,
v
);
++*
pos
;
return
psf
;
}
static
void
igmp6_mcf_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
igmp6_mcf_iter_state
*
state
=
igmp6_mcf_seq_private
(
seq
);
if
(
likely
(
state
->
im
!=
NULL
))
spin_unlock_bh
(
&
state
->
im
->
mca_lock
);
if
(
likely
(
state
->
idev
!=
NULL
))
{
read_unlock_bh
(
&
state
->
idev
->
lock
);
in6_dev_put
(
state
->
idev
);
}
read_unlock
(
&
dev_base_lock
);
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
int
igmp6_mcf_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
ip6_sf_list
*
psf
=
(
struct
ip6_sf_list
*
)
v
;
struct
igmp6_mcf_iter_state
*
state
=
igmp6_mcf_seq_private
(
seq
);
if
(
v
==
(
void
*
)
1
)
{
seq_printf
(
seq
,
"%3s %6s "
"%32s %32s %6s %6s
\n
"
,
"Idx"
,
"Device"
,
"Multicast Address"
,
"Source Address"
,
"INC"
,
"EXC"
);
}
else
{
seq_printf
(
seq
,
"%3d %6.6s "
"%04x%04x%04x%04x%04x%04x%04x%04x "
"%04x%04x%04x%04x%04x%04x%04x%04x "
"%6lu %6lu
\n
"
,
state
->
dev
->
ifindex
,
state
->
dev
->
name
,
NIP6
(
state
->
im
->
mca_addr
),
NIP6
(
psf
->
sf_addr
),
psf
->
sf_count
[
MCAST_INCLUDE
],
psf
->
sf_count
[
MCAST_EXCLUDE
]);
}
return
0
;
}
static
struct
seq_operations
igmp6_mcf_seq_ops
=
{
.
start
=
igmp6_mcf_seq_start
,
.
next
=
igmp6_mcf_seq_next
,
.
stop
=
igmp6_mcf_seq_stop
,
.
show
=
igmp6_mcf_seq_show
,
};
static
int
igmp6_mcf_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
igmp6_mcf_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
igmp6_mcf_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
igmp6_mcf_seq_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
igmp6_mcf_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
#endif
int
__init
igmp6_init
(
struct
net_proto_family
*
ops
)
...
...
@@ -2178,6 +2358,9 @@ int __init igmp6_init(struct net_proto_family *ops)
struct
ipv6_pinfo
*
np
;
struct
sock
*
sk
;
int
err
;
#ifdef CONFIG_PROC_FS
struct
proc_dir_entry
*
p
;
#endif
err
=
sock_create
(
PF_INET6
,
SOCK_RAW
,
IPPROTO_ICMPV6
,
&
igmp6_socket
);
if
(
err
<
0
)
{
...
...
@@ -2194,9 +2377,14 @@ int __init igmp6_init(struct net_proto_family *ops)
np
=
inet6_sk
(
sk
);
np
->
hop_limit
=
1
;
#ifdef CONFIG_PROC_FS
create_proc_read_entry
(
"net/igmp6"
,
0
,
0
,
igmp6_read_proc
,
NULL
);
create_proc_read_entry
(
"net/mcfilter6"
,
0
,
0
,
ip6_mcf_read_proc
,
NULL
);
p
=
create_proc_entry
(
"igmp6"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
igmp6_mc_seq_fops
;
p
=
create_proc_entry
(
"mcfilter6"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
igmp6_mcf_seq_fops
;
#endif
return
0
;
...
...
@@ -2207,6 +2395,7 @@ void igmp6_cleanup(void)
sock_release
(
igmp6_socket
);
igmp6_socket
=
NULL
;
/* for safety */
#ifdef CONFIG_PROC_FS
remove_proc_entry
(
"net/igmp6"
,
0
);
proc_net_remove
(
"mcfilter6"
);
proc_net_remove
(
"igmp6"
);
#endif
}
net/ipv6/ndisc.c
View file @
d524ab44
...
...
@@ -884,7 +884,6 @@ static void ndisc_recv_ns(struct sk_buff *skb)
in6_dev_put
(
idev
);
}
else
{
struct
inet6_dev
*
in6_dev
=
in6_dev_get
(
dev
);
int
addr_type
=
ipv6_addr_type
(
saddr
);
if
(
in6_dev
&&
in6_dev
->
cnf
.
forwarding
&&
(
addr_type
&
IPV6_ADDR_UNICAST
)
&&
...
...
net/ipv6/raw.c
View file @
d524ab44
...
...
@@ -1029,7 +1029,22 @@ static struct seq_operations raw6_seq_ops = {
static
int
raw6_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
raw6_seq_ops
);
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
raw6_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
raw6_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
raw6_seq_fops
=
{
...
...
@@ -1037,7 +1052,7 @@ static struct file_operations raw6_seq_fops = {
.
open
=
raw6_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
.
release
=
seq_release
_private
,
};
int
__init
raw6_proc_init
(
void
)
...
...
net/ipv6/tcp_ipv6.c
View file @
d524ab44
...
...
@@ -93,43 +93,6 @@ static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
return
tcp_v6_hashfn
(
laddr
,
lport
,
faddr
,
fport
);
}
static
inline
int
ipv6_rcv_saddr_equal
(
struct
sock
*
sk
,
struct
sock
*
sk2
)
{
struct
ipv6_pinfo
*
np
=
inet6_sk
(
sk
);
int
addr_type
=
ipv6_addr_type
(
&
np
->
rcv_saddr
);
if
(
!
inet_sk
(
sk2
)
->
rcv_saddr
&&
!
ipv6_only_sock
(
sk
))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
ipv6_addr_any
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
&&
!
(
ipv6_only_sock
(
sk2
)
&&
addr_type
==
IPV6_ADDR_MAPPED
))
return
1
;
if
(
addr_type
==
IPV6_ADDR_ANY
&&
(
!
ipv6_only_sock
(
sk
)
||
!
(
sk2
->
sk_family
==
AF_INET6
?
(
ipv6_addr_type
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
==
IPV6_ADDR_MAPPED
)
:
1
)))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
!
ipv6_addr_cmp
(
&
np
->
rcv_saddr
,
(
sk2
->
sk_state
!=
TCP_TIME_WAIT
?
&
inet6_sk
(
sk2
)
->
rcv_saddr
:
&
((
struct
tcp_tw_bucket
*
)
sk
)
->
tw_v6_rcv_saddr
)))
return
1
;
if
(
addr_type
==
IPV6_ADDR_MAPPED
&&
!
ipv6_only_sock
(
sk2
)
&&
(
!
inet_sk
(
sk2
)
->
rcv_saddr
||
!
inet_sk
(
sk
)
->
rcv_saddr
||
inet_sk
(
sk
)
->
rcv_saddr
==
inet_sk
(
sk2
)
->
rcv_saddr
))
return
1
;
return
0
;
}
static
inline
int
tcp_v6_bind_conflict
(
struct
sock
*
sk
,
struct
tcp_bind_bucket
*
tb
)
{
...
...
net/ipv6/udp.c
View file @
d524ab44
...
...
@@ -59,43 +59,6 @@
DEFINE_SNMP_STAT
(
struct
udp_mib
,
udp_stats_in6
);
/* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put
* XXX it somewhere common. -DaveM
*/
static
__inline__
int
udv6_rcv_saddr_equal
(
struct
sock
*
sk
,
struct
sock
*
sk2
)
{
struct
ipv6_pinfo
*
np
=
inet6_sk
(
sk
);
int
addr_type
=
ipv6_addr_type
(
&
np
->
rcv_saddr
);
if
(
!
inet_sk
(
sk2
)
->
rcv_saddr
&&
!
ipv6_only_sock
(
sk
))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
ipv6_addr_any
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
&&
!
(
ipv6_only_sock
(
sk2
)
&&
addr_type
==
IPV6_ADDR_MAPPED
))
return
1
;
if
(
addr_type
==
IPV6_ADDR_ANY
&&
(
!
ipv6_only_sock
(
sk
)
||
!
(
sk2
->
sk_family
==
AF_INET6
?
(
ipv6_addr_type
(
&
inet6_sk
(
sk2
)
->
rcv_saddr
)
==
IPV6_ADDR_MAPPED
)
:
1
)))
return
1
;
if
(
sk2
->
sk_family
==
AF_INET6
&&
!
ipv6_addr_cmp
(
&
inet6_sk
(
sk
)
->
rcv_saddr
,
&
inet6_sk
(
sk2
)
->
rcv_saddr
))
return
1
;
if
(
addr_type
==
IPV6_ADDR_MAPPED
&&
!
ipv6_only_sock
(
sk2
)
&&
(
!
inet_sk
(
sk2
)
->
rcv_saddr
||
!
inet_sk
(
sk
)
->
rcv_saddr
||
inet_sk
(
sk
)
->
rcv_saddr
==
inet_sk
(
sk2
)
->
rcv_saddr
))
return
1
;
return
0
;
}
/* Grrr, addr_type already calculated by caller, but I don't want
* to add some silly "cookie" argument to this method just for that.
*/
...
...
@@ -151,7 +114,7 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum)
sk2
!=
sk
&&
sk2
->
sk_bound_dev_if
==
sk
->
sk_bound_dev_if
&&
(
!
sk2
->
sk_reuse
||
!
sk
->
sk_reuse
)
&&
ud
v6_rcv_saddr_equal
(
sk
,
sk2
))
ip
v6_rcv_saddr_equal
(
sk
,
sk2
))
goto
fail
;
}
}
...
...
net/ipv6/xfrm6_input.c
View file @
d524ab44
...
...
@@ -67,10 +67,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
xfrm_vec
[
xfrm_nr
++
].
xvec
=
x
;
iph
=
skb
->
nh
.
ipv6h
;
if
(
x
->
props
.
mode
)
{
/* XXX */
if
(
iph
->
nexthdr
!=
IPPROTO_IPV6
)
if
(
nexthdr
!=
IPPROTO_IPV6
)
goto
drop
;
skb
->
nh
.
raw
=
skb
->
data
;
iph
=
skb
->
nh
.
ipv6h
;
...
...
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