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
48bdef02
Commit
48bdef02
authored
Jun 30, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/jmorris/net-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
317cfe29
92f8b857
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
864 additions
and
339 deletions
+864
-339
include/net/addrconf.h
include/net/addrconf.h
+2
-0
include/net/ip.h
include/net/ip.h
+1
-2
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
+38
-0
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/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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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/ipv4/igmp.c
View file @
48bdef02
...
...
@@ -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
);
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_lock
(
&
in_dev
->
lock
);
for
(
im
=
in_dev
->
mc_list
;
im
;
im
=
im
->
next
)
{
len
+=
sprintf
(
buffer
+
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
);
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
;
return
0
;
}
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
)
{
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
;
};
#define igmp_mcf_seq_private(seq) ((struct igmp_mcf_iter_state *)&seq->private)
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
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
read_unlock_bh
(
&
idev
->
lock
);
}
done:
read_unlock
(
&
dev_base_lock
);
return
psf
;
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
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
;
}
state
->
idev
=
in_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
->
lock
);
psf
=
state
->
im
->
sources
;
}
out:
return
psf
;
}
int
ip_mcf_procinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
struct
ip_sf_list
*
igmp_mcf_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
off_t
pos
=
0
,
begin
=
0
;
int
len
=
0
;
int
first
=
1
;
struct
net_device
*
dev
;
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
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
in_device
*
in_dev
=
in_dev_get
(
dev
);
struct
ip_mc_list
*
imc
;
return
*
pos
?
igmp_mcf_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
if
(
in_dev
==
NULL
)
continue
;
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
;
}
read_lock
(
&
in_dev
->
lock
);
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
);
}
read_unlock
(
&
dev_base_lock
);
}
for
(
imc
=
in_dev
->
mc_list
;
imc
;
imc
=
imc
->
next
)
{
struct
ip_sf_list
*
psf
;
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
);
spin_lock_bh
(
&
imc
->
lock
);
for
(
psf
=
imc
->
sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
if
(
v
==
(
void
*
)
1
)
{
seq_printf
(
seq
,
"%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
),
"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
]);
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
;
}
}
spin_unlock_bh
(
&
imc
->
lock
);
}
read_unlock
(
&
in_dev
->
lock
);
in_dev_put
(
in_dev
);
}
done:
read_unlock
(
&
dev_base_lock
);
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
;
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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>
...
...
@@ -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
)
...
...
net/ipv6/af_inet6.c
View file @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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
;
};
if
((
idev
=
in6_dev_get
(
dev
))
==
NULL
)
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
);
#define ac6_seq_private(seq) ((struct ac6_iter_state *)&seq->private)
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
);
static
inline
struct
ifacaddr6
*
ac6_get_first
(
struct
seq_file
*
seq
)
{
struct
ifacaddr6
*
im
=
NULL
;
struct
ac6_iter_state
*
state
=
ac6_seq_private
(
seq
);
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
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
->
ac_list
;
if
(
im
)
{
state
->
idev
=
idev
;
break
;
}
if
(
pos
>
offset
+
length
)
{
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
goto
done
;
}
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
);
}
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
->
ac_list
;
}
return
im
;
}
done:
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
;
}
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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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
;
struct
inet6_dev
*
idev
;
};
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
#define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)&seq->private)
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
(
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
;
}
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
);
if
((
idev
=
in6_dev_get
(
dev
))
==
NULL
)
im
=
im
->
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
->
mc_list
;
}
return
im
;
}
read_lock_bh
(
&
idev
->
lock
);
for
(
im
=
idev
->
mc_list
;
im
;
im
=
im
->
next
)
{
int
i
;
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
;
}
len
+=
sprintf
(
buffer
+
len
,
"%-4d %-15s "
,
dev
->
ifindex
,
dev
->
name
);
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
);
}
for
(
i
=
0
;
i
<
16
;
i
++
)
len
+=
sprintf
(
buffer
+
len
,
"%02x"
,
im
->
mca_addr
.
s6_addr
[
i
]);
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
;
}
len
+=
sprintf
(
buffer
+
len
,
" %5d %08X %ld
\n
"
,
im
->
mca_users
,
im
->
mca_flags
,
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
);
}
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
;
}
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
;
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
)
{
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
;
struct
inet6_dev
*
idev
;
struct
ifmcaddr6
*
im
;
};
#define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)&seq->private)
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
(
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
->
mca_lock
);
}
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
}
*
eof
=
1
;
done:
read_unlock
(
&
dev_base_lock
);
return
psf
;
}
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
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
;
}
static
int
ip6_mcf_read_proc
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
*
eof
,
void
*
data
)
static
struct
ip6_sf_list
*
igmp6_mcf_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
off_t
pos
=
0
,
begin
=
0
;
int
len
=
0
;
int
first
=
1
;
struct
net_device
*
dev
;
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
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
struct
inet6_dev
*
idev
=
in6_dev_get
(
dev
);
struct
ifmcaddr6
*
imc
;
return
*
pos
?
igmp6_mcf_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
if
(
idev
==
NULL
)
continue
;
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
;
}
read_lock_bh
(
&
idev
->
lock
);
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
);
}
for
(
imc
=
idev
->
mc_list
;
imc
;
imc
=
imc
->
next
)
{
struct
ip6_sf_list
*
psf
;
unsigned
long
i
;
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
);
spin_lock_bh
(
&
imc
->
mca_lock
);
for
(
psf
=
imc
->
mca_sources
;
psf
;
psf
=
psf
->
sf_next
)
{
if
(
first
)
{
len
+=
sprintf
(
buffer
+
len
,
"%3s %6s "
if
(
v
==
(
void
*
)
1
)
{
seq_printf
(
seq
,
"%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
"
,
}
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
]);
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
;
}
}
spin_unlock_bh
(
&
imc
->
mca_lock
);
}
read_unlock_bh
(
&
idev
->
lock
);
in6_dev_put
(
idev
);
}
*
eof
=
1
;
return
0
;
}
done:
read_unlock
(
&
dev_base_lock
);
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
;
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
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/raw.c
View file @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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 @
48bdef02
...
...
@@ -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