Subject: [patch] source-address selection
To: None <tech-net@netbsd.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 09/02/2006 16:22:44
For review, here are my latest patches adding a mechanism
for enforcing an IPv4 source-address selection policy,
<ftp://cuw.ojctech.com/cuw/netbsd-e3b075d7/pristine-selsrc-patch>.
Below, I document the impact of the patches a bit.  I will turn this
text into a manual page.

The patches let an operator set the policy by which the kernel chooses a
source address for any socket bound to the "wildcard" address, INADDR_ANY.
Note that the policy is applied *after* the kernel makes its forwarding
decision, thereby choosing the output interface; in other words, this
mechanism does not affect whether or not NetBSD is a "strong ES".

An operator affects the source-address selection using sysctl(8) and
ifconfig(8).  Operators set policies with sysctl(8).  Some policies
consider the "preference number" of an address.  An operator may set
preference numbers for each address with ifconfig(8).

A source-address policy is a priority-ordered list of source-address
ranking functions.  A ranking function maps its arguments, (_source
address_, _source index_, _source preference_, _destination address_),
to integers.  The _source index_ is the position of _source address_
in the interface address list; the index of the first address is 0.
The _source preference_ is the preference number the operator assigned
to _source address_.  The _destination address_ is the socket peer /
packet destination.

Presently, there are four ranking functions to choose from:

        index           ranks by _source index_; lower indices are ranked
                        more highly

        preference      ranks by _source preference_; lower preference
                        numbers are ranked more highly

        common-prefix-len
                        ranks each _source address_ by the length of the
                        longest prefix it has in common with _destination
                        address_; longer common prefixes rank more highly

        same-category determines the "categories" of _source_ and
                        _destination address_.  A category is one of
                        "private", "link-local", or "other".  If the
                        categories exactly match, same-category assigns a
                        rank of 2.  Some sources are ranked 1 by category:
                        a link-local source with a private destination,
                        a private source with a link-local destination,
                        and a private source with an "other" destination
                        rank 1.  All other sources rank 0.

                        Categories are defined as follows.

                        private: RFC1918 networks, 192.168/16, 172.16/12,
                                 and 10/8,

                        link-local: 169.254/16, 224/24

                        other: all other networks---i.e., not private,
                               not link-local

To apply a policy, the kernel applies all ranking functions in the policy
to every source address, producing a vector of ranks for each source.
The kernel sorts the sources in descending, lexicographical order by their
rank-vector, and chooses the highest-ranking (first) source.  The kernel
breaks ties by choosing the source with the least _source index_.

The operator may set a policy on individual interfaces.  The operator
may also set a global policy that applies to all interfaces whose policy
he does not set individually.

Here is the sysctl tree for the policy at system startup:

net.inet.ip.selectsrc.default = index
net.inet.ip.interfaces.ath0.selectsrc =
net.inet.ip.interfaces.sip0.selectsrc =
net.inet.ip.interfaces.sip1.selectsrc =
net.inet.ip.interfaces.lo0.selectsrc =
net.inet.ip.interfaces.pflog0.selectsrc =

The policy on every interface is the "empty" policy, so the default
policy applies.  The default policy, "index," is the "historical" policy
in NetBSD.

The operator may override the default policy on ath0,

	# sysctl -w net.inet.ip.interfaces.ath0.selectsrc=\
	> same-category,common-prefix-len,preference

yielding this policy:

net.inet.ip.selectsrc.default = index
net.inet.ip.interfaces.ath0.selectsrc = same-category,common-prefix-len,preference

The operator may set a new default,

	# sysctl -w net.inet.ip.selectsrc.debug=\
	> same-category,common-prefix-len,preference
	# sysctl -w net.inet.ip.interfaces.ath0.selectsrc=

yielding this policy:

net.inet.ip.selectsrc.default = same-category,common-prefix-len,preference
net.inet.ip.interfaces.ath0.selectsrc =

In a number of application areas, the policy above will usually pick
suitable source addresses if ath0 is configured in this way:

	# ifconfig ath0 inet 64.198.255.1/24
	# ifconfig ath0 inet 10.0.0.1/24
	# ifconfig ath0 inet 169.254.1.1/24
	# ifconfig ath0 inet 192.168.49.1/24 preference 5
	# ifconfig ath0 inet 192.168.37.1/24 preference 9

A sysctl, net.inet.ip.selectsrc.debug, turns on and off debug messages
concerned with source selection.  You may set it to 0 (no messages) or 1.

You add the source-address selection policy mechanism to your kernel with
'options IPSELSRC'.

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933