Subject: patch rfc: source-address selection policy
To: None <tech-net@netbsd.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 09/20/2005 18:43:56
I have a patch, <http://tinyurl.com/89hkx>, and a bundle of files,
<http://tinyurl.com/az9wh>, that add IPv4 source address-selection
policies to NetBSD.
Problem
Today, an operator can assign two or more IPv4 addresses to a single
network interface on his NetBSD host, but he cannot directly express
his preference that NetBSD should choose one address over another
as local address for a socket bound to the "don't care" address,
INADDR_ANY. For such a socket, NetBSD arbitrarily chooses the first
address on the outgoing interface. An arbitrary choice does not suit
every application. I will give some examples.
One local address may be more suitable than another for connections to a
particular remote address. For example, on an interface with addresses
169.254.3.7/16 and 10.0.3.2/24 assigned, an operator may prefer that
packets with link-local destinations (169.254/16, 224.0.0/24) carry
a link-local source address, 169.254.3.7, while packets with other
destinations should use the source 10.0.3.2.
An operator may likewise assign an interface both an address 10.1.2.3/24
for the corporate WAN (10/8), and 64.233.167.147/28, which is assigned
by the local ISP, preferring for connections to hosts on the corporate
WAN to use the source 10.1.2.3, and connections to the Internet to
use the source 64.233.167.147.
An operator may assign three addresses to an interface---10.0.0.1/24,
10.0.0.2/24, and 10.0.0.3/24---preferring that only 10.0.0.3/24 is
used as a local address.
None of these source address-selection preferences can be expressed
to the NetBSD kernel, today.
Solution
First, I add a facility for labeling addresses with "preference
numbers". Set preference numbers using ifconfig(8):
% ifconfig ath0 inet
ath0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
inet 10.0.237.106 netmask 0xffffffff broadcast 10.0.237.106
inet alias 169.254.237.106 netmask 0xffff0000 broadcast 169.254.255.255
% ifconfig ath0 inet alias 169.254.237.106/16 preference 10
% ifconfig ath0 inet
ath0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
inet 10.0.237.106 netmask 0xffffffff broadcast 10.0.237.106 preference 0
inet alias 169.254.237.106 netmask 0xffff0000 broadcast 169.254.255.255 preference 10
I also add to each interface a "policy vector," a comma-delimited list
of policies for source selection, which are evaluated in order:
% sysctl net.inet.ip.ath0.selectsrc
net.inet.ip.ath0.selectsrc = same-category,common-prefix-len,preference
% sysctl -w net.inet.ip.ath0.selectsrc=index
net.inet.ip.ath0.selectsrc: same-category,common-prefix-len,preference -> index
The policies are in priority order, highest priority first.
Evaluating a policy on a source address produces a score. The
highest-scoring source address is selected, with ties broken by choosing
the address closest to the head of the interface's address list.
I define four policies, 'index', 'common-prefix-len', 'preference',
and 'same-category'. 'index' assigns higher scores to addresses
near the head of an interface's address list. 'common-prefix-len'
assigns a score equal to the length of the longest prefix the source
and destination have in common. 'same-category' assigns a score of 1
if the source and destination belong to the same "category" of address,
one of "link-local" (224/8, 169.254/16), RFC1918 (10/8, 172.16/12,
192.168/16) or "global" (all others); otherwise, 'same-category'
assigns 0. 'preference' assigns a score equal to a source's preference
number, negated; in this way, lower preference numbers are preferred.
It is easy to add more policies to the four I already define.
Using policy vectors, it is possible to express a large and useful
set of policies.
Outstanding issues that I will fix before committing:
1 The default policy ought to be 'index', since that is functionally
identical to the status quo.
2 The synchronization is not right, yet.
3 It is not possible to set a global default policy.
4 Negative preference numbers should be allowed, or else the default
preference should be greater than 0, so that it is possible to
preempt addresses assigned automatically by programs that do not
grok preference numbers (dhclient, say).
5 Needs a manual page.
Issues for further study:
1 It is not an option to forbid a socket from binding a different
address than the a socket can still be bound to an address on a
different interface than the outgoing interface (NetBSD remains
a Weak ES). To correct this, modifications to in_pcbconnect will
be necessary.
2 There is no IPv6 implementation of address preferences or policy
vectors.
3 We cannot enforce different policies on different processes.
Dave
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933