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
453c5e30
Commit
453c5e30
authored
Mar 19, 2003
by
David Stevens
Committed by
David S. Miller
Mar 19, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV6]: Add anycast support.
parent
6d6ce30e
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
836 additions
and
54 deletions
+836
-54
include/linux/in6.h
include/linux/in6.h
+4
-0
include/linux/ipv6.h
include/linux/ipv6.h
+1
-0
include/linux/netdevice.h
include/linux/netdevice.h
+4
-0
include/net/addrconf.h
include/net/addrconf.h
+28
-0
include/net/if_inet6.h
include/net/if_inet6.h
+20
-0
net/core/dev.c
net/core/dev.c
+44
-0
net/ipv6/Makefile
net/ipv6/Makefile
+1
-1
net/ipv6/addrconf.c
net/ipv6/addrconf.c
+152
-48
net/ipv6/af_inet6.c
net/ipv6/af_inet6.c
+9
-0
net/ipv6/anycast.c
net/ipv6/anycast.c
+489
-0
net/ipv6/icmp.c
net/ipv6/icmp.c
+2
-1
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_sockglue.c
+18
-0
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+62
-4
net/netsyms.c
net/netsyms.c
+2
-0
No files found.
include/linux/in6.h
View file @
453c5e30
...
...
@@ -65,6 +65,8 @@ struct ipv6_mreq {
int
ipv6mr_ifindex
;
};
#define ipv6mr_acaddr ipv6mr_multiaddr
struct
in6_flowlabel_req
{
struct
in6_addr
flr_dst
;
...
...
@@ -166,6 +168,8 @@ struct in6_flowlabel_req
#define IPV6_MTU 24
#define IPV6_RECVERR 25
#define IPV6_V6ONLY 26
#define IPV6_JOIN_ANYCAST 27
#define IPV6_LEAVE_ANYCAST 28
/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT 0
...
...
include/linux/ipv6.h
View file @
453c5e30
...
...
@@ -172,6 +172,7 @@ struct ipv6_pinfo {
ipv6only:
1
;
struct
ipv6_mc_socklist
*
ipv6_mc_list
;
struct
ipv6_ac_socklist
*
ipv6_ac_list
;
struct
ipv6_fl_socklist
*
ipv6_fl_list
;
__u32
dst_cookie
;
...
...
include/linux/netdevice.h
View file @
453c5e30
...
...
@@ -469,6 +469,10 @@ extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr);
extern
void
dev_add_pack
(
struct
packet_type
*
pt
);
extern
void
dev_remove_pack
(
struct
packet_type
*
pt
);
extern
int
dev_get
(
const
char
*
name
);
extern
struct
net_device
*
dev_get_by_flags
(
unsigned
short
flags
,
unsigned
short
mask
);
extern
struct
net_device
*
__dev_get_by_flags
(
unsigned
short
flags
,
unsigned
short
mask
);
extern
struct
net_device
*
dev_get_by_name
(
const
char
*
name
);
extern
struct
net_device
*
__dev_get_by_name
(
const
char
*
name
);
extern
struct
net_device
*
dev_alloc
(
const
char
*
name
,
int
*
err
);
...
...
include/net/addrconf.h
View file @
453c5e30
...
...
@@ -63,7 +63,15 @@ extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
extern
int
ipv6_get_saddr
(
struct
dst_entry
*
dst
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
);
extern
int
ipv6_dev_get_saddr
(
struct
net_device
*
dev
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
,
int
onlink
);
extern
int
ipv6_get_lladdr
(
struct
net_device
*
dev
,
struct
in6_addr
*
);
extern
void
addrconf_join_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
extern
void
addrconf_leave_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
/*
* multicast prototypes (mcast.c)
...
...
@@ -93,6 +101,26 @@ extern int ipv6_chk_mcast_addr(struct net_device *dev,
extern
void
addrconf_prefix_rcv
(
struct
net_device
*
dev
,
u8
*
opt
,
int
len
);
/*
* anycast prototypes (anycast.c)
*/
extern
int
ipv6_sock_ac_join
(
struct
sock
*
sk
,
int
ifindex
,
struct
in6_addr
*
addr
);
extern
int
ipv6_sock_ac_drop
(
struct
sock
*
sk
,
int
ifindex
,
struct
in6_addr
*
addr
);
extern
void
ipv6_sock_ac_close
(
struct
sock
*
sk
);
extern
int
inet6_ac_check
(
struct
sock
*
sk
,
struct
in6_addr
*
addr
,
int
ifindex
);
extern
int
ipv6_dev_ac_inc
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
extern
int
ipv6_dev_ac_dec
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
extern
int
ipv6_chk_acast_addr
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
);
/* Device notifier */
extern
int
register_inet6addr_notifier
(
struct
notifier_block
*
nb
);
extern
int
unregister_inet6addr_notifier
(
struct
notifier_block
*
nb
);
...
...
include/net/if_inet6.h
View file @
453c5e30
...
...
@@ -75,6 +75,25 @@ struct ifmcaddr6
spinlock_t
mca_lock
;
};
/* Anycast stuff */
struct
ipv6_ac_socklist
{
struct
in6_addr
acl_addr
;
int
acl_ifindex
;
struct
ipv6_ac_socklist
*
acl_next
;
};
struct
ifacaddr6
{
struct
in6_addr
aca_addr
;
struct
inet6_dev
*
aca_idev
;
struct
ifacaddr6
*
aca_next
;
int
aca_users
;
atomic_t
aca_refcnt
;
spinlock_t
aca_lock
;
};
#define IFA_HOST IPV6_ADDR_LOOPBACK
#define IFA_LINK IPV6_ADDR_LINKLOCAL
#define IFA_SITE IPV6_ADDR_SITELOCAL
...
...
@@ -108,6 +127,7 @@ struct inet6_dev
struct
inet6_ifaddr
*
addr_list
;
struct
ifmcaddr6
*
mc_list
;
struct
ifacaddr6
*
ac_list
;
rwlock_t
lock
;
atomic_t
refcnt
;
__u32
if_flags
;
...
...
net/core/dev.c
View file @
453c5e30
...
...
@@ -546,6 +546,50 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
return
dev
;
}
/**
* dev_get_by_flags - find any device with given flags
* @if_flags: IFF_* values
* @mask: bitmask of bits in if_flags to check
*
* Search for any interface with the given flags. Returns NULL if a device
* is not found or a pointer to the device. The device returned has
* had a reference added and the pointer is safe until the user calls
* dev_put to indicate they have finished with it.
*/
struct
net_device
*
dev_get_by_flags
(
unsigned
short
if_flags
,
unsigned
short
mask
)
{
struct
net_device
*
dev
;
read_lock
(
&
dev_base_lock
);
dev
=
__dev_get_by_flags
(
if_flags
,
mask
);
if
(
dev
)
dev_hold
(
dev
);
read_unlock
(
&
dev_base_lock
);
return
dev
;
}
/**
* __dev_get_by_flags - find any device with given flags
* @if_flags: IFF_* values
* @mask: bitmask of bits in if_flags to check
*
* Search for any interface with the given flags. Returns NULL if a device
* is not found or a pointer to the device. The caller must hold either
* the RTNL semaphore or @dev_base_lock.
*/
struct
net_device
*
__dev_get_by_flags
(
unsigned
short
if_flags
,
unsigned
short
mask
)
{
struct
net_device
*
dev
;
for
(
dev
=
dev_base
;
dev
!=
NULL
;
dev
=
dev
->
next
)
{
if
(((
dev
->
flags
^
if_flags
)
&
mask
)
==
0
)
return
dev
;
}
return
NULL
;
}
/**
* dev_alloc_name - allocate a name for a device
* @dev: device
...
...
net/ipv6/Makefile
View file @
453c5e30
...
...
@@ -4,7 +4,7 @@
obj-$(CONFIG_IPV6)
+=
ipv6.o
ipv6-objs
:=
af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o
\
ipv6-objs
:=
af_inet6.o
anycast.o
ip6_output.o ip6_input.o addrconf.o sit.o
\
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o
\
protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o
\
exthdrs.o sysctl_net_ipv6.o datagram.o proc.o
\
...
...
net/ipv6/addrconf.c
View file @
453c5e30
...
...
@@ -174,21 +174,15 @@ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
int
ipv6_addr_type
(
struct
in6_addr
*
addr
)
{
int
type
;
u32
st
;
st
=
addr
->
s6_addr32
[
0
];
/* Consider all addresses with the first three bits different of
000 and 111 as unicasts.
*/
if
((
st
&
htonl
(
0xE0000000
))
!=
htonl
(
0x00000000
)
&&
(
st
&
htonl
(
0xE0000000
))
!=
htonl
(
0xE0000000
))
return
IPV6_ADDR_UNICAST
;
if
((
st
&
htonl
(
0xFF000000
))
==
htonl
(
0xFF000000
))
{
int
type
=
IPV6_ADDR_MULTICAST
;
if
((
st
&
__constant_htonl
(
0xFF000000
))
==
__constant_htonl
(
0xFF000000
))
{
type
=
IPV6_ADDR_MULTICAST
;
switch
((
st
&
htonl
(
0x00FF0000
)))
{
switch
((
st
&
__constant_
htonl
(
0x00FF0000
)))
{
case
__constant_htonl
(
0x00010000
):
type
|=
IPV6_ADDR_LOOPBACK
;
break
;
...
...
@@ -203,29 +197,53 @@ int ipv6_addr_type(struct in6_addr *addr)
};
return
type
;
}
/* check for reserved anycast addresses */
if
((
st
&
__constant_htonl
(
0xE0000000
))
&&
((
addr
->
s6_addr32
[
2
]
==
__constant_htonl
(
0xFDFFFFFF
)
&&
(
addr
->
s6_addr32
[
3
]
|
__constant_htonl
(
0x7F
))
==
(
u32
)
~
0
)
||
(
addr
->
s6_addr32
[
2
]
==
0
&&
addr
->
s6_addr32
[
3
]
==
0
)))
type
=
IPV6_ADDR_ANYCAST
;
else
type
=
IPV6_ADDR_UNICAST
;
/* Consider all addresses with the first three bits different of
000 and 111 as finished.
*/
if
((
st
&
__constant_htonl
(
0xE0000000
))
!=
__constant_htonl
(
0x00000000
)
&&
(
st
&
__constant_htonl
(
0xE0000000
))
!=
__constant_htonl
(
0xE0000000
))
return
type
;
if
((
st
&
htonl
(
0xFFC00000
))
==
htonl
(
0xFE800000
))
return
(
IPV6_ADDR_LINKLOCAL
|
IPV6_ADDR_UNICAST
);
if
((
st
&
__constant_htonl
(
0xFFC00000
))
==
__constant_
htonl
(
0xFE800000
))
return
(
IPV6_ADDR_LINKLOCAL
|
type
);
if
((
st
&
htonl
(
0xFFC00000
))
==
htonl
(
0xFEC00000
))
return
(
IPV6_ADDR_SITELOCAL
|
IPV6_ADDR_UNICAST
);
if
((
st
&
__constant_htonl
(
0xFFC00000
))
==
__constant_
htonl
(
0xFEC00000
))
return
(
IPV6_ADDR_SITELOCAL
|
type
);
if
((
addr
->
s6_addr32
[
0
]
|
addr
->
s6_addr32
[
1
])
==
0
)
{
if
(
addr
->
s6_addr32
[
2
]
==
0
)
{
if
(
addr
->
s
6_addr32
[
3
]
==
0
)
if
(
addr
->
in6_u
.
u
6_addr32
[
3
]
==
0
)
return
IPV6_ADDR_ANY
;
if
(
addr
->
s6_addr32
[
3
]
==
htonl
(
0x00000001
))
return
(
IPV6_ADDR_LOOPBACK
|
IPV6_ADDR_UNICAST
);
if
(
addr
->
s6_addr32
[
3
]
==
__constant_
htonl
(
0x00000001
))
return
(
IPV6_ADDR_LOOPBACK
|
type
);
return
(
IPV6_ADDR_COMPATv4
|
IPV6_ADDR_UNICAST
);
return
(
IPV6_ADDR_COMPATv4
|
type
);
}
if
(
addr
->
s6_addr32
[
2
]
==
htonl
(
0x0000ffff
))
if
(
addr
->
s6_addr32
[
2
]
==
__constant_
htonl
(
0x0000ffff
))
return
IPV6_ADDR_MAPPED
;
}
return
IPV6_ADDR_RESERVED
;
st
&=
__constant_htonl
(
0xFF000000
);
if
(
st
==
0
)
return
IPV6_ADDR_RESERVED
;
st
&=
__constant_htonl
(
0xFE000000
);
if
(
st
==
__constant_htonl
(
0x02000000
))
return
IPV6_ADDR_RESERVED
;
/* for NSAP */
if
(
st
==
__constant_htonl
(
0x04000000
))
return
IPV6_ADDR_RESERVED
;
/* for IPX */
return
type
;
}
static
void
addrconf_del_timer
(
struct
inet6_ifaddr
*
ifp
)
...
...
@@ -261,7 +279,6 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
add_timer
(
&
ifp
->
timer
);
}
/* Nobody refers to this device, we may destroy it. */
void
in6_dev_finish_destroy
(
struct
inet6_dev
*
idev
)
...
...
@@ -358,24 +375,91 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
return
idev
;
}
void
ipv6_addr_prefix
(
struct
in6_addr
*
prefix
,
struct
in6_addr
*
addr
,
int
prefix_len
)
{
unsigned
long
mask
;
int
ncopy
,
nbits
;
memset
(
prefix
,
0
,
sizeof
(
*
prefix
));
if
(
prefix_len
<=
0
)
return
;
if
(
prefix_len
>
128
)
prefix_len
=
128
;
ncopy
=
prefix_len
/
32
;
switch
(
ncopy
)
{
case
4
:
prefix
->
s6_addr32
[
3
]
=
addr
->
s6_addr32
[
3
];
case
3
:
prefix
->
s6_addr32
[
2
]
=
addr
->
s6_addr32
[
2
];
case
2
:
prefix
->
s6_addr32
[
1
]
=
addr
->
s6_addr32
[
1
];
case
1
:
prefix
->
s6_addr32
[
0
]
=
addr
->
s6_addr32
[
0
];
case
0
:
break
;
}
nbits
=
prefix_len
%
32
;
if
(
nbits
==
0
)
return
;
mask
=
~
((
1
<<
(
32
-
nbits
))
-
1
);
mask
=
htonl
(
mask
);
prefix
->
s6_addr32
[
ncopy
]
=
addr
->
s6_addr32
[
ncopy
]
&
mask
;
}
static
void
dev_forward_change
(
struct
inet6_dev
*
idev
)
{
struct
net_device
*
dev
;
struct
inet6_ifaddr
*
ifa
;
struct
in6_addr
addr
;
if
(
!
idev
)
return
;
dev
=
idev
->
dev
;
if
(
dev
&&
(
dev
->
flags
&
IFF_MULTICAST
))
{
ipv6_addr_all_routers
(
&
addr
);
if
(
idev
->
cnf
.
forwarding
)
ipv6_dev_mc_inc
(
dev
,
&
addr
);
else
ipv6_dev_mc_dec
(
dev
,
&
addr
);
}
for
(
ifa
=
idev
->
addr_list
;
ifa
;
ifa
=
ifa
->
if_next
)
{
ipv6_addr_prefix
(
&
addr
,
&
ifa
->
addr
,
ifa
->
prefix_len
);
if
(
addr
.
s6_addr32
[
0
]
==
0
&&
addr
.
s6_addr32
[
1
]
==
0
&&
addr
.
s6_addr32
[
2
]
==
0
&&
addr
.
s6_addr32
[
3
]
==
0
)
continue
;
if
(
idev
->
cnf
.
forwarding
)
ipv6_dev_ac_inc
(
idev
->
dev
,
&
addr
);
else
ipv6_dev_ac_dec
(
idev
->
dev
,
&
addr
);
}
}
static
void
addrconf_forward_change
(
struct
inet6_dev
*
idev
)
{
struct
net_device
*
dev
;
if
(
idev
)
if
(
idev
)
{
dev_forward_change
(
idev
);
return
;
}
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
read_lock
(
&
addrconf_lock
);
idev
=
__in6_dev_get
(
dev
);
if
(
idev
)
if
(
idev
)
{
idev
->
cnf
.
forwarding
=
ipv6_devconf
.
forwarding
;
dev_forward_change
(
idev
);
}
read_unlock
(
&
addrconf_lock
);
}
read_unlock
(
&
dev_base_lock
);
}
/* Nobody refers to this ifaddr, destroy it */
void
inet6_ifa_finish_destroy
(
struct
inet6_ifaddr
*
ifp
)
...
...
@@ -658,30 +742,20 @@ static int inline ipv6_saddr_pref(const struct inet6_ifaddr *ifp, u8 invpref)
#define IPV6_GET_SADDR_MAXSCORE(score) (score)
#endif
int
ipv6_
get_saddr
(
struct
dst_entry
*
dst
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
)
int
ipv6_
dev_get_saddr
(
struct
net_device
*
dev
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
,
int
onlink
)
{
int
scope
;
struct
inet6_ifaddr
*
ifp
=
NULL
;
struct
inet6_ifaddr
*
match
=
NULL
;
struct
net_device
*
dev
=
NULL
;
struct
inet6_dev
*
idev
;
struct
rt6_info
*
rt
;
int
scope
;
int
err
;
int
hiscore
=
-
1
,
score
;
rt
=
(
struct
rt6_info
*
)
dst
;
if
(
rt
)
dev
=
rt
->
rt6i_dev
;
scope
=
ipv6_addr_scope
(
daddr
);
if
(
rt
&&
(
rt
->
rt6i_flags
&
RTF_ALLONLINK
))
{
/*
* route for the "all destinations on link" rule
* when no routers are present
*/
if
(
!
onlink
)
scope
=
ipv6_addr_scope
(
daddr
);
else
scope
=
IFA_LINK
;
}
/*
* known dev
...
...
@@ -782,6 +856,24 @@ int ipv6_get_saddr(struct dst_entry *dst,
return
err
;
}
int
ipv6_get_saddr
(
struct
dst_entry
*
dst
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
)
{
struct
rt6_info
*
rt
;
struct
net_device
*
dev
=
NULL
;
int
onlink
;
rt
=
(
struct
rt6_info
*
)
dst
;
if
(
rt
)
dev
=
rt
->
rt6i_dev
;
onlink
=
(
rt
&&
(
rt
->
rt6i_flags
&
RTF_ALLONLINK
));
return
ipv6_dev_get_saddr
(
dev
,
daddr
,
saddr
,
onlink
);
}
int
ipv6_get_lladdr
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
)
{
struct
inet6_dev
*
idev
;
...
...
@@ -889,7 +981,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
/* Join to solicited addr multicast group. */
static
void
addrconf_join_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
)
void
addrconf_join_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
)
{
struct
in6_addr
maddr
;
...
...
@@ -900,7 +992,7 @@ static void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr)
ipv6_dev_mc_inc
(
dev
,
&
maddr
);
}
static
void
addrconf_leave_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
)
void
addrconf_leave_solict
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
)
{
struct
in6_addr
maddr
;
...
...
@@ -1937,6 +2029,15 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
addrconf_mod_timer
(
ifp
,
AC_RS
,
ifp
->
idev
->
cnf
.
rtr_solicit_interval
);
spin_unlock_bh
(
&
ifp
->
lock
);
}
if
(
ifp
->
idev
->
cnf
.
forwarding
)
{
struct
in6_addr
addr
;
ipv6_addr_prefix
(
&
addr
,
&
ifp
->
addr
,
ifp
->
prefix_len
);
if
(
addr
.
s6_addr32
[
0
]
||
addr
.
s6_addr32
[
1
]
||
addr
.
s6_addr32
[
2
]
||
addr
.
s6_addr32
[
3
])
ipv6_dev_ac_inc
(
ifp
->
idev
->
dev
,
&
addr
);
}
}
#ifdef CONFIG_PROC_FS
...
...
@@ -2267,6 +2368,14 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
break
;
case
RTM_DELADDR
:
addrconf_leave_solict
(
ifp
->
idev
->
dev
,
&
ifp
->
addr
);
if
(
ifp
->
idev
->
cnf
.
forwarding
)
{
struct
in6_addr
addr
;
ipv6_addr_prefix
(
&
addr
,
&
ifp
->
addr
,
ifp
->
prefix_len
);
if
(
addr
.
s6_addr32
[
0
]
||
addr
.
s6_addr32
[
1
]
||
addr
.
s6_addr32
[
2
]
||
addr
.
s6_addr32
[
3
])
ipv6_dev_ac_dec
(
ifp
->
idev
->
dev
,
&
addr
);
}
if
(
!
ipv6_chk_addr
(
&
ifp
->
addr
,
NULL
))
ip6_rt_addr_del
(
&
ifp
->
addr
,
ifp
->
idev
->
dev
);
break
;
...
...
@@ -2289,11 +2398,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
struct
inet6_dev
*
idev
=
NULL
;
if
(
valp
!=
&
ipv6_devconf
.
forwarding
)
{
struct
net_device
*
dev
=
dev_get_by_index
(
ctl
->
ctl_name
);
if
(
dev
)
{
idev
=
in6_dev_get
(
dev
);
dev_put
(
dev
);
}
idev
=
(
struct
inet6_dev
*
)
ctl
->
extra1
;
if
(
idev
==
NULL
)
return
ret
;
}
else
...
...
@@ -2303,8 +2408,6 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
if
(
*
valp
)
rt6_purge_dflt_routers
(
0
);
if
(
idev
)
in6_dev_put
(
idev
);
}
return
ret
;
...
...
@@ -2491,6 +2594,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
for
(
i
=
0
;
t
->
addrconf_vars
[
i
].
data
;
i
++
)
{
t
->
addrconf_vars
[
i
].
data
+=
(
char
*
)
p
-
(
char
*
)
&
ipv6_devconf
;
t
->
addrconf_vars
[
i
].
de
=
NULL
;
t
->
addrconf_vars
[
i
].
extra1
=
idev
;
/* embedded; no ref */
}
if
(
dev
)
{
t
->
addrconf_dev
[
0
].
procname
=
dev
->
name
;
...
...
net/ipv6/af_inet6.c
View file @
453c5e30
...
...
@@ -74,6 +74,7 @@ MODULE_PARM(unloadable, "i");
/* IPv6 procfs goodies... */
#ifdef CONFIG_PROC_FS
extern
int
anycast6_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
raw6_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
tcp6_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
udp6_get_info
(
char
*
,
char
**
,
off_t
,
int
);
...
...
@@ -381,6 +382,9 @@ int inet6_release(struct socket *sock)
/* Free mc lists */
ipv6_sock_mc_close
(
sk
);
/* Free ac lists */
ipv6_sock_ac_close
(
sk
);
return
inet_release
(
sock
);
}
...
...
@@ -785,6 +789,8 @@ static int __init inet6_init(void)
goto
proc_sockstat6_fail
;
if
(
!
proc_net_create
(
"snmp6"
,
0
,
afinet6_get_snmp
))
goto
proc_snmp6_fail
;
if
(
!
proc_net_create
(
"anycast6"
,
0
,
anycast6_get_info
))
goto
proc_anycast6_fail
;
#endif
ipv6_netdev_notif_init
();
ipv6_packet_init
();
...
...
@@ -800,6 +806,8 @@ static int __init inet6_init(void)
return
0
;
#ifdef CONFIG_PROC_FS
proc_anycast6_fail:
proc_net_remove
(
"anycast6"
);
proc_snmp6_fail:
proc_net_remove
(
"sockstat6"
);
proc_sockstat6_fail:
...
...
@@ -837,6 +845,7 @@ static void inet6_exit(void)
proc_net_remove
(
"udp6"
);
proc_net_remove
(
"sockstat6"
);
proc_net_remove
(
"snmp6"
);
proc_net_remove
(
"anycast6"
);
#endif
/* Cleanup code parts. */
sit_cleanup
();
...
...
net/ipv6/anycast.c
0 → 100644
View file @
453c5e30
This diff is collapsed.
Click to expand it.
net/ipv6/icmp.c
View file @
453c5e30
...
...
@@ -369,7 +369,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
saddr
=
&
skb
->
nh
.
ipv6h
->
daddr
;
if
(
ipv6_addr_type
(
saddr
)
&
IPV6_ADDR_MULTICAST
)
if
(
ipv6_addr_type
(
saddr
)
&
IPV6_ADDR_MULTICAST
||
ipv6_chk_acast_addr
(
0
,
saddr
))
saddr
=
NULL
;
msg
.
icmph
.
icmp6_type
=
ICMPV6_ECHO_REPLY
;
...
...
net/ipv6/ipv6_sockglue.c
View file @
453c5e30
...
...
@@ -358,6 +358,24 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
retv
=
ipv6_sock_mc_drop
(
sk
,
mreq
.
ipv6mr_ifindex
,
&
mreq
.
ipv6mr_multiaddr
);
break
;
}
case
IPV6_JOIN_ANYCAST
:
case
IPV6_LEAVE_ANYCAST
:
{
struct
ipv6_mreq
mreq
;
if
(
optlen
!=
sizeof
(
struct
ipv6_mreq
))
goto
e_inval
;
retv
=
-
EFAULT
;
if
(
copy_from_user
(
&
mreq
,
optval
,
sizeof
(
struct
ipv6_mreq
)))
break
;
if
(
optname
==
IPV6_JOIN_ANYCAST
)
retv
=
ipv6_sock_ac_join
(
sk
,
mreq
.
ipv6mr_ifindex
,
&
mreq
.
ipv6mr_acaddr
);
else
retv
=
ipv6_sock_ac_drop
(
sk
,
mreq
.
ipv6mr_ifindex
,
&
mreq
.
ipv6mr_acaddr
);
break
;
}
case
IPV6_ROUTER_ALERT
:
retv
=
ip6_ra_control
(
sk
,
val
,
NULL
);
break
;
...
...
net/ipv6/ndisc.c
View file @
453c5e30
...
...
@@ -413,10 +413,13 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
solicited_addr
,
int
router
,
int
solicited
,
int
override
,
int
inc_opt
)
{
static
struct
in6_addr
tmpaddr
;
struct
inet6_ifaddr
*
ifp
;
struct
flowi
fl
;
struct
rt6_info
*
rt
=
NULL
;
struct
dst_entry
*
dst
;
struct
sock
*
sk
=
ndisc_socket
->
sk
;
struct
in6_addr
*
src_addr
;
struct
nd_msg
*
msg
;
int
len
;
struct
sk_buff
*
skb
;
...
...
@@ -428,7 +431,18 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
if
(
!
rt
)
return
;
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_ADVERTISEMENT
,
solicited_addr
,
daddr
);
/* for anycast or proxy, solicited_addr != src_addr */
ifp
=
ipv6_get_ifaddr
(
solicited_addr
,
dev
);
if
(
ifp
)
{
src_addr
=
solicited_addr
;
in6_ifa_put
(
ifp
);
}
else
{
if
(
ipv6_dev_get_saddr
(
dev
,
daddr
,
&
tmpaddr
,
0
))
return
;
src_addr
=
&
tmpaddr
;
}
ndisc_flow_init
(
&
fl
,
NDISC_NEIGHBOUR_ADVERTISEMENT
,
src_addr
,
daddr
);
ndisc_rt_init
(
rt
,
dev
,
neigh
);
dst
=
(
struct
dst_entry
*
)
rt
;
...
...
@@ -456,7 +470,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
}
skb_reserve
(
skb
,
(
dev
->
hard_header_len
+
15
)
&
~
15
);
ip6_nd_hdr
(
sk
,
skb
,
dev
,
s
olicited
_addr
,
daddr
,
IPPROTO_ICMPV6
,
len
);
ip6_nd_hdr
(
sk
,
skb
,
dev
,
s
rc
_addr
,
daddr
,
IPPROTO_ICMPV6
,
len
);
skb
->
h
.
raw
=
(
unsigned
char
*
)
msg
=
(
struct
nd_msg
*
)
skb_put
(
skb
,
len
);
...
...
@@ -470,13 +484,13 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
msg
->
icmph
.
icmp6_override
=
!!
override
;
/* Set the target address. */
ipv6_addr_copy
(
&
msg
->
target
,
s
olicited
_addr
);
ipv6_addr_copy
(
&
msg
->
target
,
s
rc
_addr
);
if
(
inc_opt
)
ndisc_fill_option
(
msg
->
opt
,
ND_OPT_TARGET_LL_ADDR
,
dev
->
dev_addr
,
dev
->
addr_len
);
/* checksum */
msg
->
icmph
.
icmp6_cksum
=
csum_ipv6_magic
(
s
olicited
_addr
,
daddr
,
len
,
msg
->
icmph
.
icmp6_cksum
=
csum_ipv6_magic
(
s
rc
_addr
,
daddr
,
len
,
IPPROTO_ICMPV6
,
csum_partial
((
__u8
*
)
msg
,
len
,
0
));
...
...
@@ -793,6 +807,50 @@ void ndisc_recv_ns(struct sk_buff *skb)
}
}
in6_ifa_put
(
ifp
);
}
else
if
(
ipv6_chk_acast_addr
(
dev
,
&
msg
->
target
))
{
struct
inet6_dev
*
idev
=
in6_dev_get
(
dev
);
int
addr_type
=
ipv6_addr_type
(
saddr
);
/* anycast */
if
(
!
idev
)
{
/* XXX: count this drop? */
return
0
;
}
if
(
addr_type
==
IPV6_ADDR_ANY
)
{
struct
in6_addr
maddr
;
ipv6_addr_all_nodes
(
&
maddr
);
ndisc_send_na
(
dev
,
NULL
,
&
maddr
,
&
msg
->
target
,
idev
->
cnf
.
forwarding
,
0
,
0
,
1
);
in6_dev_put
(
idev
);
return
0
;
}
if
(
addr_type
&
IPV6_ADDR_UNICAST
)
{
int
inc
=
ipv6_addr_type
(
daddr
)
&
IPV6_ADDR_MULTICAST
;
if
(
inc
)
nd_tbl
.
stats
.
rcv_probes_mcast
++
;
else
nd_tbl
.
stats
.
rcv_probes_ucast
++
;
/*
* update / create cache entry
* for the source adddress
*/
neigh
=
neigh_event_ns
(
&
nd_tbl
,
lladdr
,
saddr
,
skb
->
dev
);
if
(
neigh
||
!
dev
->
hard_header
)
{
ndisc_send_na
(
dev
,
neigh
,
saddr
,
&
msg
->
target
,
idev
->
cnf
.
forwarding
,
1
,
0
,
inc
);
if
(
neigh
)
neigh_release
(
neigh
);
}
}
in6_dev_put
(
idev
);
}
else
{
struct
inet6_dev
*
in6_dev
=
in6_dev_get
(
dev
);
int
addr_type
=
ipv6_addr_type
(
saddr
);
...
...
net/netsyms.c
View file @
453c5e30
...
...
@@ -547,6 +547,8 @@ EXPORT_SYMBOL(register_netdevice);
EXPORT_SYMBOL
(
unregister_netdevice
);
EXPORT_SYMBOL
(
netdev_state_change
);
EXPORT_SYMBOL
(
dev_new_index
);
EXPORT_SYMBOL
(
dev_get_by_flags
);
EXPORT_SYMBOL
(
__dev_get_by_flags
);
EXPORT_SYMBOL
(
dev_get_by_index
);
EXPORT_SYMBOL
(
__dev_get_by_index
);
EXPORT_SYMBOL
(
dev_get_by_name
);
...
...
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