From: Lorenzo Colitti <hidden> Date: 2011-10-05 20:16:07
net: ipv6: Allow netlink to set IPv6 address scope
Currently, userspace cannot specify the scope of IPv6
addresses when creating or modifying them. Instead, the
scope is automatically determined from the address itself.
In IPv4, userspace can set whatever scope it likes.
Allow userspace to specify the scope of IPv6 addresses in
a backwards-compatible way: if the scope passed in is zero,
use the old behaviour of automatically determining the
scope based on the address.
Signed-off-by: Lorenzo Colitti <redacted>
@@ -2141,8 +2168,6 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pif(IS_ERR(idev))returnPTR_ERR(idev);-scope=ipv6_addr_scope(pfx);-timeout=addrconf_timeout_fixup(valid_lft,HZ);if(addrconf_finite_timeout(timeout)){expires=jiffies_to_clock_t(timeout*HZ);
@@ -2239,7 +2264,8 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)rtnl_lock();err=inet6_addr_add(net,ireq.ifr6_ifindex,&ireq.ifr6_addr,ireq.ifr6_prefixlen,IFA_F_PERMANENT,-INFINITY_LIFE_TIME,INFINITY_LIFE_TIME);+IPV6_ADDR_ANY,INFINITY_LIFE_TIME,+INFINITY_LIFE_TIME);rtnl_unlock();returnerr;}
@@ -3418,6 +3445,13 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)/* We ignore other flags so far. */ifa_flags=ifm->ifa_flags&(IFA_F_NODAD|IFA_F_HOMEADDRESS);+if(ifm->ifa_scope==RT_SCOPE_UNIVERSE){+/* Be backwards compatible with tools that don't set scope. */+scope=ipv6_addr_scope(pfx);+}else{+scope=ifa_scope(ifm->ifa_scope);+}+ifa=ipv6_get_ifaddr(net,pfx,dev,1);if(ifa==NULL){/*
From: Brian Haley <hidden> Date: 2011-10-10 16:23:00
On 10/05/2011 04:15 PM, Lorenzo Colitti wrote:
net: ipv6: Allow netlink to set IPv6 address scope
Currently, userspace cannot specify the scope of IPv6
addresses when creating or modifying them. Instead, the
scope is automatically determined from the address itself.
In IPv4, userspace can set whatever scope it likes.
Allow userspace to specify the scope of IPv6 addresses in
a backwards-compatible way: if the scope passed in is zero,
use the old behaviour of automatically determining the
scope based on the address.
Signed-off-by: Lorenzo Colitti <redacted>
Hi Lorenzo,
I remember someone proposing a similar patch before and it was not accepted, do
you have a use case for doing this? It just seems like it will cause problems.
Also, there are other parts of the kernel (NFS, SCTP, IPv6 multicast) that are
still calling ipv6_addr_scope() on a plain address - won't those be broken since
they'll return the correct, RFC-implied scope?
-Brian
From: Lorenzo Colitti <hidden> Date: 2011-10-13 23:55:45
On Mon, Oct 10, 2011 at 09:16, Brian Haley [off-list ref] wrote:
quoted
net: ipv6: Allow netlink to set IPv6 address scope
Currently, userspace cannot specify the scope of IPv6
addresses when creating or modifying them. Instead, the
scope is automatically determined from the address itself.
In IPv4, userspace can set whatever scope it likes.
Allow userspace to specify the scope of IPv6 addresses in
a backwards-compatible way: if the scope passed in is zero,
use the old behaviour of automatically determining the
scope based on the address.
Signed-off-by: Lorenzo Colitti <redacted>
Hi Lorenzo,
I remember someone proposing a similar patch before and it was not accepted, do you have a use case for doing this? It just seems like it will cause problems.
Well, to begin with it's a question of feature parity. If we allow
users to set the scope of IPv4 addresses, then we should allow them to
set the scope of IPv6 addresses as well. Policy belongs in userspace,
not in the kernel.
One use case is as follows. I have a phone with an always-on IPv6
interface which is used for signaling, provisioning, SMS, etc. This
IPv6 address is a global unicast IPv6 address, but it belongs to a
closed carrier network, and cannot be used to communicate with the
IPv6 Internet in either direction.
The phone also supports wifi. When there is IPv6 on the wifi
interface, things get messy because the phone can decide to use the
carrier source address on the wifi interface. This will not work,
because the replies will be dropped in the carrier network.
You can stop this from happening in most cases by not putting a
default route on the walled garden interface, and only using host
routes as needed. Unfortunately, you can't stop it from happening in
at least the following two cases:
1. You receive an IPv6 RA on the wifi interface which provides a
default route and a 6to4 address, or a default route and no IPv6
address (for example, because the network uses DHCPv6 and not
RFC4862-style autoconf)
2. You receive an IPv6 RA on the wifi interface which provides a
default route and a "native" IPv6 address, but the phone attempts a
connection while the address is in the tentative state (i.e., the
phone is performing DAD on the address)
In both cases, ipv6_get_saddr_eval will return the carrier IPv6
address (because "avoid tentative and optimistic addresses" takes
precedence over "prefer outgoing interface" in RFC3484) and the kernel
will pick the default route on the wifi interface. The return packets
will get dropped and the connection will time out after several
minutes.
The only way I can think of to get this right is to set the carrier
IPv6 address to a scope less than global - which, in effect, it is,
because it can't reach the Internet.
Also, there are other parts of the kernel (NFS, SCTP, IPv6 multicast) that are still calling ipv6_addr_scope() on a plain address - won't those be broken since they'll return the correct, RFC-implied scope?
Good point. I looked at these and don't think there is a serious problem though:
- SCTP doesn't look at the scope in IPv4 either, it just looks at the
address itself. So at worse this change will make IPv6 match IPv4.
- NFS only looks at the scope to check whether it's link-local, and if
so only declares an address to be unique if the scopes match. In this
case I think it's the right thing to do, because it's really the
network that decides whether an address can be duplicate on different
links, not the host.
- Unicast and multicast do it when dumping the addresses to userspace.
I need to fix these.
Does that make sense?
From: Brian Haley <hidden> Date: 2011-10-14 20:14:24
On 10/13/2011 07:55 PM, Lorenzo Colitti wrote:
On Mon, Oct 10, 2011 at 09:16, Brian Haley [off-list ref] wrote:
quoted
quoted
net: ipv6: Allow netlink to set IPv6 address scope
Currently, userspace cannot specify the scope of IPv6
addresses when creating or modifying them. Instead, the
scope is automatically determined from the address itself.
In IPv4, userspace can set whatever scope it likes.
Allow userspace to specify the scope of IPv6 addresses in
a backwards-compatible way: if the scope passed in is zero,
use the old behaviour of automatically determining the
scope based on the address.
Signed-off-by: Lorenzo Colitti <redacted>
Hi Lorenzo,
I remember someone proposing a similar patch before and it was not accepted, do you have a use case for doing this? It just seems like it will cause problems.
Well, to begin with it's a question of feature parity. If we allow
users to set the scope of IPv4 addresses, then we should allow them to
set the scope of IPv6 addresses as well. Policy belongs in userspace,
not in the kernel.
I can understand the feature parity need, and we are just providing the rope for
the sysadmin to hang themselves with, but I'm still not convinced. Hopefully
someone else will have an opinion.
One use case is as follows. I have a phone with an always-on IPv6
interface which is used for signaling, provisioning, SMS, etc. This
IPv6 address is a global unicast IPv6 address, but it belongs to a
closed carrier network, and cannot be used to communicate with the
IPv6 Internet in either direction.
Playing devil's advocate here, isn't this a brain-dead ISP? If they're giving
you a global IPv6 address you should get Internet connectivity with it. If not,
you probably knew it up front, or you're going to find another provider that
does. It's like they're giving you a site-local address...
So are you talking about being able to dynamically change the scope of an
address? Wifi comes up - change provider addreses to host-local, wifi goes down
- change it back to global. That looks like a hack.
The phone also supports wifi. When there is IPv6 on the wifi
interface, things get messy because the phone can decide to use the
carrier source address on the wifi interface. This will not work,
because the replies will be dropped in the carrier network.
You can stop this from happening in most cases by not putting a
default route on the walled garden interface, and only using host
routes as needed. Unfortunately, you can't stop it from happening in
at least the following two cases:
The IETF MIF working group is looking at a lot of these scenarios, I only lurk
there and don't have any good drafts I can point you at though.
1. You receive an IPv6 RA on the wifi interface which provides a
default route and a 6to4 address, or a default route and no IPv6
address (for example, because the network uses DHCPv6 and not
RFC4862-style autoconf)
A default route with only a link-local address isn't very useful. Will the
kernel ever use this interface with the global address of your carrier - isn't
it going to prefer the interface that address is configured on?
2. You receive an IPv6 RA on the wifi interface which provides a
default route and a "native" IPv6 address, but the phone attempts a
connection while the address is in the tentative state (i.e., the
phone is performing DAD on the address)
That's a pretty small window where the address is in tentative state (< 2 sec),
and re-trying shortly after will work.
In both cases, ipv6_get_saddr_eval will return the carrier IPv6
address (because "avoid tentative and optimistic addresses" takes
precedence over "prefer outgoing interface" in RFC3484) and the kernel
will pick the default route on the wifi interface. The return packets
will get dropped and the connection will time out after several
minutes.
The only way I can think of to get this right is to set the carrier
IPv6 address to a scope less than global - which, in effect, it is,
because it can't reach the Internet.
You can also use routing rules, like anyone that does dual-homed with IPv4 does
- only use 1.2.3.4 on eth0, and only use 4.3.2.1 on eth1.
And there's also gai.conf, although I haven't played with that in a while.
The other trick/hack is to change the preferred lifetime of an address to zero,
which should mark it deprecated, moving it down in the selection list.
quoted
Also, there are other parts of the kernel (NFS, SCTP, IPv6 multicast) that are still calling ipv6_addr_scope() on a plain address - won't those be broken since they'll return the correct, RFC-implied scope?
Good point. I looked at these and don't think there is a serious problem though:
- SCTP doesn't look at the scope in IPv4 either, it just looks at the
address itself. So at worse this change will make IPv6 match IPv4.
- NFS only looks at the scope to check whether it's link-local, and if
so only declares an address to be unique if the scopes match. In this
case I think it's the right thing to do, because it's really the
network that decides whether an address can be duplicate on different
links, not the host.
- Unicast and multicast do it when dumping the addresses to userspace.
I need to fix these.
Does that make sense?
What else will break though? If I configure fe80::1/64 and set the scope to
global, do applications know to look at ifa_scope and not just the address
itself to determine the scope? Should they?
-Brian
From: Lorenzo Colitti <hidden> Date: 2011-10-14 22:32:54
On Fri, Oct 14, 2011 at 13:14, Brian Haley [off-list ref] wrote:
Playing devil's advocate here, isn't this a brain-dead ISP? If they're
giving you a global IPv6 address you should get Internet connectivity
with it. If not, you probably knew it up front, or you're going to find
another provider that does. It's like they're giving you a site-local
address...
I wouldn't say they're a brain-dead carrier, because they also give you
true IPv6 connectivity on another interface. The phone will deactivate
this interface when bringing up wifi, because wifi is usually cheaper and
faster. However, the carrier interface needs to stay up all the time
in order to do such things as provisioning, send and receive SMS
messages, handle voice over IP calls, and so on. So you will have
cases where the phone's primary Internet connection is over wifi, but
the phone still has a global unicast IPv6 address on the carrier interface.
So are you talking about being able to dynamically change the scope
of an address? Wifi comes up - change provider addreses to host-
local, wifi goes down - change it back to global. That looks like a
hack.
What I'm suggesting is to have the carrier interface be created with
site scope and stay up forever (or as long as the phone is on the cell
network). If an application wants to use the carrier interface, it will create
host routes that explicitly specify the carrier interface and the source
address of the carrier interface.
Applications that don't use the carrier interface will not have to do
anything special; if you set the carrier interface to site scope,
the kernel should just do the right thing.
A default route with only a link-local address isn't very useful. Will the
kernel ever use this interface with the global address of your carrier -
isn't it going to prefer the interface that address is configured on?
No, it will use the carrier address, because RFC3484 says "avoid
deprecated addresses" (rule 3) before it says "prefer outgoing interface"
(rule 5).
That's a pretty small window where the address is in tentative state (< 2 sec), and re-trying shortly after will work.
That's true, but as the application you don't know that. You just call
connect(), and sit there and hang. There's a lot of applications that want
to reconnect as soon as they see that wifi has come up, and they all
get stuck.
You can also use routing rules, like anyone that does dual-homed
with IPv4 does - only use 1.2.3.4 on eth0, and only use 4.3.2.1 on
eth1.
That doesn't work, because when the kernel creates a new TCP
connection, its source address is empty, so no source-based rules
match. More specifically, if I do (assume the carrier IP address is
2001:db8::1/64):
ip -6 rule add prio 100 from 2001:db8::/64 lookup 100
ip -6 route add table 100 unreachable default
ip -6 route add default via fe80::1 dev wlan0
the system will still use the address from the carrier interface. I think
this is by design though.
And there's also gai.conf, although I haven't played with that in a
while.
gai.conf only handles destination address selection; the kernel
handles source address selection.
The other trick/hack is to change the preferred lifetime of an address
to zero, which should mark it deprecated, moving it down in the
selection list.
That will work, but I think it's more of a hack than setting scope to
site. The carrier address is not deprecated, it's perfectly
functional. It just can't reach the Internet, but only a part of it.
So I think that calling it scoped is the solution that makes the most
sense.
What else will break though? If I configure fe80::1/64 and set the
scope to global, do applications know to look at ifa_scope and not
just the address itself to determine the scope? Should they?
If the application treats scoped addresses specially, it will treat
fe80::1 as link-local scope, and will do things like check
sin6_scope_id to see if it's unique. On balance, I think that's the
right thing to do for an application in this situation, since, as
above, it's the network that truly decides what scope an address is
unique in, not the application or the kernel, and I would expect the
rest of the network to treat fe80::/64 as link-local (for example,
routers won't forward it, and so on).
The kernel, on the other hand, will try to use fe80::1 as if it were a
global address for the purposes of source address selection, but after
all, that's what you asked it to do, so you can't really blame it.
Make sense?
From: Brian Haley <hidden> Date: 2011-10-17 00:45:25
On 10/14/2011 06:32 PM, Lorenzo Colitti wrote:
On Fri, Oct 14, 2011 at 13:14, Brian Haley [off-list ref] wrote:
quoted
Playing devil's advocate here, isn't this a brain-dead ISP? If they're
giving you a global IPv6 address you should get Internet connectivity
with it. If not, you probably knew it up front, or you're going to find
another provider that does. It's like they're giving you a site-local
address...
I wouldn't say they're a brain-dead carrier, because they also give you
true IPv6 connectivity on another interface. The phone will deactivate
this interface when bringing up wifi, because wifi is usually cheaper and
faster. However, the carrier interface needs to stay up all the time
in order to do such things as provisioning, send and receive SMS
messages, handle voice over IP calls, and so on. So you will have
cases where the phone's primary Internet connection is over wifi, but
the phone still has a global unicast IPv6 address on the carrier interface.
quoted
So are you talking about being able to dynamically change the scope
of an address? Wifi comes up - change provider addreses to host-
local, wifi goes down - change it back to global. That looks like a
hack.
What I'm suggesting is to have the carrier interface be created with
site scope and stay up forever (or as long as the phone is on the cell
network). If an application wants to use the carrier interface, it will create
host routes that explicitly specify the carrier interface and the source
address of the carrier interface.
Applications that don't use the carrier interface will not have to do
anything special; if you set the carrier interface to site scope,
the kernel should just do the right thing.
I think this goes against the intent of RFC 3879 (Deprecating Site Local
Addresses), and it assumes that the user has some knowledge of the network
topology. When we send something out the carrier interface, we don't know why
it didn't make it to it's final destination - firewall, network link down,
congestion - we might not get the ICMP reason back.
The MIF problem statement (in the RFC editor's queue) talks about this problem,
http://tools.ietf.org/html/draft-ietf-mif-problem-statement-15 - perhaps it's
better to work there to develop a more generic solution (using DHCPv6, RA
options, etc) before making this change?
-Brian
From: Lorenzo Colitti <hidden> Date: 2011-10-17 02:27:04
On Mon, Oct 17, 2011 at 09:45, Brian Haley [off-list ref] wrote:
I think this goes against the intent of RFC 3879 (Deprecating Site Local
Addresses), and it assumes that the user has some knowledge of the network
topology. When we send something out the carrier interface, we don't know why
it didn't make it to it's final destination - firewall, network link down,
congestion - we might not get the ICMP reason back.
Absolutely yes, this assumes that the user has knowledge of network
topology. But
we already know that, because in order for this code to be exercised,
the user must
have explicitly specified a non-global scope in the code that he ran
(or in the "ip
addr add" command that he executed). The only difference with this patch is that
the kernel does what the user asked for instead of making its own decision.
The way things would work in this scenario is that whatever userspace
code creates
the IPv6 address on the carrier interface would create it with
site-local scope. That
code knows perfectly well that the interface should not be used when
connecting to
globally scoped addresses and would tell the kernel not to use it. The kernel
currently refuses to do so because it thinks it knows better, but
since it doesn't, the
user's connections hang. I don't think this is a good idea.
RFC 3879 deprecated site-local addresses because the were non-unique and thus
ambiguous, and if they leak, they cause problems. This is not an issue
in the use
case I presented, because the addresses are syntactically global
addresses - they
just don't have global reachability.
The MIF problem statement (in the RFC editor's queue) talks about this problem,
http://tools.ietf.org/html/draft-ietf-mif-problem-statement-15 - perhaps it's
better to work there to develop a more generic solution (using DHCPv6, RA
options, etc) before making this change?
I don't think it's a good idea. Waiting for an IETF working group to
produce a standard
when it doesn't even have a problem statement finalized could take years.
Is there another reason why we shouldn't enable userspace to do what it wants?
From: Brian Haley <hidden> Date: 2011-10-17 21:32:09
On 10/16/2011 10:26 PM, Lorenzo Colitti wrote:
RFC 3879 deprecated site-local addresses because the were non-unique and thus
ambiguous, and if they leak, they cause problems. This is not an issue
in the use
case I presented, because the addresses are syntactically global
addresses - they
just don't have global reachability.
Not very global then :(
quoted
The MIF problem statement (in the RFC editor's queue) talks about this problem,
http://tools.ietf.org/html/draft-ietf-mif-problem-statement-15 - perhaps it's
better to work there to develop a more generic solution (using DHCPv6, RA
options, etc) before making this change?
I don't think it's a good idea. Waiting for an IETF working group to
produce a standard
when it doesn't even have a problem statement finalized could take years.
It would be useful to give some input there, even if the Linux-specific
implementation of any standard plays with bits in the ifaddr.
Is there another reason why we shouldn't enable userspace to do what it wants?
In my opinion it just feels like a hack, because things won't work when your
wifi attaches to a walled garden, or there's a third interface - who wins the
tiebreaker?
I do see your point that it will help with the problem you're trying to solve,
hopefully someone else will offer their opinion.
-Brian
From: Maciej Żenczykowski <hidden> Date: 2011-10-21 04:25:20
quoted
RFC 3879 deprecated site-local addresses because the were non-unique and thus
ambiguous, and if they leak, they cause problems. This is not an issue
in the use
case I presented, because the addresses are syntactically global
addresses - they
just don't have global reachability.
Not very global then :(
They're globally unique.
Global does not imply being able to reach the internet, or being able
to be reached from the internet.
Whatever the RFC's say, that's just a sad fact of life.
quoted
I don't think it's a good idea. Waiting for an IETF working group to
produce a standard
when it doesn't even have a problem statement finalized could take years.
It would be useful to give some input there, even if the Linux-specific
implementation of any standard plays with bits in the ifaddr.
I'm afraid this is a real problem _right_ now, a solution is required
and we can't really afford to wait a year while working groups work
out a bugfix.
In my opinion it just feels like a hack, because things won't work when your
wifi attaches to a walled garden, or there's a third interface - who wins the
tiebreaker?
I would tend to agree that this is a little hacky... but, ultimately,
I always claim that policy should belong in userspace - not in the
kernel.
If userspace administrator wants to shoot himself, he can do that in
plenty of ways already.
I do see your point that it will help with the problem you're trying to solve,
hopefully someone else will offer their opinion.
I'm a little biased here, but I'd prefer my cellphone to just work ;-)
- Maciej