Subject: Re: mutating IPv4 aliases on NetBSD 2 systems
To: None <tech-net@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-net
Date: 02/26/2006 23:21:26
>>> It is hard to imagine what sane meaning it could possibly have to
>>> have two host addresses on the same physical segment with different
>>> -- but overlapping -- netmasks.
>> It seems fairly straightforward to me.
> Straightforward, perhaps.  [But not sane], for a number of reasons,

Okay, you gave one reason:

> if you don't bind a socket specifically to either address, what
> source address do you get, and what destination for broadcast
> packets?

That's what the primary address is for (the one ifconfig shows without
"alias"), and this foofooraw blew up because something shuffled
addresses in a way that changed which address was primary.

What are some of the other reasons?  You have me curious what I'm
missing; I don't see any other surprises waiting.

> I see little compelling reason why anyone would _want_ to run a
> system this way,

Because it works.

Do you have something else (that works at least as well) to recommend
instead?  At work we have a number of systems configured this way and
have never had trouble with them; if you have something better to
suggest, I'd like to hear it.

>>> You can configure additional host addresses on lo0 with a /32
>>> netmask if you wish.
>> And why not on any other interface?  What's magic about lo0 that /32
>> aliases are acceptable on *it*, but not elsewhere?
> You read into my message something that, quite simply, is not there.

I think it is there in context.  If you want to deny context, you could
equally well have said "You can configure lo0 with address
11.11.11.11/13 if you wish"; I don't think it's unreasonable to read
some link between the foregoing message and that comment into what you
wrote, and to me that link is that this suggestion is somehow more
acceptable than what you were calling not sane.

> Aliases with different, overlapping netmasks, on the same physical
> segment, aren't okay anywhere.

Again, why not?  I've seen only one reason, and that one is a problem
only in the face of something shuffling address order.

This is not entirely an academic question to me.  Among the systems I
refer to above is one I set up for a customer (I work for an ISP) in a
way that uses such different overlapping netmasks briefly, and if you
can suggest something better, I would very much like to see it.  Since
I suspect your first suggestion will be, approximately, "use the same
netmask for all addresses", which might work for some of the systems at
work but not for this one, I'll sketch the problem and my "solution":

The machine has four interfaces.  Three are connected to microwave
links from an external provider.  The provider has assigned a pool of
30 addresses to these links; all are specced by the provider as being
in /24s, with the same default gateway (they were not willing to give
us multiple subnets with their own uplink gateways).  Using 1918
addresses as an exmaple (the actual IPs are fully routed), the provider
has given us 10.1.2.149-153 and 10.1.2.207-231, all /24 with default
gateway 10.1.2.1.  We want to loadshare among the three microwave links
(the machine NATs for an internal network, but that's mostly irrelevant
to this aspect of it).

Since it won't do anything useful to configure three interfaces all in
the same /24 (I'm not sure it will even work minimally), what I did was
to carve out three /30s from that pool of addresses - fortunately,
there were three /30s among them.  Then (to use the same example
addresses, with interface names ex0, vr0, and wm0),

ifconfig ex0 10.1.2.209/30
ifconfig ex0 10.1.2.149/32 alias
ifconfig ex0 10.1.2.150/32 alias
ifconfig ex0 10.1.2.151/32 alias
ifconfig ex0 10.1.2.152/32 alias
ifconfig vr0 10.1.2.213/30
ifconfig vr0 10.1.2.153/32 alias
ifconfig vr0 10.1.2.207/32 alias
ifconfig vr0 10.1.2.220/32 alias
ifconfig vr0 10.1.2.221/32 alias
ifconfig wm0 10.1.2.217/30
ifconfig wm0 10.1.2.222/32 alias
ifconfig wm0 10.1.2.223/32 alias
ifconfig wm0 10.1.2.224/32 alias
ifconfig wm0 10.1.2.225/32 alias

Worse, the addresses are all floating: an address does not work on an
antenna unless we ARP for the upstream - simply sending traffic is not
enough.  What I did was to add each address first as a /24, ping the
upstream, delete the ARP entry, delete the address, and install the
address with the netmask given above - except that for the /30 address
on each interface, I grab the MAC address before deleting the ARP
entry, and use it to set a permanent ARP entry for the other end of the
/30 - 10.1.2.210, 10.1.2.214, or 10.1.2.218.  Then I can route to one
of those "other end" addresses in the routing table and everything will
work.  Below I include the rc.d script I wrote (rc.d/LOCAL.antennas) to
do ths dance (I've changed the upstream's address to match the example
above).  Now, the above config does not include overlapping addresses
(the /32s are outside of the /30s), but the setup script does use such
overlapping netmasks briefly.

What do you think I should have done instead?

You may argue that attempting to do anything with that peculiar a setup
is inherently non-sane.  I might even agree with you.  But unless you
simply consider this about the sanest way to deal with the mess short
of turfing it all and finding a different provider, I'd very much like
to hear any suggestions you have.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B

Here's that rc.d script.  (/etc/ifnames holds assignments like
"ANT1=ex0", "ANT2=vr0", etc.)

#!/bin/sh

# PROVIDE: antennas
# REQUIRE: network
# BEFORE:  NETWORKING pf

$_rc_subr_loaded . /etc/rc.subr

name=antennas
start_cmd=antennas_start
stop_cmd=:

upstream=10.1.2.1

antennas_start()
{
	. /etc/ifnames
	setdef=true
	for intf in $ANT1 $ANT2 $ANT3; do
		exec 3</etc/ifconfig.$intf
		first=true
		while read line 0<&3; do
			case "$line" in
				"#"*)	;;
				"!"*)	eval "${line#!}";;
				*)	echo $line
					if $first; then
						ifconfig $intf ${line%/*}/24
						arp -d $upstream 2> /dev/null
						ping -n -o -c 10 $upstream
						mac=`arp -na | fgrep "($upstream)" | awk '{print $4}'`
						arp -d $upstream
						ifconfig $intf $line
						arp -s `echo $line{%/*} | tr . \  | awk '{ print $1 "." $2 "." $3 "." $4+3-(2*($4%4)) }'` $mac
						if $setdef; then
							route add default `echo $line{%/*} | tr . \  | awk '{ print $1 "." $2 "." $3 "." $4+3-(2*($4%4)) }'`
							setdef=false
						fi
					else
						line="${line% alias}"
						ifconfig $intf ${line%/*}/24 alias
						arp -d $upstream 2> /dev/null
						ping -n -o -c 10 $upstream
						arp -d $upstream
						ifconfig $intf delete ${line%/*}
						ifconfig $intf $line alias
					fi
					first=false
					;;
			esac
		done
	done
}

load_rc_config $name
run_rc_command "$1"