Subject: kern/1941: ifconfig alias bug.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <neil@domino.org>
List: netbsd-bugs
Date: 01/14/1996 10:27:20
>Number:         1941
>Category:       kern
>Synopsis:       Arp who-has problem with interface alias addresses
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 14 05:50:03 1996
>Last-Modified:
>Originator:     Neil J. McRae
>Organization:
--  neil@domino.org                     Domino: In the glow of the night.  --
--  Free your computer and your <a href="http://www.NetBSD.ORG/">mind</a>  --
>Release:        1.1
>Environment:
System: NetBSD mandy.domino.org 1.1A NetBSD 1.1A (MANDY) #13: Tue Dec 26 05:22:46 GMT 1995 neil@mandy.domino.org:/usr/src/sys/arch/i386/compile/MANDY i386


>Description:
When interface aliases are configured, NetBSD uses the last configured
interface alias IP address as the source IP address in all subsequent
arpwhohas requests from that interface regardless of which network the
address being arped for is on.  Certain Non-BSD IP implementations are
known to validate the IP addresses in arp requests and will therefore
be unreacheable if the BSD host is always the party originating traffic.
This is known to be a problem at least with ACC Danube routers running
version 8.0.3 and Cisco 2501 routers running 10.3(3).

>How-To-Repeat:

Create an interface alias and watch it use that address
inappropriately in future arp requests.
netbsd# netstat -in
Name  Mtu   Network     Address              Ipkts Ierrs    Opkts Oerrs  Coll
de0   1500  <Link>      0.0.c0.6e.b.9f    49853606   119  1487476    35 262938
de0   1500  158.152.1   158.152.1.55      49853606   119  1487476    35 262938
lo0   32768 <Link>                            3176     0     3176     0     0
lo0   32768 127         127.0.0.1             3176     0     3176     0     0
netbsd#  tcpdump -p -n arp and ether src 00:00:c0:6e:0b:9f &
[1] 9756
netbsd# tcpdump: listening on de0
arp -d 158.152.1.65
158.152.1.65 (158.152.1.65) deleted
netbsd# ping -c1 !$
ping -c1 158.152.1.65
PING 158.152.1.65 (158.152.1.65): 56 data bytes
64 bytes from 158.152.1.65: icmp_seq=0 ttl=255 time=2.321 ms

--- 158.152.1.65 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.321/2.321/2.321 ms
netbsd# 11:03:33.175735 arp who-has 158.152.1.65 tell 158.152.1.55
ifconfig de0 alias 172.31.1.1
11:03:54.815774 arp who-has 172.31.1.1 tell 172.31.1.1
netbsd# !a
arp -d 158.152.1.65
158.152.1.65 (158.152.1.65) deleted
netbsd# !p
ping -c1 158.152.1.65
PING 158.152.1.65 (158.152.1.65): 56 data bytes
64 bytes from 158.152.1.65: icmp_seq=0 ttl=255 time=2.621 ms

--- 158.152.1.65 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.621/2.621/2.621 ms
netbsd# 
11:04:01.984628 arp who-has 158.152.1.65 tell 172.31.1.1 ***WRONG***

>Fix:

This is not a terribly good fix, but does not require changing the way
interface aliases are implemented for now.

Index: src/sys/netinet/if_ether.c
***************
*** 250,259 ****
   */
  void
  arpwhohas(ac, addr)
!       register struct arpcom *ac;
        register struct in_addr *addr;
  {
!       arprequest(ac, &ac->ac_ipaddr.s_addr, &addr->s_addr, ac->ac_enaddr);
  }

  /*
--- 250,284 ----
   */
  void
  arpwhohas(ac, addr)
!       struct arpcom *ac;
        register struct in_addr *addr;
  {
!     struct ifnet *ifp = (struct ifnet *) ac;
!     register struct ifaddr *ifa;
!     struct in_addr myaddr = ac->ac_ipaddr;
!
!     /*
!      * This is a kludge.  The problem is that as things stand, ac->ac_ipaddr
!      * has only one value -- the value of the last interface alias address
!      * to be set, and this will almost certainly be wrong if you set the
!      * primary address first, and aliases next.  Some implementations
!      * (Cisco and ACC, for example) object to this, so we must try to find
!      * the right IP address to use in the presence of interface aliases.
!      * The correct thing to do is probably to give interface aliases
!      * their own ifp and thus ac each.  However, we don't arpwhohas that
!      * often anyway, so I guess this linear search each time won't hurt.
!      */
!     for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
!        ifa = ifa->ifa_list.tqe_next) {
!       u_int32_t adr, msk;
!       if (ifa->ifa_addr->sa_family != AF_INET)
!           continue;
!       adr = satosin(ifa->ifa_addr)->sin_addr.s_addr;
!       msk = satosin(ifa->ifa_netmask)->sin_addr.s_addr;
!       if ((adr & msk) == (addr->s_addr & msk))
!           myaddr = satosin(ifa->ifa_addr)->sin_addr;
!     }
!     arprequest(ac, &myaddr.s_addr, &addr->s_addr, ac->ac_enaddr);
  }

  /*

>Audit-Trail:
>Unformatted: