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
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