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
7cbca67c
Commit
7cbca67c
authored
Mar 25, 2008
by
YOSHIFUJI Hideaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV6]: Support Source Address Selection API (RFC5014).
Signed-off-by:
YOSHIFUJI Hideaki
<
yoshfuji@linux-ipv6.org
>
parent
1d5d236d
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
146 additions
and
13 deletions
+146
-13
include/linux/in6.h
include/linux/in6.h
+11
-0
include/linux/ipv6.h
include/linux/ipv6.h
+5
-1
include/net/addrconf.h
include/net/addrconf.h
+1
-0
include/net/ip6_route.h
include/net/ip6_route.h
+6
-3
net/ipv6/addrconf.c
net/ipv6/addrconf.c
+14
-3
net/ipv6/fib6_rules.c
net/ipv6/fib6_rules.c
+11
-1
net/ipv6/ip6_output.c
net/ipv6/ip6_output.c
+3
-1
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_sockglue.c
+78
-0
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+3
-1
net/ipv6/route.c
net/ipv6/route.c
+10
-1
net/ipv6/xfrm6_policy.c
net/ipv6/xfrm6_policy.c
+1
-1
net/sctp/ipv6.c
net/sctp/ipv6.c
+3
-1
No files found.
include/linux/in6.h
View file @
7cbca67c
...
...
@@ -249,4 +249,15 @@ struct in6_flowlabel_req
* IP6T_SO_GET_REVISION_TARGET 69
*/
/* RFC5014: Source address selection */
#define IPV6_ADDR_PREFERENCES 72
#define IPV6_PREFER_SRC_TMP 0x0001
#define IPV6_PREFER_SRC_PUBLIC 0x0002
#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100
#define IPV6_PREFER_SRC_COA 0x0004
#define IPV6_PREFER_SRC_HOME 0x0400
#define IPV6_PREFER_SRC_CGA 0x0008
#define IPV6_PREFER_SRC_NONCGA 0x0800
#endif
include/linux/ipv6.h
View file @
7cbca67c
...
...
@@ -322,7 +322,11 @@ struct ipv6_pinfo {
__u8
recverr
:
1
,
sndflow:
1
,
pmtudisc:
2
,
ipv6only:
1
;
ipv6only:
1
,
srcprefs:
3
;
/* 001: prefer temporary address
* 010: prefer public address
* 100: prefer care-of address
*/
__u8
tclass
;
__u32
dst_cookie
;
...
...
include/net/addrconf.h
View file @
7cbca67c
...
...
@@ -78,6 +78,7 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
extern
int
ipv6_dev_get_saddr
(
struct
net_device
*
dev
,
struct
in6_addr
*
daddr
,
unsigned
int
srcprefs
,
struct
in6_addr
*
saddr
);
extern
int
ipv6_get_lladdr
(
struct
net_device
*
dev
,
struct
in6_addr
*
addr
,
...
...
include/net/ip6_route.h
View file @
7cbca67c
...
...
@@ -30,9 +30,12 @@ struct route_info {
#include <linux/ip.h>
#include <linux/ipv6.h>
#define RT6_LOOKUP_F_IFACE 0x1
#define RT6_LOOKUP_F_REACHABLE 0x2
#define RT6_LOOKUP_F_HAS_SADDR 0x4
#define RT6_LOOKUP_F_IFACE 0x00000001
#define RT6_LOOKUP_F_REACHABLE 0x00000002
#define RT6_LOOKUP_F_HAS_SADDR 0x00000004
#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008
#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
extern
struct
rt6_info
*
ip6_null_entry
;
...
...
net/ipv6/addrconf.c
View file @
7cbca67c
...
...
@@ -909,6 +909,7 @@ struct ipv6_saddr_dst {
int
ifindex
;
int
scope
;
int
label
;
unsigned
int
prefs
;
};
static
inline
int
ipv6_saddr_preferred
(
int
type
)
...
...
@@ -984,9 +985,12 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
break
;
#ifdef CONFIG_IPV6_MIP6
case
IPV6_SADDR_RULE_HOA
:
{
/* Rule 4: Prefer home address */
ret
=
!!
(
score
->
ifa
->
flags
&
IFA_F_HOMEADDRESS
);
int
prefhome
=
!
(
dst
->
prefs
&
IPV6_PREFER_SRC_COA
);
ret
=
!
(
score
->
ifa
->
flags
&
IFA_F_HOMEADDRESS
)
^
prefhome
;
break
;
}
#endif
case
IPV6_SADDR_RULE_OIF
:
/* Rule 5: Prefer outgoing interface */
...
...
@@ -1000,11 +1004,16 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
break
;
#ifdef CONFIG_IPV6_PRIVACY
case
IPV6_SADDR_RULE_PRIVACY
:
{
/* Rule 7: Prefer public address
* Note: prefer temprary address if use_tempaddr >= 2
*/
ret
=
(
!
(
score
->
ifa
->
flags
&
IFA_F_TEMPORARY
))
^
(
score
->
ifa
->
idev
->
cnf
.
use_tempaddr
>=
2
);
int
preftmp
=
dst
->
prefs
&
(
IPV6_PREFER_SRC_PUBLIC
|
IPV6_PREFER_SRC_TMP
)
?
!!
(
dst
->
prefs
&
IPV6_PREFER_SRC_TMP
)
:
score
->
ifa
->
idev
->
cnf
.
use_tempaddr
>=
2
;
ret
=
(
!
(
score
->
ifa
->
flags
&
IFA_F_TEMPORARY
))
^
preftmp
;
break
;
}
#endif
case
IPV6_SADDR_RULE_ORCHID
:
/* Rule 8-: Prefer ORCHID vs ORCHID or
...
...
@@ -1030,7 +1039,8 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
}
int
ipv6_dev_get_saddr
(
struct
net_device
*
dst_dev
,
struct
in6_addr
*
daddr
,
struct
in6_addr
*
saddr
)
struct
in6_addr
*
daddr
,
unsigned
int
prefs
,
struct
in6_addr
*
saddr
)
{
struct
ipv6_saddr_score
scores
[
2
],
*
score
=
&
scores
[
0
],
*
hiscore
=
&
scores
[
1
];
...
...
@@ -1044,6 +1054,7 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev,
dst
.
ifindex
=
dst_dev
?
dst_dev
->
ifindex
:
0
;
dst
.
scope
=
__ipv6_addr_src_scope
(
dst_type
);
dst
.
label
=
ipv6_addr_label
(
daddr
,
dst_type
,
dst
.
ifindex
);
dst
.
prefs
=
prefs
;
hiscore
->
rule
=
-
1
;
hiscore
->
ifa
=
NULL
;
...
...
net/ipv6/fib6_rules.c
View file @
7cbca67c
...
...
@@ -84,8 +84,18 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
if
((
rule
->
flags
&
FIB_RULE_FIND_SADDR
)
&&
r
->
src
.
plen
&&
!
(
flags
&
RT6_LOOKUP_F_HAS_SADDR
))
{
struct
in6_addr
saddr
;
unsigned
int
srcprefs
=
0
;
if
(
flags
&
RT6_LOOKUP_F_SRCPREF_TMP
)
srcprefs
|=
IPV6_PREFER_SRC_TMP
;
if
(
flags
&
RT6_LOOKUP_F_SRCPREF_PUBLIC
)
srcprefs
|=
IPV6_PREFER_SRC_PUBLIC
;
if
(
flags
&
RT6_LOOKUP_F_SRCPREF_COA
)
srcprefs
|=
IPV6_PREFER_SRC_COA
;
if
(
ipv6_dev_get_saddr
(
ip6_dst_idev
(
&
rt
->
u
.
dst
)
->
dev
,
&
flp
->
fl6_dst
,
&
saddr
))
&
flp
->
fl6_dst
,
srcprefs
,
&
saddr
))
goto
again
;
if
(
!
ipv6_prefix_equal
(
&
saddr
,
&
r
->
src
.
addr
,
r
->
src
.
plen
))
...
...
net/ipv6/ip6_output.c
View file @
7cbca67c
...
...
@@ -920,7 +920,9 @@ static int ip6_dst_lookup_tail(struct sock *sk,
if
(
ipv6_addr_any
(
&
fl
->
fl6_src
))
{
err
=
ipv6_dev_get_saddr
(
ip6_dst_idev
(
*
dst
)
->
dev
,
&
fl
->
fl6_dst
,
&
fl
->
fl6_src
);
&
fl
->
fl6_dst
,
sk
?
inet6_sk
(
sk
)
->
srcprefs
:
0
,
&
fl
->
fl6_src
);
if
(
err
)
goto
out_err_release
;
}
...
...
net/ipv6/ipv6_sockglue.c
View file @
7cbca67c
...
...
@@ -617,7 +617,67 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
retv
=
xfrm_user_policy
(
sk
,
optname
,
optval
,
optlen
);
break
;
case
IPV6_ADDR_PREFERENCES
:
{
unsigned
int
pref
=
0
;
unsigned
int
prefmask
=
~
0
;
retv
=
-
EINVAL
;
/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
switch
(
val
&
(
IPV6_PREFER_SRC_PUBLIC
|
IPV6_PREFER_SRC_TMP
|
IPV6_PREFER_SRC_PUBTMP_DEFAULT
))
{
case
IPV6_PREFER_SRC_PUBLIC
:
pref
|=
IPV6_PREFER_SRC_PUBLIC
;
break
;
case
IPV6_PREFER_SRC_TMP
:
pref
|=
IPV6_PREFER_SRC_TMP
;
break
;
case
IPV6_PREFER_SRC_PUBTMP_DEFAULT
:
break
;
case
0
:
goto
pref_skip_pubtmp
;
default:
goto
e_inval
;
}
prefmask
&=
~
(
IPV6_PREFER_SRC_PUBLIC
|
IPV6_PREFER_SRC_TMP
);
pref_skip_pubtmp:
/* check HOME/COA conflicts */
switch
(
val
&
(
IPV6_PREFER_SRC_HOME
|
IPV6_PREFER_SRC_COA
))
{
case
IPV6_PREFER_SRC_HOME
:
break
;
case
IPV6_PREFER_SRC_COA
:
pref
|=
IPV6_PREFER_SRC_COA
;
case
0
:
goto
pref_skip_coa
;
default:
goto
e_inval
;
}
prefmask
&=
~
IPV6_PREFER_SRC_COA
;
pref_skip_coa:
/* check CGA/NONCGA conflicts */
switch
(
val
&
(
IPV6_PREFER_SRC_CGA
|
IPV6_PREFER_SRC_NONCGA
))
{
case
IPV6_PREFER_SRC_CGA
:
case
IPV6_PREFER_SRC_NONCGA
:
case
0
:
break
;
default:
goto
e_inval
;
}
np
->
srcprefs
=
(
np
->
srcprefs
&
prefmask
)
|
pref
;
retv
=
0
;
break
;
}
}
release_sock
(
sk
);
return
retv
;
...
...
@@ -932,6 +992,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
val
=
np
->
sndflow
;
break
;
case
IPV6_ADDR_PREFERENCES
:
val
=
0
;
if
(
np
->
srcprefs
&
IPV6_PREFER_SRC_TMP
)
val
|=
IPV6_PREFER_SRC_TMP
;
else
if
(
np
->
srcprefs
&
IPV6_PREFER_SRC_PUBLIC
)
val
|=
IPV6_PREFER_SRC_PUBLIC
;
else
{
/* XXX: should we return system default? */
val
|=
IPV6_PREFER_SRC_PUBTMP_DEFAULT
;
}
if
(
np
->
srcprefs
&
IPV6_PREFER_SRC_COA
)
val
|=
IPV6_PREFER_SRC_COA
;
else
val
|=
IPV6_PREFER_SRC_HOME
;
break
;
default:
return
-
ENOPROTOOPT
;
}
...
...
net/ipv6/ndisc.c
View file @
7cbca67c
...
...
@@ -546,7 +546,9 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
override
=
0
;
in6_ifa_put
(
ifp
);
}
else
{
if
(
ipv6_dev_get_saddr
(
dev
,
daddr
,
&
tmpaddr
))
if
(
ipv6_dev_get_saddr
(
dev
,
daddr
,
inet6_sk
(
dev
->
nd_net
->
ipv6
.
ndisc_sk
)
->
srcprefs
,
&
tmpaddr
))
return
;
src_addr
=
&
tmpaddr
;
}
...
...
net/ipv6/route.c
View file @
7cbca67c
...
...
@@ -782,6 +782,15 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
if
(
!
ipv6_addr_any
(
&
fl
->
fl6_src
))
flags
|=
RT6_LOOKUP_F_HAS_SADDR
;
else
if
(
sk
)
{
unsigned
int
prefs
=
inet6_sk
(
sk
)
->
srcprefs
;
if
(
prefs
&
IPV6_PREFER_SRC_TMP
)
flags
|=
RT6_LOOKUP_F_SRCPREF_TMP
;
if
(
prefs
&
IPV6_PREFER_SRC_PUBLIC
)
flags
|=
RT6_LOOKUP_F_SRCPREF_PUBLIC
;
if
(
prefs
&
IPV6_PREFER_SRC_COA
)
flags
|=
RT6_LOOKUP_F_SRCPREF_COA
;
}
return
fib6_rule_lookup
(
net
,
fl
,
flags
,
ip6_pol_route_output
);
}
...
...
@@ -2162,7 +2171,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
else
if
(
dst
)
{
struct
in6_addr
saddr_buf
;
if
(
ipv6_dev_get_saddr
(
ip6_dst_idev
(
&
rt
->
u
.
dst
)
->
dev
,
dst
,
&
saddr_buf
)
==
0
)
dst
,
0
,
&
saddr_buf
)
==
0
)
NLA_PUT
(
skb
,
RTA_PREFSRC
,
16
,
&
saddr_buf
);
}
...
...
net/ipv6/xfrm6_policy.c
View file @
7cbca67c
...
...
@@ -58,7 +58,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
return
-
EHOSTUNREACH
;
ipv6_dev_get_saddr
(
ip6_dst_idev
(
dst
)
->
dev
,
(
struct
in6_addr
*
)
&
daddr
->
a6
,
(
struct
in6_addr
*
)
&
daddr
->
a6
,
0
,
(
struct
in6_addr
*
)
&
saddr
->
a6
);
dst_release
(
dst
);
return
0
;
...
...
net/sctp/ipv6.c
View file @
7cbca67c
...
...
@@ -316,7 +316,9 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
if
(
!
asoc
)
{
ipv6_dev_get_saddr
(
dst
?
ip6_dst_idev
(
dst
)
->
dev
:
NULL
,
&
daddr
->
v6
.
sin6_addr
,
&
saddr
->
v6
.
sin6_addr
);
&
daddr
->
v6
.
sin6_addr
,
inet6_sk
(
asoc
->
base
.
sk
)
->
srcprefs
,
&
saddr
->
v6
.
sin6_addr
);
SCTP_DEBUG_PRINTK
(
"saddr from ipv6_get_saddr: "
NIP6_FMT
"
\n
"
,
NIP6
(
saddr
->
v6
.
sin6_addr
));
return
;
...
...
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