Home | History | Annotate | Line # | Download | only in routed
if.c revision 1.10
      1  1.10  christos /*	$NetBSD: if.c,v 1.10 1996/09/24 16:24:13 christos Exp $	*/
      2   1.7       cgd 
      3   1.1       cgd /*
      4   1.5   mycroft  * Copyright (c) 1983, 1993
      5   1.5   mycroft  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1       cgd  * modification, are permitted provided that the following conditions
      9   1.1       cgd  * are met:
     10   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16   1.1       cgd  *    must display the following acknowledgement:
     17   1.1       cgd  *	This product includes software developed by the University of
     18   1.1       cgd  *	California, Berkeley and its contributors.
     19   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20   1.1       cgd  *    may be used to endorse or promote products derived from this software
     21   1.1       cgd  *    without specific prior written permission.
     22   1.1       cgd  *
     23   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33   1.1       cgd  * SUCH DAMAGE.
     34   1.1       cgd  */
     35   1.1       cgd 
     36  1.10  christos #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
     37   1.7       cgd static char sccsid[] = "@(#)if.c	8.1 (Berkeley) 6/5/93";
     38  1.10  christos #elif defined(__NetBSD__)
     39  1.10  christos static char rcsid[] = "$NetBSD: if.c,v 1.10 1996/09/24 16:24:13 christos Exp $";
     40   1.7       cgd #endif
     41   1.1       cgd 
     42   1.1       cgd #include "defs.h"
     43   1.9   thorpej #include "pathnames.h"
     44   1.9   thorpej 
     45   1.9   thorpej struct	interface *ifnet;		/* all interfaces */
     46   1.9   thorpej int	tot_interfaces;			/* # of remote and local interfaces */
     47   1.9   thorpej int	rip_interfaces;			/* # of interfaces doing RIP */
     48   1.9   thorpej int	foundloopback;			/* valid flag for loopaddr */
     49   1.9   thorpej naddr	loopaddr;			/* our address on loopback */
     50   1.9   thorpej 
     51   1.9   thorpej struct timeval ifinit_timer;
     52   1.1       cgd 
     53   1.9   thorpej int	have_ripv1_out;			/* have a RIPv1 interface */
     54   1.9   thorpej int	have_ripv1_in;
     55   1.1       cgd 
     56   1.9   thorpej 
     57   1.9   thorpej /* Find the interface with an address
     58   1.1       cgd  */
     59   1.1       cgd struct interface *
     60   1.9   thorpej ifwithaddr(naddr addr,
     61   1.9   thorpej 	   int	bcast,			/* notice IFF_BROADCAST address */
     62   1.9   thorpej 	   int	remote)			/* include IS_REMOTE interfaces */
     63   1.1       cgd {
     64   1.9   thorpej 	struct interface *ifp, *possible = 0;
     65   1.1       cgd 
     66   1.1       cgd 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
     67  1.10  christos 		if (ifp->int_addr == addr
     68   1.9   thorpej 		    || ((ifp->int_if_flags & IFF_BROADCAST)
     69   1.9   thorpej 			&& ifp->int_brdaddr == addr
     70   1.9   thorpej 			&& bcast)) {
     71   1.9   thorpej 			if ((ifp->int_state & IS_REMOTE) && !remote)
     72   1.9   thorpej 				continue;
     73   1.9   thorpej 
     74   1.9   thorpej 			if (!(ifp->int_state & IS_BROKE)
     75   1.9   thorpej 			    && !(ifp->int_state & IS_PASSIVE))
     76   1.9   thorpej 				return ifp;
     77   1.9   thorpej 
     78   1.9   thorpej 			possible = ifp;
     79   1.9   thorpej 		}
     80   1.1       cgd 	}
     81   1.9   thorpej 
     82   1.9   thorpej 	return possible;
     83   1.1       cgd }
     84   1.1       cgd 
     85   1.9   thorpej 
     86   1.9   thorpej /* find the interface with a name
     87   1.1       cgd  */
     88   1.1       cgd struct interface *
     89   1.9   thorpej ifwithname(char *name,			/* "ec0" or whatever */
     90   1.9   thorpej 	   naddr addr)			/* 0 or network address */
     91   1.1       cgd {
     92   1.9   thorpej 	struct interface *ifp;
     93   1.9   thorpej 
     94   1.1       cgd 
     95   1.9   thorpej 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
     96   1.9   thorpej 		if (!strcmp(ifp->int_name, name)
     97   1.9   thorpej 		    && (ifp->int_addr == addr
     98   1.9   thorpej 			|| (addr == 0 && !(ifp->int_state & IS_ALIAS))))
     99   1.9   thorpej 			return ifp;
    100   1.1       cgd 	}
    101   1.9   thorpej 	return 0;
    102   1.1       cgd }
    103   1.1       cgd 
    104   1.9   thorpej 
    105   1.1       cgd struct interface *
    106   1.9   thorpej ifwithindex(u_short index)
    107   1.1       cgd {
    108   1.9   thorpej 	struct interface *ifp;
    109   1.9   thorpej 
    110   1.9   thorpej 
    111   1.9   thorpej 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
    112   1.9   thorpej 		if (ifp->int_index == index)
    113   1.9   thorpej 			return ifp;
    114   1.1       cgd 	}
    115   1.9   thorpej 	return 0;
    116   1.1       cgd }
    117   1.1       cgd 
    118   1.9   thorpej 
    119   1.9   thorpej /* Find an interface from which the specified address
    120   1.1       cgd  * should have come from.  Used for figuring out which
    121   1.1       cgd  * interface a packet came in on -- for tracing.
    122   1.1       cgd  */
    123   1.1       cgd struct interface *
    124   1.9   thorpej iflookup(naddr addr)
    125   1.1       cgd {
    126   1.9   thorpej 	struct interface *ifp, *maybe;
    127   1.1       cgd 
    128   1.1       cgd 	maybe = 0;
    129   1.1       cgd 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
    130   1.9   thorpej 		if (ifp->int_if_flags & IFF_POINTOPOINT) {
    131   1.9   thorpej 			if (ifp->int_dstaddr == addr)
    132   1.9   thorpej 				/* finished with a match */
    133   1.9   thorpej 				return ifp;
    134   1.9   thorpej 
    135   1.9   thorpej 		} else {
    136   1.9   thorpej 			/* finished with an exact match */
    137   1.9   thorpej 			if (ifp->int_addr == addr)
    138   1.9   thorpej 				return ifp;
    139   1.9   thorpej 			if ((ifp->int_if_flags & IFF_BROADCAST)
    140   1.9   thorpej 			    && ifp->int_brdaddr == addr)
    141   1.9   thorpej 				return ifp;
    142   1.9   thorpej 
    143   1.9   thorpej 			/* Look for the longest approximate match.
    144   1.9   thorpej 			 */
    145   1.9   thorpej 			if (on_net(addr, ifp->int_net, ifp->int_mask)
    146   1.9   thorpej 			    && (maybe == 0
    147   1.9   thorpej 				|| ifp->int_mask > maybe->int_mask))
    148   1.9   thorpej 				maybe = ifp;
    149   1.9   thorpej 		}
    150   1.9   thorpej 	}
    151   1.9   thorpej 
    152   1.9   thorpej 	return maybe;
    153   1.9   thorpej }
    154   1.9   thorpej 
    155   1.9   thorpej 
    156   1.9   thorpej /* Return the classical netmask for an IP address.
    157   1.9   thorpej  */
    158   1.9   thorpej naddr
    159   1.9   thorpej std_mask(naddr addr)			/* in network order */
    160   1.9   thorpej {
    161   1.9   thorpej 	NTOHL(addr);			/* was a host, not a network */
    162   1.9   thorpej 
    163   1.9   thorpej 	if (addr == 0)			/* default route has mask 0 */
    164   1.9   thorpej 		return 0;
    165   1.9   thorpej 	if (IN_CLASSA(addr))
    166   1.9   thorpej 		return IN_CLASSA_NET;
    167   1.9   thorpej 	if (IN_CLASSB(addr))
    168   1.9   thorpej 		return IN_CLASSB_NET;
    169   1.9   thorpej 	return IN_CLASSC_NET;
    170   1.9   thorpej }
    171   1.9   thorpej 
    172   1.9   thorpej 
    173  1.10  christos /* Find the netmask that would be inferred by RIPv1 listeners
    174   1.9   thorpej  *	on the given interface for a given network.
    175   1.9   thorpej  *	If no interface is specified, look for the best fitting	interface.
    176   1.9   thorpej  */
    177   1.9   thorpej naddr
    178   1.9   thorpej ripv1_mask_net(naddr addr,		/* in network byte order */
    179   1.9   thorpej 	       struct interface *ifp)	/* as seen on this interface */
    180   1.9   thorpej {
    181   1.9   thorpej 	naddr mask = 0;
    182   1.9   thorpej 
    183   1.9   thorpej 	if (addr == 0)			/* default always has 0 mask */
    184   1.9   thorpej 		return mask;
    185   1.9   thorpej 
    186   1.9   thorpej 	if (ifp != 0) {
    187   1.9   thorpej 		/* If the target network is that of the associated interface
    188   1.9   thorpej 		 * on which it arrived, then use the netmask of the interface.
    189   1.9   thorpej 		 */
    190   1.9   thorpej 		if (on_net(addr, ifp->int_net, ifp->int_std_mask))
    191   1.9   thorpej 			mask = ifp->int_ripv1_mask;
    192   1.9   thorpej 
    193   1.9   thorpej 	} else {
    194   1.9   thorpej 		/* Examine all interfaces, and if it the target seems
    195   1.9   thorpej 		 * to have the same network number of an interface, use the
    196   1.9   thorpej 		 * netmask of that interface.  If there is more than one
    197   1.9   thorpej 		 * such interface, prefer the interface with the longest
    198   1.9   thorpej 		 * match.
    199   1.9   thorpej 		 */
    200   1.9   thorpej 		for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
    201   1.9   thorpej 			if (on_net(addr, ifp->int_std_net, ifp->int_std_mask)
    202   1.9   thorpej 			    && ifp->int_ripv1_mask > mask)
    203   1.9   thorpej 				mask = ifp->int_ripv1_mask;
    204   1.9   thorpej 		}
    205   1.9   thorpej 	}
    206   1.9   thorpej 
    207   1.9   thorpej 	/* Otherwise, make the classic A/B/C guess.
    208   1.9   thorpej 	 */
    209   1.9   thorpej 	if (mask == 0)
    210   1.9   thorpej 		mask = std_mask(addr);
    211   1.9   thorpej 
    212   1.9   thorpej 	return mask;
    213   1.9   thorpej }
    214   1.9   thorpej 
    215   1.9   thorpej 
    216   1.9   thorpej naddr
    217   1.9   thorpej ripv1_mask_host(naddr addr,		/* in network byte order */
    218   1.9   thorpej 		struct interface *ifp)	/* as seen on this interface */
    219   1.9   thorpej {
    220   1.9   thorpej 	naddr mask = ripv1_mask_net(addr, ifp);
    221   1.9   thorpej 
    222   1.9   thorpej 
    223   1.9   thorpej 	/* If the computed netmask does not mask the address,
    224   1.9   thorpej 	 * then assume it is a host address
    225   1.9   thorpej 	 */
    226   1.9   thorpej 	if ((ntohl(addr) & ~mask) != 0)
    227   1.9   thorpej 		mask = HOST_MASK;
    228   1.9   thorpej 	return mask;
    229   1.9   thorpej }
    230   1.9   thorpej 
    231   1.9   thorpej 
    232   1.9   thorpej /* See if a IP address looks reasonable as a destination
    233   1.9   thorpej  */
    234   1.9   thorpej int					/* 0=bad */
    235   1.9   thorpej check_dst(naddr addr)
    236   1.9   thorpej {
    237   1.9   thorpej 	NTOHL(addr);
    238   1.9   thorpej 
    239   1.9   thorpej 	if (IN_CLASSA(addr)) {
    240   1.9   thorpej 		if (addr == 0)
    241   1.9   thorpej 			return 1;	/* default */
    242   1.9   thorpej 
    243   1.9   thorpej 		addr >>= IN_CLASSA_NSHIFT;
    244   1.9   thorpej 		return (addr != 0 && addr != IN_LOOPBACKNET);
    245   1.9   thorpej 	}
    246   1.9   thorpej 
    247   1.9   thorpej 	return (IN_CLASSB(addr) || IN_CLASSC(addr));
    248   1.9   thorpej }
    249   1.9   thorpej 
    250   1.9   thorpej 
    251   1.9   thorpej /* Delete an interface.
    252   1.9   thorpej  */
    253   1.9   thorpej static void
    254   1.9   thorpej ifdel(struct interface *ifp)
    255   1.9   thorpej {
    256   1.9   thorpej 	struct ip_mreq m;
    257   1.9   thorpej 	struct interface *ifp1;
    258   1.9   thorpej 
    259   1.9   thorpej 
    260   1.9   thorpej 	trace_if("Del", ifp);
    261   1.9   thorpej 
    262   1.9   thorpej 	ifp->int_state |= IS_BROKE;
    263   1.9   thorpej 
    264   1.9   thorpej 	/* unlink the interface
    265   1.9   thorpej 	 */
    266   1.9   thorpej 	if (rip_sock_mcast == ifp)
    267   1.9   thorpej 		rip_sock_mcast = 0;
    268   1.9   thorpej 	if (ifp->int_next != 0)
    269   1.9   thorpej 		ifp->int_next->int_prev = ifp->int_prev;
    270   1.9   thorpej 	if (ifp->int_prev != 0)
    271   1.9   thorpej 		ifp->int_prev->int_next = ifp->int_next;
    272   1.9   thorpej 	else
    273   1.9   thorpej 		ifnet = ifp->int_next;
    274   1.9   thorpej 
    275   1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    276   1.9   thorpej 		/* delete aliases
    277   1.9   thorpej 		 */
    278   1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    279   1.9   thorpej 			if (ifp1 != ifp
    280   1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    281   1.9   thorpej 				ifdel(ifp1);
    282   1.9   thorpej 		}
    283   1.9   thorpej 
    284   1.9   thorpej 		if ((ifp->int_if_flags & IFF_MULTICAST)
    285   1.9   thorpej #ifdef MCAST_PPP_BUG
    286   1.9   thorpej 		    && !(ifp->int_if_flags & IFF_POINTOPOINT)
    287   1.9   thorpej #endif
    288   1.9   thorpej 		    && rip_sock >= 0) {
    289   1.9   thorpej 			m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
    290   1.9   thorpej 			m.imr_interface.s_addr = ((ifp->int_if_flags
    291   1.9   thorpej 						   & IFF_POINTOPOINT)
    292   1.9   thorpej 						  ? ifp->int_dstaddr
    293   1.9   thorpej 						  : ifp->int_addr);
    294   1.9   thorpej 			if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,
    295   1.9   thorpej 				       &m, sizeof(m)) < 0
    296   1.9   thorpej 			    && errno != EADDRNOTAVAIL
    297   1.9   thorpej 			    && !TRACEACTIONS)
    298   1.9   thorpej 				LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)");
    299   1.9   thorpej 		}
    300   1.9   thorpej 		if (ifp->int_rip_sock >= 0) {
    301   1.9   thorpej 			(void)close(ifp->int_rip_sock);
    302   1.9   thorpej 			ifp->int_rip_sock = -1;
    303   1.9   thorpej 			fix_select();
    304   1.9   thorpej 		}
    305   1.9   thorpej 
    306   1.9   thorpej 		tot_interfaces--;
    307   1.9   thorpej 		if (!IS_RIP_OFF(ifp->int_state))
    308   1.9   thorpej 			rip_interfaces--;
    309   1.9   thorpej 
    310   1.9   thorpej 		/* Zap all routes associated with this interface.
    311   1.9   thorpej 		 * Assume routes just using gateways beyond this interface will
    312   1.9   thorpej 		 * timeout naturally, and have probably already died.
    313   1.9   thorpej 		 */
    314   1.9   thorpej 		(void)rn_walktree(rhead, walk_bad, 0);
    315   1.9   thorpej 
    316   1.9   thorpej 		set_rdisc_mg(ifp, 0);
    317   1.9   thorpej 		if_bad_rdisc(ifp);
    318   1.9   thorpej 	}
    319   1.9   thorpej 
    320   1.9   thorpej 	free(ifp);
    321   1.9   thorpej }
    322   1.9   thorpej 
    323   1.9   thorpej 
    324   1.9   thorpej /* Mark an interface ill.
    325   1.9   thorpej  */
    326   1.9   thorpej void
    327   1.9   thorpej if_sick(struct interface *ifp)
    328   1.9   thorpej {
    329   1.9   thorpej 	if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) {
    330   1.9   thorpej 		ifp->int_state |= IS_SICK;
    331   1.9   thorpej 		trace_if("Chg", ifp);
    332   1.9   thorpej 
    333   1.9   thorpej 		LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
    334   1.9   thorpej 	}
    335   1.9   thorpej }
    336   1.9   thorpej 
    337   1.9   thorpej 
    338   1.9   thorpej /* Mark an interface dead.
    339   1.9   thorpej  */
    340   1.9   thorpej void
    341   1.9   thorpej if_bad(struct interface *ifp)
    342   1.9   thorpej {
    343   1.9   thorpej 	struct interface *ifp1;
    344   1.9   thorpej 
    345   1.9   thorpej 
    346   1.9   thorpej 	if (ifp->int_state & IS_BROKE)
    347   1.9   thorpej 		return;
    348   1.9   thorpej 
    349   1.9   thorpej 	LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
    350   1.9   thorpej 
    351   1.9   thorpej 	ifp->int_state |= (IS_BROKE | IS_SICK);
    352   1.9   thorpej 	ifp->int_state &= ~(IS_RIP_QUERIED | IS_ACTIVE);
    353   1.9   thorpej 	ifp->int_data.ts = 0;
    354   1.9   thorpej 
    355   1.9   thorpej 	trace_if("Chg", ifp);
    356   1.9   thorpej 
    357   1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    358   1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    359   1.9   thorpej 			if (ifp1 != ifp
    360   1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    361   1.9   thorpej 				if_bad(ifp1);
    362   1.9   thorpej 		}
    363   1.9   thorpej 		(void)rn_walktree(rhead, walk_bad, 0);
    364   1.9   thorpej 		if_bad_rdisc(ifp);
    365   1.9   thorpej 	}
    366   1.9   thorpej }
    367   1.9   thorpej 
    368   1.9   thorpej 
    369   1.9   thorpej /* Mark an interface alive
    370   1.9   thorpej  */
    371   1.9   thorpej int					/* 1=it was dead */
    372   1.9   thorpej if_ok(struct interface *ifp,
    373   1.9   thorpej       char *type)
    374   1.9   thorpej {
    375   1.9   thorpej 	struct interface *ifp1;
    376   1.9   thorpej 
    377   1.9   thorpej 
    378   1.9   thorpej 	if (!(ifp->int_state & IS_BROKE)) {
    379   1.9   thorpej 		if (ifp->int_state & IS_SICK) {
    380   1.9   thorpej 			trace_act("%sinterface %s to %s working better\n",
    381   1.9   thorpej 				  type,
    382   1.9   thorpej 				  ifp->int_name, naddr_ntoa(ifp->int_addr));
    383   1.9   thorpej 			ifp->int_state &= ~IS_SICK;
    384   1.9   thorpej 		}
    385   1.9   thorpej 		return 0;
    386   1.9   thorpej 	}
    387   1.9   thorpej 
    388   1.9   thorpej 	msglog("%sinterface %s to %s restored",
    389   1.9   thorpej 	       type, ifp->int_name, naddr_ntoa(ifp->int_addr));
    390   1.9   thorpej 	ifp->int_state &= ~(IS_BROKE | IS_SICK);
    391   1.9   thorpej 	ifp->int_data.ts = 0;
    392   1.9   thorpej 
    393   1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    394   1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    395   1.9   thorpej 			if (ifp1 != ifp
    396   1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    397   1.9   thorpej 				if_ok(ifp1, type);
    398   1.9   thorpej 		}
    399   1.9   thorpej 		if_ok_rdisc(ifp);
    400   1.9   thorpej 	}
    401   1.9   thorpej 	return 1;
    402   1.9   thorpej }
    403   1.9   thorpej 
    404   1.9   thorpej 
    405   1.9   thorpej /* disassemble routing message
    406   1.9   thorpej  */
    407   1.9   thorpej void
    408   1.9   thorpej rt_xaddrs(struct rt_addrinfo *info,
    409   1.9   thorpej 	  struct sockaddr *sa,
    410   1.9   thorpej 	  struct sockaddr *lim,
    411   1.9   thorpej 	  int addrs)
    412   1.9   thorpej {
    413   1.9   thorpej 	int i;
    414   1.9   thorpej #ifdef _HAVE_SA_LEN
    415   1.9   thorpej 	static struct sockaddr sa_zero;
    416   1.9   thorpej #endif
    417   1.9   thorpej #ifdef sgi
    418   1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
    419   1.9   thorpej 		    : sizeof(__uint64_t))
    420   1.9   thorpej #else
    421   1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
    422   1.9   thorpej 		    : sizeof(long))
    423   1.9   thorpej #endif
    424   1.9   thorpej 
    425   1.9   thorpej 
    426   1.9   thorpej 	bzero(info, sizeof(*info));
    427   1.9   thorpej 	info->rti_addrs = addrs;
    428   1.9   thorpej 	for (i = 0; i < RTAX_MAX && sa < lim; i++) {
    429   1.9   thorpej 		if ((addrs & (1 << i)) == 0)
    430   1.9   thorpej 			continue;
    431   1.9   thorpej #ifdef _HAVE_SA_LEN
    432   1.9   thorpej 		info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero;
    433   1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    434   1.9   thorpej 					 + ROUNDUP(sa->sa_len));
    435   1.9   thorpej #else
    436   1.9   thorpej 		info->rti_info[i] = sa;
    437   1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    438   1.9   thorpej 					 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
    439   1.9   thorpej #endif
    440   1.9   thorpej 	}
    441   1.9   thorpej }
    442   1.9   thorpej 
    443   1.9   thorpej 
    444   1.9   thorpej /* Find the network interfaces which have configured themselves.
    445   1.9   thorpej  *	This must be done regularly, if only for extra addresses
    446   1.9   thorpej  *	that come and go on interfaces.
    447   1.9   thorpej  */
    448   1.9   thorpej void
    449   1.9   thorpej ifinit(void)
    450   1.9   thorpej {
    451   1.9   thorpej 	static char *sysctl_buf;
    452   1.9   thorpej 	static size_t sysctl_buf_size = 0;
    453   1.9   thorpej 	uint complaints = 0;
    454   1.9   thorpej 	static u_int prev_complaints = 0;
    455  1.10  christos #	define COMP_NOT_INET	0x001
    456  1.10  christos #	define COMP_WIERD	0x002
    457  1.10  christos #	define COMP_NOADDR	0x004
    458  1.10  christos #	define COMP_BADADDR	0x008
    459  1.10  christos #	define COMP_NODST	0x010
    460  1.10  christos #	define COMP_NOBADR	0x020
    461  1.10  christos #	define COMP_NOMASK	0x040
    462  1.10  christos #	define COMP_DUP		0x080
    463  1.10  christos #	define COMP_BAD_METRIC	0x100
    464  1.10  christos #	define COMP_NETMASK	0x200
    465   1.9   thorpej 
    466   1.9   thorpej 	struct interface ifs, ifs0, *ifp, *ifp1;
    467   1.9   thorpej 	struct rt_entry *rt;
    468   1.9   thorpej 	size_t needed;
    469   1.9   thorpej 	int mib[6];
    470   1.9   thorpej 	struct if_msghdr *ifm;
    471   1.9   thorpej 	struct ifa_msghdr *ifam, *ifam_lim, *ifam2;
    472   1.9   thorpej 	struct sockaddr_dl *sdl;
    473   1.9   thorpej 	int in, ierr, out, oerr;
    474   1.9   thorpej 	struct intnet *intnetp;
    475   1.9   thorpej 	struct rt_addrinfo info;
    476   1.9   thorpej #ifdef SIOCGIFMETRIC
    477   1.9   thorpej 	struct ifreq ifr;
    478   1.9   thorpej #endif
    479   1.9   thorpej 
    480   1.9   thorpej 
    481   1.9   thorpej 	ifinit_timer.tv_sec = now.tv_sec + (supplier
    482   1.9   thorpej 					    ? CHECK_ACT_INTERVAL
    483   1.9   thorpej 					    : CHECK_QUIET_INTERVAL);
    484   1.9   thorpej 
    485   1.9   thorpej 	/* mark all interfaces so we can get rid of thost that disappear */
    486   1.9   thorpej 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
    487   1.9   thorpej 		ifp->int_state &= ~(IS_CHECKED | IS_DUP);
    488   1.9   thorpej 
    489   1.9   thorpej 	/* Fetch the interface list, without too many system calls
    490   1.9   thorpej 	 * since we do it repeatedly.
    491   1.9   thorpej 	 */
    492   1.9   thorpej 	mib[0] = CTL_NET;
    493   1.9   thorpej 	mib[1] = PF_ROUTE;
    494   1.9   thorpej 	mib[2] = 0;
    495   1.9   thorpej 	mib[3] = AF_INET;
    496   1.9   thorpej 	mib[4] = NET_RT_IFLIST;
    497   1.9   thorpej 	mib[5] = 0;
    498   1.9   thorpej 	for (;;) {
    499   1.9   thorpej 		if ((needed = sysctl_buf_size) != 0) {
    500   1.9   thorpej 			if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
    501   1.9   thorpej 				break;
    502   1.9   thorpej 			if (errno != ENOMEM && errno != EFAULT)
    503   1.9   thorpej 				BADERR(1, "ifinit: get interface table");
    504   1.9   thorpej 			free(sysctl_buf);
    505   1.9   thorpej 			needed = 0;
    506   1.9   thorpej 		}
    507   1.9   thorpej 		if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
    508   1.9   thorpej 			BADERR(1,"ifinit: route-sysctl-estimate");
    509  1.10  christos 		sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit");
    510   1.9   thorpej 	}
    511   1.9   thorpej 
    512   1.9   thorpej 	ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
    513   1.9   thorpej 	for (ifam = (struct ifa_msghdr *)sysctl_buf;
    514   1.9   thorpej 	     ifam < ifam_lim;
    515   1.9   thorpej 	     ifam = ifam2) {
    516   1.9   thorpej 
    517   1.9   thorpej 		ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen);
    518   1.9   thorpej 
    519   1.9   thorpej 		if (ifam->ifam_type == RTM_IFINFO) {
    520   1.9   thorpej 			ifm = (struct if_msghdr *)ifam;
    521   1.9   thorpej 			/* make prototype structure for the IP aliases
    522   1.9   thorpej 			 */
    523   1.9   thorpej 			bzero(&ifs0, sizeof(ifs0));
    524   1.9   thorpej 			ifs0.int_rip_sock = -1;
    525   1.9   thorpej 			ifs0.int_index = ifm->ifm_index;
    526   1.9   thorpej 			ifs0.int_if_flags = ifm->ifm_flags;
    527   1.9   thorpej 			ifs0.int_state = IS_CHECKED;
    528   1.9   thorpej 			ifs0.int_act_time = now.tv_sec;
    529   1.9   thorpej 			ifs0.int_data.ts = now.tv_sec;
    530   1.9   thorpej 			ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets;
    531   1.9   thorpej 			ifs0.int_data.ierrors = ifm->ifm_data.ifi_ierrors;
    532   1.9   thorpej 			ifs0.int_data.opackets = ifm->ifm_data.ifi_opackets;
    533   1.9   thorpej 			ifs0.int_data.oerrors = ifm->ifm_data.ifi_oerrors;
    534   1.9   thorpej #ifdef sgi
    535   1.9   thorpej 			ifs0.int_data.odrops = ifm->ifm_data.ifi_odrops;
    536   1.9   thorpej #endif
    537   1.9   thorpej 			sdl = (struct sockaddr_dl *)(ifm + 1);
    538   1.9   thorpej 			sdl->sdl_data[sdl->sdl_nlen] = 0;
    539   1.9   thorpej 			continue;
    540   1.9   thorpej 		}
    541   1.9   thorpej 		if (ifam->ifam_type != RTM_NEWADDR) {
    542  1.10  christos 			logbad(1,"ifinit: out of sync");
    543   1.9   thorpej 			continue;
    544   1.9   thorpej 		}
    545   1.9   thorpej 
    546   1.9   thorpej 		rt_xaddrs(&info, (struct sockaddr *)(ifam+1),
    547   1.9   thorpej 			  (struct sockaddr *)ifam2,
    548   1.9   thorpej 			  ifam->ifam_addrs);
    549   1.9   thorpej 
    550   1.9   thorpej 		if (INFO_IFA(&info) == 0) {
    551   1.9   thorpej 			if (iff_alive(ifs.int_if_flags)) {
    552   1.9   thorpej 				if (!(prev_complaints & COMP_NOADDR))
    553  1.10  christos 					msglog("%s has no address",
    554   1.9   thorpej 					       sdl->sdl_data);
    555   1.9   thorpej 				complaints |= COMP_NOADDR;
    556   1.9   thorpej 			}
    557   1.9   thorpej 			continue;
    558   1.9   thorpej 		}
    559   1.9   thorpej 		if (INFO_IFA(&info)->sa_family != AF_INET) {
    560   1.9   thorpej 			if (iff_alive(ifs.int_if_flags)) {
    561   1.9   thorpej 				if (!(prev_complaints & COMP_NOT_INET))
    562   1.9   thorpej 					trace_act("%s: not AF_INET\n",
    563   1.9   thorpej 						  sdl->sdl_data);
    564   1.9   thorpej 				complaints |= COMP_NOT_INET;
    565   1.9   thorpej 			}
    566   1.9   thorpej 			continue;
    567   1.9   thorpej 		}
    568   1.9   thorpej 
    569   1.9   thorpej 		bcopy(&ifs0, &ifs, sizeof(ifs0));
    570   1.9   thorpej 		ifs0.int_state |= IS_ALIAS;	/* next will be an alias */
    571   1.9   thorpej 
    572   1.9   thorpej 		ifs.int_addr = S_ADDR(INFO_IFA(&info));
    573   1.9   thorpej 
    574  1.10  christos 		if (ntohl(ifs.int_addr)>>24 == 0
    575  1.10  christos 		    || ntohl(ifs.int_addr)>>24 == 0xff) {
    576  1.10  christos 			if (iff_alive(ifs.int_if_flags)) {
    577  1.10  christos 				if (!(prev_complaints & COMP_BADADDR))
    578  1.10  christos 					msglog("%s has a bad address",
    579  1.10  christos 					       sdl->sdl_data);
    580  1.10  christos 				complaints |= COMP_BADADDR;
    581  1.10  christos 			}
    582  1.10  christos 			continue;
    583  1.10  christos 		}
    584  1.10  christos 
    585   1.9   thorpej 		if (ifs.int_if_flags & IFF_BROADCAST) {
    586   1.9   thorpej 			if (INFO_MASK(&info) == 0) {
    587   1.9   thorpej 				if (iff_alive(ifs.int_if_flags)) {
    588   1.9   thorpej 					if (!(prev_complaints & COMP_NOMASK))
    589   1.9   thorpej 						msglog("%s has no netmask",
    590   1.9   thorpej 						       sdl->sdl_data);
    591   1.9   thorpej 					complaints |= COMP_NOMASK;
    592   1.9   thorpej 				}
    593   1.9   thorpej 				continue;
    594   1.9   thorpej 			}
    595   1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    596   1.9   thorpej 			ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    597   1.9   thorpej 			ifs.int_ripv1_mask = ifs.int_mask;
    598   1.9   thorpej 			ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask;
    599   1.9   thorpej 			ifs.int_std_mask = std_mask(ifs.int_addr);
    600   1.9   thorpej 			if (ifs.int_mask != ifs.int_std_mask)
    601   1.9   thorpej 				ifs.int_state |= IS_SUBNET;
    602   1.9   thorpej 
    603   1.9   thorpej 			if (INFO_BRD(&info) == 0) {
    604   1.9   thorpej 				if (iff_alive(ifs.int_if_flags)) {
    605   1.9   thorpej 					if (!(prev_complaints & COMP_NOBADR))
    606   1.9   thorpej 						msglog("%s has no"
    607   1.9   thorpej 						       " broadcast address",
    608   1.9   thorpej 						       sdl->sdl_data);
    609   1.9   thorpej 					complaints |= COMP_NOBADR;
    610   1.9   thorpej 				}
    611   1.9   thorpej 				continue;
    612   1.9   thorpej 			}
    613   1.9   thorpej 			ifs.int_brdaddr = S_ADDR(INFO_BRD(&info));
    614   1.9   thorpej 
    615   1.9   thorpej 		} else if (ifs.int_if_flags & IFF_POINTOPOINT) {
    616   1.9   thorpej 			if (INFO_BRD(&info) == 0
    617   1.9   thorpej 			    || INFO_BRD(&info)->sa_family != AF_INET) {
    618   1.9   thorpej 				if (iff_alive(ifs.int_if_flags)) {
    619   1.9   thorpej 					if (!(prev_complaints & COMP_NODST))
    620   1.9   thorpej 						msglog("%s has a bad"
    621   1.9   thorpej 						       " destination address",
    622   1.9   thorpej 						       sdl->sdl_data);
    623   1.9   thorpej 					complaints |= COMP_NODST;
    624   1.9   thorpej 				}
    625   1.9   thorpej 				continue;
    626   1.9   thorpej 			}
    627   1.9   thorpej 			ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
    628  1.10  christos 			if (ntohl(ifs.int_dstaddr)>>24 == 0
    629  1.10  christos 			    || ntohl(ifs.int_dstaddr)>>24 == 0xff) {
    630  1.10  christos 				if (iff_alive(ifs.int_if_flags)) {
    631  1.10  christos 					if (!(prev_complaints & COMP_NODST))
    632  1.10  christos 						msglog("%s has a bad"
    633  1.10  christos 						       " destination address",
    634  1.10  christos 						       sdl->sdl_data);
    635  1.10  christos 					complaints |= COMP_NODST;
    636  1.10  christos 				}
    637  1.10  christos 				continue;
    638  1.10  christos 			}
    639   1.9   thorpej 			ifs.int_mask = HOST_MASK;
    640   1.9   thorpej 			ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    641   1.9   thorpej 			ifs.int_net = ntohl(ifs.int_dstaddr);
    642   1.9   thorpej 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    643   1.9   thorpej 
    644   1.9   thorpej 		} else if (ifs.int_if_flags & IFF_LOOPBACK) {
    645   1.9   thorpej 			ifs.int_state |= IS_PASSIVE | IS_NO_RIP;
    646   1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    647   1.9   thorpej 			ifs.int_mask = HOST_MASK;
    648   1.9   thorpej 			ifs.int_ripv1_mask = HOST_MASK;
    649   1.9   thorpej 			ifs.int_net = ntohl(ifs.int_dstaddr);
    650   1.9   thorpej 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    651   1.9   thorpej 			if (!foundloopback) {
    652   1.9   thorpej 				foundloopback = 1;
    653   1.9   thorpej 				loopaddr = ifs.int_addr;
    654   1.9   thorpej 			}
    655   1.9   thorpej 
    656   1.9   thorpej 		} else {
    657   1.9   thorpej 			if (!(prev_complaints & COMP_WIERD))
    658   1.9   thorpej 				trace_act("%s is neither broadcast"
    659   1.9   thorpej 					  " nor point-to-point nor loopback",
    660   1.9   thorpej 					  sdl->sdl_data);
    661   1.9   thorpej 			complaints |= COMP_WIERD;
    662   1.1       cgd 			continue;
    663   1.9   thorpej 		}
    664   1.9   thorpej 		ifs.int_std_net = ifs.int_net & ifs.int_std_mask;
    665   1.9   thorpej 		ifs.int_std_addr = htonl(ifs.int_std_net);
    666   1.9   thorpej 
    667   1.9   thorpej 		/* Use a minimum metric of one.  Treat the interface metric
    668   1.9   thorpej 		 * (default 0) as an increment to the hop count of one.
    669   1.9   thorpej 		 *
    670   1.9   thorpej 		 * The metric obtained from the routing socket dump of
    671   1.9   thorpej 		 * interface addresses is wrong.  It is not set by the
    672   1.9   thorpej 		 * SIOCSIFMETRIC ioctl.
    673   1.9   thorpej 		 */
    674   1.9   thorpej #ifdef SIOCGIFMETRIC
    675   1.9   thorpej 		strncpy(ifr.ifr_name, sdl->sdl_data, sizeof(ifr.ifr_name));
    676   1.9   thorpej 		if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) {
    677   1.9   thorpej 			DBGERR(1, "ioctl(SIOCGIFMETRIC)");
    678   1.9   thorpej 			ifs.int_metric = 0;
    679   1.9   thorpej 		} else {
    680   1.9   thorpej 			ifs.int_metric = ifr.ifr_metric;
    681   1.9   thorpej 		}
    682   1.9   thorpej #else
    683   1.9   thorpej 		ifs.int_metric = ifam->ifam_metric;
    684   1.9   thorpej #endif
    685   1.9   thorpej 		if (ifs.int_metric > HOPCNT_INFINITY) {
    686   1.9   thorpej 			ifs.int_metric = 0;
    687   1.9   thorpej 			if (!(prev_complaints & COMP_BAD_METRIC)
    688   1.9   thorpej 			    && iff_alive(ifs.int_if_flags)) {
    689   1.9   thorpej 				complaints |= COMP_BAD_METRIC;
    690   1.9   thorpej 				msglog("%s has a metric of %d",
    691   1.9   thorpej 				       sdl->sdl_data, ifs.int_metric);
    692   1.9   thorpej 			}
    693   1.9   thorpej 		}
    694   1.9   thorpej 
    695   1.9   thorpej 		/* See if this is a familiar interface.
    696   1.9   thorpej 		 * If so, stop worrying about it if it is the same.
    697   1.9   thorpej 		 * Start it over if it now is to somewhere else, as happens
    698   1.9   thorpej 		 * frequently with PPP and SLIP.
    699   1.9   thorpej 		 */
    700   1.9   thorpej 		ifp = ifwithname(sdl->sdl_data, ((ifs.int_state & IS_ALIAS)
    701   1.9   thorpej 						 ? ifs.int_addr
    702   1.9   thorpej 						 : 0));
    703   1.9   thorpej 		if (ifp != 0) {
    704   1.9   thorpej 			ifp->int_state |= IS_CHECKED;
    705   1.9   thorpej 
    706   1.9   thorpej 			if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags)
    707   1.9   thorpej 				  & (IFF_BROADCAST
    708   1.9   thorpej 				     | IFF_LOOPBACK
    709   1.9   thorpej 				     | IFF_POINTOPOINT
    710   1.9   thorpej 				     | IFF_MULTICAST))
    711   1.9   thorpej 			    || 0 != ((ifp->int_state ^ ifs.int_state)
    712   1.9   thorpej 				     & IS_ALIAS)
    713   1.9   thorpej 			    || ifp->int_addr != ifs.int_addr
    714   1.9   thorpej 			    || ifp->int_brdaddr != ifs.int_brdaddr
    715   1.9   thorpej 			    || ifp->int_dstaddr != ifs.int_dstaddr
    716   1.9   thorpej 			    || ifp->int_mask != ifs.int_mask
    717   1.9   thorpej 			    || ifp->int_metric != ifs.int_metric) {
    718   1.9   thorpej 				/* Forget old information about
    719   1.9   thorpej 				 * a changed interface.
    720   1.9   thorpej 				 */
    721   1.9   thorpej 				trace_act("interface %s has changed\n",
    722   1.9   thorpej 					  ifp->int_name);
    723   1.9   thorpej 				ifdel(ifp);
    724   1.9   thorpej 				ifp = 0;
    725   1.9   thorpej 			}
    726   1.9   thorpej 		}
    727   1.9   thorpej 
    728   1.9   thorpej 		if (ifp != 0) {
    729  1.10  christos 			/* The primary representative of an alias worries
    730  1.10  christos 			 * about how things are working.
    731  1.10  christos 			 */
    732   1.9   thorpej 			if (ifp->int_state & IS_ALIAS)
    733   1.9   thorpej 				continue;
    734   1.9   thorpej 
    735   1.9   thorpej 			/* note interfaces that have been turned off
    736   1.9   thorpej 			 */
    737   1.9   thorpej 			if (!iff_alive(ifs.int_if_flags)) {
    738   1.9   thorpej 				if (iff_alive(ifp->int_if_flags)) {
    739   1.9   thorpej 					msglog("interface %s to %s turned off",
    740   1.9   thorpej 					       ifp->int_name,
    741   1.9   thorpej 					       naddr_ntoa(ifp->int_addr));
    742   1.9   thorpej 					if_bad(ifp);
    743   1.9   thorpej 					ifp->int_if_flags &= ~IFF_UP_RUNNING;
    744   1.9   thorpej 				}
    745   1.9   thorpej 				continue;
    746   1.9   thorpej 			}
    747   1.9   thorpej 			/* or that were off and are now ok */
    748   1.9   thorpej 			if (!iff_alive(ifp->int_if_flags)) {
    749   1.9   thorpej 				ifp->int_if_flags |= IFF_UP_RUNNING;
    750   1.9   thorpej 				(void)if_ok(ifp, "");
    751   1.9   thorpej 			}
    752   1.9   thorpej 
    753   1.9   thorpej 			/* If it has been long enough,
    754   1.9   thorpej 			 * see if the interface is broken.
    755   1.9   thorpej 			 */
    756   1.9   thorpej 			if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL)
    757   1.9   thorpej 				continue;
    758   1.9   thorpej 
    759   1.9   thorpej 			in = ifs.int_data.ipackets - ifp->int_data.ipackets;
    760   1.9   thorpej 			ierr = ifs.int_data.ierrors - ifp->int_data.ierrors;
    761   1.9   thorpej 			out = ifs.int_data.opackets - ifp->int_data.opackets;
    762   1.9   thorpej 			oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
    763   1.9   thorpej #ifdef sgi
    764   1.9   thorpej 			/* Through at least IRIX 6.2, PPP and SLIP
    765   1.9   thorpej 			 * count packets dropped by  the filters.
    766   1.9   thorpej 			 * But FDDI rings stuck non-operational count
    767   1.9   thorpej 			 * dropped packets as they wait for improvement.
    768   1.9   thorpej 			 */
    769   1.9   thorpej 			if (!(ifp->int_if_flags & IFF_POINTOPOINT))
    770   1.9   thorpej 				oerr += (ifs.int_data.odrops
    771   1.9   thorpej 					 - ifp->int_data.odrops);
    772   1.9   thorpej #endif
    773   1.9   thorpej 			/* If the interface just awoke, restart the counters.
    774   1.9   thorpej 			 */
    775   1.9   thorpej 			if (ifp->int_data.ts == 0) {
    776   1.9   thorpej 				ifp->int_data = ifs.int_data;
    777   1.9   thorpej 				continue;
    778   1.9   thorpej 			}
    779   1.9   thorpej 			ifp->int_data = ifs.int_data;
    780   1.9   thorpej 
    781   1.9   thorpej 			/* Withhold judgement when the short error
    782   1.9   thorpej 			 * counters wrap or the interface is reset.
    783   1.9   thorpej 			 */
    784   1.9   thorpej 			if (ierr < 0 || in < 0 || oerr < 0 || out < 0) {
    785   1.9   thorpej 				LIM_SEC(ifinit_timer,
    786   1.9   thorpej 					now.tv_sec+CHECK_BAD_INTERVAL);
    787   1.9   thorpej 				continue;
    788   1.9   thorpej 			}
    789   1.9   thorpej 
    790   1.9   thorpej 			/* Withhold judgement when there is no traffic
    791   1.9   thorpej 			 */
    792   1.9   thorpej 			if (in == 0 && out == 0 && ierr == 0 && oerr == 0)
    793   1.9   thorpej 				continue;
    794   1.9   thorpej 
    795   1.9   thorpej 			/* It is bad if input or output is not working.
    796   1.9   thorpej 			 * Require presistent problems before marking it dead.
    797   1.9   thorpej 			 */
    798   1.9   thorpej 			if ((in <= ierr && ierr > 0)
    799   1.9   thorpej 			    || (out <= oerr && oerr > 0)) {
    800   1.9   thorpej 				if (!(ifp->int_state & IS_SICK)) {
    801   1.9   thorpej 					trace_act("interface %s to %s"
    802   1.9   thorpej 						  " sick: in=%d ierr=%d"
    803   1.9   thorpej 						  " out=%d oerr=%d\n",
    804   1.9   thorpej 						  ifp->int_name,
    805   1.9   thorpej 						  naddr_ntoa(ifp->int_addr),
    806   1.9   thorpej 						  in, ierr, out, oerr);
    807   1.9   thorpej 					if_sick(ifp);
    808   1.9   thorpej 					continue;
    809   1.9   thorpej 				}
    810   1.9   thorpej 				if (!(ifp->int_state & IS_BROKE)) {
    811   1.9   thorpej 					msglog("interface %s to %s bad:"
    812   1.9   thorpej 					       " in=%d ierr=%d out=%d oerr=%d",
    813   1.9   thorpej 					       ifp->int_name,
    814   1.9   thorpej 					       naddr_ntoa(ifp->int_addr),
    815   1.9   thorpej 					       in, ierr, out, oerr);
    816   1.9   thorpej 					if_bad(ifp);
    817   1.9   thorpej 				}
    818   1.9   thorpej 				continue;
    819   1.9   thorpej 			}
    820   1.9   thorpej 
    821   1.9   thorpej 			/* otherwise, it is active and healthy
    822   1.9   thorpej 			 */
    823   1.9   thorpej 			ifp->int_act_time = now.tv_sec;
    824   1.9   thorpej 			(void)if_ok(ifp, "");
    825   1.9   thorpej 			continue;
    826   1.9   thorpej 		}
    827   1.9   thorpej 
    828   1.9   thorpej 		/* This is a new interface.
    829   1.9   thorpej 		 * If it is dead, forget it.
    830   1.9   thorpej 		 */
    831   1.9   thorpej 		if (!iff_alive(ifs.int_if_flags))
    832   1.9   thorpej 			continue;
    833   1.9   thorpej 
    834   1.9   thorpej 		/* See if it duplicates an existing interface.
    835   1.9   thorpej 		 */
    836   1.9   thorpej 		for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
    837   1.9   thorpej 			if (ifp->int_mask != ifs.int_mask)
    838   1.9   thorpej 				continue;
    839   1.9   thorpej 			if (((ifp->int_addr != ifs.int_addr
    840   1.9   thorpej 			      && ifs.int_mask != HOST_MASK)
    841   1.9   thorpej 			     || (ifp->int_dstaddr != ifs.int_dstaddr
    842   1.9   thorpej 				 && ifs.int_mask == HOST_MASK)))
    843   1.9   thorpej 				continue;
    844   1.9   thorpej 			if (!iff_alive(ifp->int_if_flags))
    845   1.9   thorpej 				continue;
    846   1.9   thorpej 			/* Let one of our real interfaces be marked
    847   1.9   thorpej 			 * passive.
    848   1.9   thorpej 			 */
    849   1.9   thorpej 			if ((ifp->int_state & IS_PASSIVE)
    850   1.9   thorpej 			    && !(ifp->int_state & IS_EXTERNAL))
    851   1.9   thorpej 				continue;
    852   1.9   thorpej 
    853   1.9   thorpej 			/* It does duplicate an existing interface,
    854   1.9   thorpej 			 * so complain about it, mark the other one
    855   1.9   thorpej 			 * duplicated, and for get this one.
    856   1.9   thorpej 			 */
    857   1.9   thorpej 			if (!(prev_complaints & COMP_DUP)) {
    858   1.9   thorpej 				complaints |= COMP_DUP;
    859   1.9   thorpej 				msglog("%s is duplicated by %s at %s",
    860   1.9   thorpej 				       sdl->sdl_data, ifp->int_name,
    861   1.9   thorpej 				       naddr_ntoa(ifp->int_addr));
    862   1.9   thorpej 			}
    863   1.9   thorpej 			ifp->int_state |= IS_DUP;
    864   1.1       cgd 			break;
    865   1.9   thorpej 		}
    866   1.9   thorpej 		if (ifp != 0)
    867   1.9   thorpej 			continue;
    868   1.9   thorpej 
    869   1.9   thorpej 		/* It is new and ok.  So make it real
    870   1.9   thorpej 		 */
    871   1.9   thorpej 		strncpy(ifs.int_name, sdl->sdl_data,
    872   1.9   thorpej 			MIN(sizeof(ifs.int_name)-1, sdl->sdl_nlen));
    873   1.9   thorpej 		get_parms(&ifs);
    874   1.9   thorpej 
    875   1.9   thorpej 		/* Add it to the list of interfaces
    876   1.9   thorpej 		 */
    877  1.10  christos 		ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit");
    878   1.9   thorpej 		bcopy(&ifs, ifp, sizeof(*ifp));
    879   1.9   thorpej 		if (ifnet != 0) {
    880   1.9   thorpej 			ifp->int_next = ifnet;
    881   1.9   thorpej 			ifnet->int_prev = ifp;
    882   1.9   thorpej 		}
    883   1.9   thorpej 		ifnet = ifp;
    884   1.9   thorpej 		trace_if("Add", ifp);
    885   1.9   thorpej 
    886  1.10  christos 		/* Notice likely bad netmask.
    887  1.10  christos 		 */
    888  1.10  christos 		if (!(prev_complaints & COMP_NETMASK)
    889  1.10  christos 		    && !(ifp->int_if_flags & IFF_POINTOPOINT)) {
    890  1.10  christos 			for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    891  1.10  christos 				if (ifp1->int_mask == ifp->int_mask)
    892  1.10  christos 					continue;
    893  1.10  christos 				if (ifp1->int_if_flags & IFF_POINTOPOINT)
    894  1.10  christos 					continue;
    895  1.10  christos 				if (on_net(ifp->int_addr,
    896  1.10  christos 					   ifp1->int_net, ifp1->int_mask)
    897  1.10  christos 				    || on_net(ifp1->int_addr,
    898  1.10  christos 					      ifp->int_net, ifp->int_mask)) {
    899  1.10  christos 					msglog("possible netmask problem"
    900  1.10  christos 					       " betwen %s:%s and %s:%s",
    901  1.10  christos 					       ifp->int_name,
    902  1.10  christos 					       addrname(htonl(ifp->int_net),
    903  1.10  christos 							ifp->int_mask, 1),
    904  1.10  christos 					       ifp1->int_name,
    905  1.10  christos 					       addrname(htonl(ifp1->int_net),
    906  1.10  christos 							ifp1->int_mask, 1));
    907  1.10  christos 					complaints |= COMP_NETMASK;
    908  1.10  christos 				}
    909  1.10  christos 			}
    910  1.10  christos 		}
    911  1.10  christos 
    912   1.9   thorpej 		/* Count the # of directly connected networks.
    913   1.9   thorpej 		 */
    914   1.9   thorpej 		if (!(ifp->int_state & IS_ALIAS)) {
    915   1.9   thorpej 			if (!(ifp->int_if_flags & IFF_LOOPBACK))
    916   1.9   thorpej 				tot_interfaces++;
    917   1.9   thorpej 			if (!IS_RIP_OFF(ifp->int_state))
    918   1.9   thorpej 				rip_interfaces++;
    919   1.9   thorpej 		}
    920   1.9   thorpej 
    921   1.9   thorpej 		if_ok_rdisc(ifp);
    922   1.9   thorpej 		rip_on(ifp);
    923   1.9   thorpej 	}
    924   1.9   thorpej 
    925   1.9   thorpej 	/* If we are multi-homed and have at least one interface
    926   1.9   thorpej 	 * listening to RIP, then output by default.
    927   1.9   thorpej 	 */
    928   1.9   thorpej 	if (!supplier_set && rip_interfaces > 1)
    929   1.9   thorpej 		set_supplier();
    930   1.9   thorpej 
    931   1.9   thorpej 	/* If we are multi-homed, optionally advertise a route to
    932   1.9   thorpej 	 * our main address.
    933   1.9   thorpej 	 */
    934   1.9   thorpej 	if (advertise_mhome
    935   1.9   thorpej 	    || (tot_interfaces > 1
    936   1.9   thorpej 		&& mhome
    937   1.9   thorpej 		&& (ifp = ifwithaddr(myaddr, 0, 0)) != 0
    938   1.9   thorpej 		&& foundloopback)) {
    939   1.9   thorpej 		advertise_mhome = 1;
    940   1.9   thorpej 		rt = rtget(myaddr, HOST_MASK);
    941   1.9   thorpej 		if (rt != 0) {
    942   1.9   thorpej 			if (rt->rt_ifp != ifp
    943   1.9   thorpej 			    || rt->rt_router != loopaddr) {
    944   1.9   thorpej 				rtdelete(rt);
    945   1.9   thorpej 				rt = 0;
    946   1.9   thorpej 			} else {
    947   1.9   thorpej 				rtchange(rt, rt->rt_state | RS_MHOME,
    948   1.9   thorpej 					 loopaddr, loopaddr,
    949   1.9   thorpej 					 0, 0, ifp, rt->rt_time, 0);
    950   1.9   thorpej 			}
    951   1.9   thorpej 		}
    952   1.9   thorpej 		if (rt == 0)
    953   1.9   thorpej 			rtadd(myaddr, HOST_MASK, loopaddr, loopaddr,
    954   1.9   thorpej 			      0, 0, RS_MHOME, ifp);
    955   1.9   thorpej 	}
    956   1.9   thorpej 
    957   1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp1) {
    958   1.9   thorpej 		ifp1 = ifp->int_next;	/* because we may delete it */
    959   1.9   thorpej 
    960   1.9   thorpej 		/* Forget any interfaces that have disappeared.
    961   1.9   thorpej 		 */
    962   1.9   thorpej 		if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
    963   1.9   thorpej 			trace_act("interface %s has disappeared\n",
    964   1.9   thorpej 				  ifp->int_name);
    965   1.9   thorpej 			ifdel(ifp);
    966   1.9   thorpej 			continue;
    967   1.9   thorpej 		}
    968   1.9   thorpej 
    969   1.9   thorpej 		if ((ifp->int_state & IS_BROKE)
    970   1.9   thorpej 		    && !(ifp->int_state & IS_PASSIVE))
    971   1.9   thorpej 			LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
    972   1.9   thorpej 
    973   1.9   thorpej 		/* If we ever have a RIPv1 interface, assume we always will.
    974   1.9   thorpej 		 * It might come back if it ever goes away.
    975   1.9   thorpej 		 */
    976  1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier)
    977  1.10  christos 			have_ripv1_out = 1;
    978  1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_IN))
    979  1.10  christos 			have_ripv1_in = 1;
    980   1.9   thorpej 	}
    981   1.9   thorpej 
    982   1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
    983   1.9   thorpej 		/* Ensure there is always a network route for interfaces,
    984   1.9   thorpej 		 * after any dead interfaces have been deleted, which
    985   1.9   thorpej 		 * might affect routes for point-to-point links.
    986   1.9   thorpej 		 */
    987   1.9   thorpej 		addrouteforif(ifp);
    988   1.9   thorpej 
    989   1.9   thorpej 		/* Add routes to the local end of point-to-point interfaces
    990   1.9   thorpej 		 * using loopback.
    991   1.9   thorpej 		 */
    992   1.9   thorpej 		if ((ifp->int_if_flags & IFF_POINTOPOINT)
    993   1.9   thorpej 		    && !(ifp->int_state & IS_REMOTE)
    994   1.9   thorpej 		    && foundloopback) {
    995   1.9   thorpej 			/* Delete any routes to the network address through
    996   1.9   thorpej 			 * foreign routers. Remove even static routes.
    997   1.9   thorpej 			 */
    998   1.9   thorpej 			del_static(ifp->int_addr, HOST_MASK, 0);
    999   1.9   thorpej 			rt = rtget(ifp->int_addr, HOST_MASK);
   1000   1.9   thorpej 			if (rt != 0 && rt->rt_router != loopaddr) {
   1001   1.9   thorpej 				rtdelete(rt);
   1002   1.9   thorpej 				rt = 0;
   1003   1.9   thorpej 			}
   1004   1.9   thorpej 			if (rt != 0) {
   1005   1.9   thorpej 				if (!(rt->rt_state & RS_LOCAL)
   1006   1.9   thorpej 				    || rt->rt_metric > ifp->int_metric) {
   1007   1.9   thorpej 					ifp1 = ifp;
   1008   1.9   thorpej 				} else {
   1009   1.9   thorpej 					ifp1 = rt->rt_ifp;
   1010   1.9   thorpej 				}
   1011   1.9   thorpej 				rtchange(rt,((rt->rt_state & ~RS_NET_SYN)
   1012   1.9   thorpej 					     | (RS_IF|RS_LOCAL)),
   1013   1.9   thorpej 					 loopaddr, loopaddr,
   1014   1.9   thorpej 					 0, 0, ifp1, rt->rt_time, 0);
   1015   1.9   thorpej 			} else {
   1016   1.9   thorpej 				rtadd(ifp->int_addr, HOST_MASK,
   1017   1.9   thorpej 				      loopaddr, loopaddr,
   1018   1.9   thorpej 				      0, 0, (RS_IF | RS_LOCAL), ifp);
   1019   1.9   thorpej 			}
   1020   1.9   thorpej 		}
   1021   1.9   thorpej 	}
   1022   1.9   thorpej 
   1023   1.9   thorpej 	/* add the authority routes */
   1024   1.9   thorpej 	for (intnetp = intnets; intnetp!=0; intnetp = intnetp->intnet_next) {
   1025   1.9   thorpej 		rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask);
   1026   1.9   thorpej 		if (rt != 0
   1027   1.9   thorpej 		    && !(rt->rt_state & RS_NO_NET_SYN)
   1028   1.9   thorpej 		    && !(rt->rt_state & RS_NET_INT)) {
   1029   1.9   thorpej 			rtdelete(rt);
   1030   1.9   thorpej 			rt = 0;
   1031   1.9   thorpej 		}
   1032   1.9   thorpej 		if (rt == 0)
   1033   1.9   thorpej 			rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
   1034   1.9   thorpej 			      loopaddr, loopaddr, intnetp->intnet_metric-1,
   1035   1.9   thorpej 			      0, RS_NET_SYN | RS_NET_INT, 0);
   1036   1.9   thorpej 	}
   1037   1.9   thorpej 
   1038   1.9   thorpej 	prev_complaints = complaints;
   1039   1.9   thorpej }
   1040   1.9   thorpej 
   1041   1.9   thorpej 
   1042   1.9   thorpej static void
   1043   1.9   thorpej check_net_syn(struct interface *ifp)
   1044   1.9   thorpej {
   1045   1.9   thorpej 	struct rt_entry *rt;
   1046   1.9   thorpej 
   1047   1.9   thorpej 
   1048   1.9   thorpej 	/* Turn on the need to automatically synthesize a network route
   1049   1.9   thorpej 	 * for this interface only if we are running RIPv1 on some other
   1050   1.9   thorpej 	 * interface that is on a different class-A,B,or C network.
   1051   1.9   thorpej 	 */
   1052   1.9   thorpej 	if (have_ripv1_out || have_ripv1_in) {
   1053   1.9   thorpej 		ifp->int_state |= IS_NEED_NET_SYN;
   1054   1.9   thorpej 		rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
   1055   1.9   thorpej 		if (rt != 0
   1056   1.9   thorpej 		    && 0 == (rt->rt_state & RS_NO_NET_SYN)
   1057   1.9   thorpej 		    && (!(rt->rt_state & RS_NET_SYN)
   1058   1.9   thorpej 			|| rt->rt_metric > ifp->int_metric)) {
   1059   1.9   thorpej 			rtdelete(rt);
   1060   1.9   thorpej 			rt = 0;
   1061   1.9   thorpej 		}
   1062   1.9   thorpej 		if (rt == 0)
   1063   1.9   thorpej 			rtadd(ifp->int_std_addr, ifp->int_std_mask,
   1064   1.9   thorpej 			      ifp->int_addr, ifp->int_addr,
   1065   1.9   thorpej 			      ifp->int_metric, 0, RS_NET_SYN, ifp);
   1066   1.9   thorpej 
   1067   1.9   thorpej 	} else {
   1068   1.9   thorpej 		ifp->int_state &= ~IS_NEED_NET_SYN;
   1069   1.9   thorpej 
   1070   1.9   thorpej 		rt = rtget(ifp->int_std_addr,
   1071   1.9   thorpej 			   ifp->int_std_mask);
   1072   1.9   thorpej 		if (rt != 0
   1073   1.9   thorpej 		    && (rt->rt_state & RS_NET_SYN)
   1074   1.9   thorpej 		    && rt->rt_ifp == ifp)
   1075   1.9   thorpej 			rtbad_sub(rt);
   1076   1.9   thorpej 	}
   1077   1.9   thorpej }
   1078   1.9   thorpej 
   1079   1.9   thorpej 
   1080   1.9   thorpej /* Add route for interface if not currently installed.
   1081   1.9   thorpej  * Create route to other end if a point-to-point link,
   1082   1.9   thorpej  * otherwise a route to this (sub)network.
   1083   1.9   thorpej  */
   1084   1.9   thorpej void
   1085   1.9   thorpej addrouteforif(struct interface *ifp)
   1086   1.9   thorpej {
   1087   1.9   thorpej 	struct rt_entry *rt;
   1088   1.9   thorpej 	naddr dst, gate;
   1089   1.9   thorpej 
   1090   1.9   thorpej 
   1091   1.9   thorpej 	/* skip sick interfaces
   1092   1.9   thorpej 	 */
   1093   1.9   thorpej 	if (ifp->int_state & IS_BROKE)
   1094   1.9   thorpej 		return;
   1095   1.9   thorpej 
   1096   1.9   thorpej 	/* If the interface on a subnet, then install a RIPv1 route to
   1097   1.9   thorpej 	 * the network as well (unless it is sick).
   1098   1.9   thorpej 	 */
   1099   1.9   thorpej 	if (ifp->int_state & IS_SUBNET)
   1100   1.9   thorpej 		check_net_syn(ifp);
   1101   1.9   thorpej 
   1102   1.9   thorpej 	if (ifp->int_state & IS_REMOTE) {
   1103   1.9   thorpej 		dst = ifp->int_addr;
   1104   1.9   thorpej 		gate = ifp->int_dstaddr;
   1105   1.9   thorpej 		/* If we are going to send packets to the gateway,
   1106   1.9   thorpej 		 * it must be reachable using our physical interfaces
   1107   1.9   thorpej 		 */
   1108   1.9   thorpej 		if (!(ifp->int_state && IS_EXTERNAL)
   1109   1.9   thorpej 		    && !rtfind(ifp->int_dstaddr)
   1110   1.9   thorpej 		    && ifp->int_transitions == 0) {
   1111   1.9   thorpej 			msglog("unreachable gateway %s in "
   1112   1.9   thorpej 			       _PATH_GATEWAYS" entry %s",
   1113   1.9   thorpej 			       naddr_ntoa(gate), ifp->int_name);
   1114   1.9   thorpej 			return;
   1115   1.9   thorpej 		}
   1116   1.9   thorpej 
   1117   1.9   thorpej 	} else {
   1118   1.9   thorpej 		dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT
   1119   1.9   thorpej 						  | IFF_LOOPBACK))
   1120   1.9   thorpej 		       ? ifp->int_dstaddr
   1121   1.9   thorpej 		       : htonl(ifp->int_net));
   1122   1.9   thorpej 		gate = ifp->int_addr;
   1123   1.9   thorpej 	}
   1124   1.9   thorpej 
   1125   1.9   thorpej 	/* We are finished if the correct main interface route exists.
   1126   1.9   thorpej 	 * The right route must be for the right interface, not synthesized
   1127   1.9   thorpej 	 * from a subnet, be a "gateway" or not as appropriate, and so forth.
   1128   1.9   thorpej 	 */
   1129   1.9   thorpej 	del_static(dst, ifp->int_mask, 0);
   1130   1.9   thorpej 	rt = rtget(dst, ifp->int_mask);
   1131   1.9   thorpej 	if (rt != 0) {
   1132   1.9   thorpej 		if ((rt->rt_ifp != ifp
   1133   1.9   thorpej 		     || rt->rt_router != ifp->int_addr)
   1134   1.9   thorpej 		    && (!(ifp->int_state & IS_DUP)
   1135   1.9   thorpej 			|| rt->rt_ifp == 0
   1136   1.9   thorpej 			|| (rt->rt_ifp->int_state & IS_BROKE))) {
   1137   1.9   thorpej 			rtdelete(rt);
   1138   1.9   thorpej 			rt = 0;
   1139   1.9   thorpej 		} else {
   1140   1.9   thorpej 			rtchange(rt, ((rt->rt_state | RS_IF)
   1141   1.9   thorpej 				      & ~(RS_NET_SYN | RS_LOCAL)),
   1142   1.9   thorpej 				 ifp->int_addr, ifp->int_addr,
   1143   1.9   thorpej 				 ifp->int_metric, 0, ifp, now.tv_sec, 0);
   1144   1.9   thorpej 		}
   1145   1.9   thorpej 	}
   1146   1.9   thorpej 	if (rt == 0) {
   1147   1.9   thorpej 		if (ifp->int_transitions++ > 0)
   1148   1.9   thorpej 			trace_act("re-install interface %s\n",
   1149   1.9   thorpej 				  ifp->int_name);
   1150   1.9   thorpej 
   1151   1.9   thorpej 		rtadd(dst, ifp->int_mask, gate, gate,
   1152   1.9   thorpej 		      ifp->int_metric, 0, RS_IF, ifp);
   1153   1.1       cgd 	}
   1154   1.1       cgd }
   1155