ifconfig creates a bogus(?) route

Bruce Evans brde at optusnet.com.au
Sun May 29 03:29:54 UTC 2016


> Bruce Evans wrote:
>> Sometime between r191220 and r201220, ifconfig started creating a bogus(?) static route.
>> The following is under r248255 with "ifconfig em0 inet 192.168.2.8" (where 192.168.2.8 is
>> for the local host and I don't bother typing the netmsk) done before bringing up lo0:
>>
>> Routing tables
>>
>> Internet:
>> Destination        Gateway            Flags    Refs      Use  Netif Expire
>> 192.168.2.0/24     link#1             U           0        0    em0
>> 192.168.2.8        link#1             UHS         0        0    lo0
>
> Why do you feel the route is bogus?  Is it because it has a netmask?

It is the second route that is bogus(?).  It is bogus(?) because:

(a) it is a new "feature" in some version between r191220 and r201220
(b) it is not needed (the defaults work)
(c) it doesn't work (it breaks working of the defaults)
(d) it produces a route to an unconfigured interface (lo0) when lo0
     happens to be configured after em0.

It is bogus(?) instead of bogus since it actually looks correct.

Utilities obfuscate this a little by not displaying enough raw state
and by displaying the state differently (even with -n).

The bug seems to be just (d) combined with (a).  Before (a), the order
of bringing up interfaces didn't matter.  After (a), lo0 must be brought
up first because (d) doesn't do all the initialization required for the
unconfigured lo0 and bringing up lo0 later gives an inconsistent state.

I use network_interfaces=<explicit alpha-sorted list> and this happens to
give an order with after the primary NIC interface in some cases.  The
default is network_interfaces="auto".  This starts with the ifconfig -l
order which seems to always put lo0 _last_.  However, r149726 moves lo0
first for unstated reasons.  Thus most installations don't see the bug.
I would have seen it even if I used auto since my userland is older than
r149726.

> If you don't supply a netmask, ifconfig will assume one based on the "class" (A, B, C) of the IP you've supplied.  192.168.2.8 is a Class C address and gets a /24 netmask by default.

Yes, I didn't bother typing one partly because I know that the default is
right for em0 and almost anything works for lo0.

>> The bogus(?) route points to itself (route get shows this more clearly), and doesn't work.
>> I know little about routiing, but can > fix things like this manually.  Simply "route delete"
>> on the bogus(?) route works in this case.  An alias for lo0 also works.
>
> In router parlance, the route would be called a "connected" route, showing that not only do you have an IP on the subnet, but by virtue of the netmask, you are "connected" to every other IP in the same subnet range, through that interface.  It will cause your system to send ARP requests through that interface for any other IP in the range, in order to communicate with them.

I still haven't figured out how to set up the bogus(?) route using route
add/change, but can now complete the initialization using a "route change"
that appears to be null:

Test script:

X # Try to kill all old interfaces and routes, if any:
X ifconfig em0 inet 0
X ifconfig lo0 inet 0
X netstat -rn
X 
X # (Re)initialize in the broken order:
X ifconfig em0 inet 192.168.2.8
X ifconfig lo0 inet 127.0.1
X netstat -rn
X route -n get 192.168.2.8
X 
X # Fix up the initialization with a null change:
X route change -iface 192.168.2.8 192.168.2.8
X netstat -rn
X route -n get 192.168.2.8
X 
X # This ping works after the fixup, or with the opposite init order:
X ping -c1 192.168.2.8

Output:

Routing tables

Y Internet:
Y Destination        Gateway            Flags    Refs      Use  Netif Expire
Y Routing tables
Y 
Y Internet:
Y Destination        Gateway            Flags    Refs      Use  Netif Expire
Y 127.0.0.1          link#2             UH          0        0    lo0
Y 192.168.2.0/24     link#1             U           0        0    em0
Y 192.168.2.8        link#1             UHS         0        0    lo0
Y    route to: 192.168.2.8
Y destination: 192.168.2.8
Y   interface: lo0
Y       flags: <UP,HOST,DONE,STATIC>
Y  recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
Y        0         0         0         0         0         0     16384         0 
Y change host 192.168.2.8: gateway 192.168.2.8
Y Routing tables
Y 
Y Internet:
Y Destination        Gateway            Flags    Refs      Use  Netif Expire
Y 127.0.0.1          link#2             UH          0        0    lo0
Y 192.168.2.0/24     link#1             U           0        0    em0
Y 192.168.2.8        192.168.2.8        UHS         0        0    lo0
Y    route to: 192.168.2.8
Y destination: 192.168.2.8
Y   interface: lo0
Y       flags: <UP,HOST,DONE,STATIC>
Y  recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
Y        0         0         0         0         0         0     16384         0 
Y PING 192.168.2.8 (192.168.2.8): 56 data bytes
Y 64 bytes from 192.168.2.8: icmp_seq=0 ttl=64 time=0.005 ms
Y 
Y --- 192.168.2.8 ping statistics ---
Y 1 packets transmitted, 1 packets received, 0% packet loss
Y round-trip min/avg/max/stddev = 0.005/0.005/0.005/0.000 ms

Note that the "null" route change just echos the current setting and it
doesn't change anything according to netstat -rn and route -n, but it
fixes up some internal state so that the ping works.  When ping works,
tcpdump shows it going from 127.0.0.1 to 192.168.2.8 and coming back as
expected.  When ping hangs, tcpdump shows it going from 0.0.0.0 to 
192.168.2.8 and never coming back.  The default route doesn't exist in
either case.

I still get confused using route(8).  For the apparently-null fixup, it
is necessary to use -iface.  The fixup
"route change 192.168.2.8 192.168.2.8" also works, but it is not a null
change although it looks even more like one.  It changes the Gateway
according to netstat -rn from link#1 to 192.168.2.8 but doesn't change
anything according to route -n get.  "G" is not in flags so the Gateway
is fairly bogus and is not displayed by route -n get, but something
critical changed so it is a bug to not display any changes.  link#1 vs
192.168.2.8 shows the difference in a cryptic way.

Anyway, I can fix my original problem by unsorting network_interfaces.

network_interfaces is documented in rc.conf(5).  Ordering requirements
for it don't seem to be mentioned there.  It has no examples there.
Examples in other man pages put lo0 first.

Bruce


More information about the freebsd-net mailing list