Home | History | Annotate | Line # | Download | only in routed
if.c revision 1.26.10.1
      1  1.26.10.1       mjf /*	$NetBSD: if.c,v 1.26.10.1 2009/01/17 13:48:53 mjf 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.16  christos  *    must display the following acknowledgment:
     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.1       cgd #include "defs.h"
     37        1.9   thorpej #include "pathnames.h"
     38        1.9   thorpej 
     39       1.22  christos #ifdef __NetBSD__
     40  1.26.10.1       mjf __RCSID("$NetBSD: if.c,v 1.26.10.1 2009/01/17 13:48:53 mjf Exp $");
     41       1.22  christos #elif defined(__FreeBSD__)
     42       1.22  christos __RCSID("$FreeBSD$");
     43       1.22  christos #else
     44       1.24  christos __RCSID("Revision: 2.27 ");
     45       1.24  christos #ident "Revision: 2.27 "
     46       1.22  christos #endif
     47       1.22  christos 
     48       1.11  christos struct interface *ifnet;		/* all interfaces */
     49       1.11  christos 
     50       1.11  christos /* hash table for all interfaces, big enough to tolerate ridiculous
     51       1.11  christos  * numbers of IP aliases.  Crazy numbers of aliases such as 7000
     52       1.11  christos  * still will not do well, but not just in looking up interfaces
     53       1.11  christos  * by name or address.
     54       1.11  christos  */
     55       1.11  christos #define AHASH_LEN 211			/* must be prime */
     56       1.11  christos #define AHASH(a) &ahash_tbl[(a)%AHASH_LEN]
     57       1.11  christos struct interface *ahash_tbl[AHASH_LEN];
     58       1.11  christos 
     59       1.11  christos #define BHASH_LEN 211			/* must be prime */
     60       1.11  christos #define BHASH(a) &bhash_tbl[(a)%BHASH_LEN]
     61       1.11  christos struct interface *bhash_tbl[BHASH_LEN];
     62       1.11  christos 
     63       1.11  christos struct interface *remote_if;		/* remote interfaces */
     64       1.11  christos 
     65       1.11  christos /* hash for physical interface names.
     66       1.11  christos  * Assume there are never more 100 or 200 real interfaces, and that
     67       1.11  christos  * aliases are put on the end of the hash chains.
     68       1.11  christos  */
     69       1.11  christos #define NHASH_LEN 97
     70       1.11  christos struct interface *nhash_tbl[NHASH_LEN];
     71       1.11  christos 
     72        1.9   thorpej int	tot_interfaces;			/* # of remote and local interfaces */
     73        1.9   thorpej int	rip_interfaces;			/* # of interfaces doing RIP */
     74        1.9   thorpej int	foundloopback;			/* valid flag for loopaddr */
     75        1.9   thorpej naddr	loopaddr;			/* our address on loopback */
     76       1.14   thorpej struct	rt_spare loop_rts;
     77        1.9   thorpej 
     78        1.9   thorpej struct timeval ifinit_timer;
     79       1.11  christos static struct timeval last_ifinit;
     80       1.14   thorpej #define IF_RESCAN_DELAY() (last_ifinit.tv_sec == now.tv_sec		\
     81       1.14   thorpej 			   && last_ifinit.tv_usec == now.tv_usec	\
     82       1.14   thorpej 			   && timercmp(&ifinit_timer, &now, >))
     83        1.1       cgd 
     84        1.9   thorpej int	have_ripv1_out;			/* have a RIPv1 interface */
     85        1.9   thorpej int	have_ripv1_in;
     86        1.1       cgd 
     87        1.9   thorpej 
     88       1.11  christos static struct interface**
     89       1.12     lukem nhash(char *p)
     90       1.11  christos {
     91       1.12     lukem 	u_int i;
     92       1.11  christos 
     93       1.11  christos 	for (i = 0; *p != '\0'; p++) {
     94       1.11  christos 		i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1);
     95       1.11  christos 		i ^= *p;
     96       1.11  christos 	}
     97       1.11  christos 	return &nhash_tbl[i % NHASH_LEN];
     98       1.11  christos }
     99       1.11  christos 
    100       1.11  christos 
    101       1.11  christos /* Link a new interface into the lists and hash tables.
    102       1.11  christos  */
    103       1.11  christos void
    104       1.11  christos if_link(struct interface *ifp)
    105       1.11  christos {
    106       1.11  christos 	struct interface **hifp;
    107       1.11  christos 
    108       1.11  christos 	ifp->int_prev = &ifnet;
    109       1.11  christos 	ifp->int_next = ifnet;
    110       1.11  christos 	if (ifnet != 0)
    111       1.11  christos 		ifnet->int_prev = &ifp->int_next;
    112       1.11  christos 	ifnet = ifp;
    113       1.11  christos 
    114       1.11  christos 	hifp = AHASH(ifp->int_addr);
    115       1.11  christos 	ifp->int_ahash_prev = hifp;
    116       1.11  christos 	if ((ifp->int_ahash = *hifp) != 0)
    117       1.11  christos 		(*hifp)->int_ahash_prev = &ifp->int_ahash;
    118       1.11  christos 	*hifp = ifp;
    119       1.11  christos 
    120       1.11  christos 	if (ifp->int_if_flags & IFF_BROADCAST) {
    121       1.11  christos 		hifp = BHASH(ifp->int_brdaddr);
    122       1.11  christos 		ifp->int_bhash_prev = hifp;
    123       1.11  christos 		if ((ifp->int_bhash = *hifp) != 0)
    124       1.11  christos 			(*hifp)->int_bhash_prev = &ifp->int_bhash;
    125       1.11  christos 		*hifp = ifp;
    126       1.11  christos 	}
    127       1.11  christos 
    128       1.11  christos 	if (ifp->int_state & IS_REMOTE) {
    129       1.11  christos 		ifp->int_rlink_prev = &remote_if;
    130       1.11  christos 		ifp->int_rlink = remote_if;
    131       1.11  christos 		if (remote_if != 0)
    132       1.11  christos 			remote_if->int_rlink_prev = &ifp->int_rlink;
    133       1.11  christos 		remote_if = ifp;
    134       1.11  christos 	}
    135       1.11  christos 
    136       1.11  christos 	hifp = nhash(ifp->int_name);
    137       1.11  christos 	if (ifp->int_state & IS_ALIAS) {
    138       1.11  christos 		/* put aliases on the end of the hash chain */
    139       1.11  christos 		while (*hifp != 0)
    140       1.11  christos 			hifp = &(*hifp)->int_nhash;
    141       1.11  christos 	}
    142       1.11  christos 	ifp->int_nhash_prev = hifp;
    143       1.11  christos 	if ((ifp->int_nhash = *hifp) != 0)
    144       1.11  christos 		(*hifp)->int_nhash_prev = &ifp->int_nhash;
    145       1.11  christos 	*hifp = ifp;
    146       1.11  christos }
    147       1.11  christos 
    148       1.11  christos 
    149        1.9   thorpej /* Find the interface with an address
    150        1.1       cgd  */
    151        1.1       cgd struct interface *
    152        1.9   thorpej ifwithaddr(naddr addr,
    153        1.9   thorpej 	   int	bcast,			/* notice IFF_BROADCAST address */
    154        1.9   thorpej 	   int	remote)			/* include IS_REMOTE interfaces */
    155        1.1       cgd {
    156        1.9   thorpej 	struct interface *ifp, *possible = 0;
    157        1.1       cgd 
    158       1.11  christos 	remote = (remote == 0) ? IS_REMOTE : 0;
    159       1.11  christos 
    160       1.11  christos 	for (ifp = *AHASH(addr); ifp; ifp = ifp->int_ahash) {
    161       1.11  christos 		if (ifp->int_addr != addr)
    162       1.11  christos 			continue;
    163       1.11  christos 		if ((ifp->int_state & remote) != 0)
    164       1.11  christos 			continue;
    165       1.11  christos 		if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0)
    166       1.11  christos 			return ifp;
    167       1.11  christos 		possible = ifp;
    168       1.11  christos 	}
    169        1.9   thorpej 
    170       1.11  christos 	if (possible || !bcast)
    171       1.11  christos 		return possible;
    172        1.9   thorpej 
    173       1.11  christos 	for (ifp = *BHASH(addr); ifp; ifp = ifp->int_bhash) {
    174       1.11  christos 		if (ifp->int_brdaddr != addr)
    175       1.11  christos 			continue;
    176       1.11  christos 		if ((ifp->int_state & remote) != 0)
    177       1.11  christos 			continue;
    178       1.11  christos 		if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0)
    179       1.11  christos 			return ifp;
    180       1.11  christos 		possible = ifp;
    181        1.1       cgd 	}
    182        1.9   thorpej 
    183        1.9   thorpej 	return possible;
    184        1.1       cgd }
    185        1.1       cgd 
    186        1.9   thorpej 
    187        1.9   thorpej /* find the interface with a name
    188        1.1       cgd  */
    189        1.1       cgd struct interface *
    190        1.9   thorpej ifwithname(char *name,			/* "ec0" or whatever */
    191        1.9   thorpej 	   naddr addr)			/* 0 or network address */
    192        1.1       cgd {
    193        1.9   thorpej 	struct interface *ifp;
    194        1.9   thorpej 
    195       1.11  christos 	for (;;) {
    196       1.11  christos 		for (ifp = *nhash(name); ifp != 0; ifp = ifp->int_nhash) {
    197       1.11  christos 			/* If the network address is not specified,
    198       1.11  christos 			 * ignore any alias interfaces.  Otherwise, look
    199       1.11  christos 			 * for the interface with the target name and address.
    200       1.11  christos 			 */
    201       1.11  christos 			if (!strcmp(ifp->int_name, name)
    202       1.11  christos 			    && ((addr == 0 && !(ifp->int_state & IS_ALIAS))
    203       1.11  christos 				|| (ifp->int_addr == addr)))
    204       1.11  christos 				return ifp;
    205       1.11  christos 		}
    206        1.1       cgd 
    207       1.11  christos 		/* If there is no known interface, maybe there is a
    208       1.11  christos 		 * new interface.  So just once look for new interfaces.
    209       1.11  christos 		 */
    210       1.14   thorpej 		if (IF_RESCAN_DELAY())
    211       1.11  christos 			return 0;
    212       1.11  christos 		ifinit();
    213        1.1       cgd 	}
    214        1.1       cgd }
    215        1.1       cgd 
    216        1.9   thorpej 
    217        1.1       cgd struct interface *
    218       1.23     lukem ifwithindex(u_short ifindex,
    219       1.11  christos 	    int rescan_ok)
    220        1.1       cgd {
    221        1.9   thorpej 	struct interface *ifp;
    222        1.9   thorpej 
    223       1.11  christos 	for (;;) {
    224       1.11  christos 		for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
    225       1.23     lukem 			if (ifp->int_index == ifindex)
    226       1.11  christos 				return ifp;
    227       1.11  christos 		}
    228        1.9   thorpej 
    229       1.11  christos 		/* If there is no known interface, maybe there is a
    230       1.11  christos 		 * new interface.  So just once look for new interfaces.
    231       1.11  christos 		 */
    232       1.11  christos 		if (!rescan_ok
    233       1.14   thorpej 		    || IF_RESCAN_DELAY())
    234       1.11  christos 			return 0;
    235       1.11  christos 		ifinit();
    236        1.1       cgd 	}
    237        1.1       cgd }
    238        1.1       cgd 
    239        1.9   thorpej 
    240        1.9   thorpej /* Find an interface from which the specified address
    241        1.1       cgd  * should have come from.  Used for figuring out which
    242       1.11  christos  * interface a packet came in on.
    243        1.1       cgd  */
    244        1.1       cgd struct interface *
    245        1.9   thorpej iflookup(naddr addr)
    246        1.1       cgd {
    247        1.9   thorpej 	struct interface *ifp, *maybe;
    248       1.20  christos 	int once = 0;
    249        1.1       cgd 
    250        1.1       cgd 	maybe = 0;
    251       1.11  christos 	for (;;) {
    252       1.11  christos 		for (ifp = ifnet; ifp; ifp = ifp->int_next) {
    253       1.11  christos 			if (ifp->int_if_flags & IFF_POINTOPOINT) {
    254        1.9   thorpej 				/* finished with a match */
    255       1.11  christos 				if (ifp->int_dstaddr == addr)
    256       1.11  christos 					return ifp;
    257        1.9   thorpej 
    258       1.11  christos 			} else {
    259       1.11  christos 				/* finished with an exact match */
    260       1.11  christos 				if (ifp->int_addr == addr)
    261       1.11  christos 					return ifp;
    262        1.9   thorpej 
    263       1.11  christos 				/* Look for the longest approximate match.
    264       1.11  christos 				 */
    265       1.11  christos 				if (on_net(addr, ifp->int_net, ifp->int_mask)
    266       1.11  christos 				    && (maybe == 0
    267       1.11  christos 					|| ifp->int_mask > maybe->int_mask))
    268       1.11  christos 					maybe = ifp;
    269       1.11  christos 			}
    270        1.9   thorpej 		}
    271       1.11  christos 
    272       1.22  christos 		if (maybe != 0 || once || IF_RESCAN_DELAY())
    273       1.11  christos 			return maybe;
    274       1.22  christos 		once = 1;
    275       1.11  christos 
    276       1.11  christos 		/* If there is no known interface, maybe there is a
    277       1.11  christos 		 * new interface.  So just once look for new interfaces.
    278       1.11  christos 		 */
    279       1.11  christos 		ifinit();
    280        1.9   thorpej 	}
    281        1.9   thorpej }
    282        1.9   thorpej 
    283        1.9   thorpej 
    284        1.9   thorpej /* Return the classical netmask for an IP address.
    285        1.9   thorpej  */
    286       1.11  christos naddr					/* host byte order */
    287       1.11  christos std_mask(naddr addr)			/* network byte order */
    288        1.9   thorpej {
    289        1.9   thorpej 	NTOHL(addr);			/* was a host, not a network */
    290        1.9   thorpej 
    291        1.9   thorpej 	if (addr == 0)			/* default route has mask 0 */
    292        1.9   thorpej 		return 0;
    293        1.9   thorpej 	if (IN_CLASSA(addr))
    294        1.9   thorpej 		return IN_CLASSA_NET;
    295        1.9   thorpej 	if (IN_CLASSB(addr))
    296        1.9   thorpej 		return IN_CLASSB_NET;
    297        1.9   thorpej 	return IN_CLASSC_NET;
    298        1.9   thorpej }
    299        1.9   thorpej 
    300        1.9   thorpej 
    301       1.10  christos /* Find the netmask that would be inferred by RIPv1 listeners
    302        1.9   thorpej  *	on the given interface for a given network.
    303        1.9   thorpej  *	If no interface is specified, look for the best fitting	interface.
    304        1.9   thorpej  */
    305        1.9   thorpej naddr
    306        1.9   thorpej ripv1_mask_net(naddr addr,		/* in network byte order */
    307        1.9   thorpej 	       struct interface *ifp)	/* as seen on this interface */
    308        1.9   thorpej {
    309       1.14   thorpej 	struct r1net *r1p;
    310        1.9   thorpej 	naddr mask = 0;
    311        1.9   thorpej 
    312        1.9   thorpej 	if (addr == 0)			/* default always has 0 mask */
    313        1.9   thorpej 		return mask;
    314        1.9   thorpej 
    315       1.14   thorpej 	if (ifp != 0 && ifp->int_ripv1_mask != HOST_MASK) {
    316        1.9   thorpej 		/* If the target network is that of the associated interface
    317        1.9   thorpej 		 * on which it arrived, then use the netmask of the interface.
    318        1.9   thorpej 		 */
    319        1.9   thorpej 		if (on_net(addr, ifp->int_net, ifp->int_std_mask))
    320        1.9   thorpej 			mask = ifp->int_ripv1_mask;
    321        1.9   thorpej 
    322        1.9   thorpej 	} else {
    323        1.9   thorpej 		/* Examine all interfaces, and if it the target seems
    324        1.9   thorpej 		 * to have the same network number of an interface, use the
    325        1.9   thorpej 		 * netmask of that interface.  If there is more than one
    326        1.9   thorpej 		 * such interface, prefer the interface with the longest
    327        1.9   thorpej 		 * match.
    328        1.9   thorpej 		 */
    329        1.9   thorpej 		for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
    330        1.9   thorpej 			if (on_net(addr, ifp->int_std_net, ifp->int_std_mask)
    331       1.14   thorpej 			    && ifp->int_ripv1_mask > mask
    332       1.14   thorpej 			    && ifp->int_ripv1_mask != HOST_MASK)
    333        1.9   thorpej 				mask = ifp->int_ripv1_mask;
    334        1.9   thorpej 		}
    335       1.14   thorpej 
    336        1.9   thorpej 	}
    337        1.9   thorpej 
    338       1.14   thorpej 	/* check special definitions */
    339       1.14   thorpej 	if (mask == 0) {
    340       1.14   thorpej 		for (r1p = r1nets; r1p != 0; r1p = r1p->r1net_next) {
    341       1.14   thorpej 			if (on_net(addr, r1p->r1net_net, r1p->r1net_match)
    342       1.14   thorpej 			    && r1p->r1net_mask > mask)
    343       1.16  christos 				mask = r1p->r1net_mask;
    344       1.14   thorpej 		}
    345       1.14   thorpej 
    346       1.14   thorpej 		/* Otherwise, make the classic A/B/C guess.
    347       1.14   thorpej 		 */
    348       1.14   thorpej 		if (mask == 0)
    349       1.14   thorpej 			mask = std_mask(addr);
    350       1.14   thorpej 	}
    351        1.9   thorpej 
    352        1.9   thorpej 	return mask;
    353        1.9   thorpej }
    354        1.9   thorpej 
    355        1.9   thorpej 
    356        1.9   thorpej naddr
    357        1.9   thorpej ripv1_mask_host(naddr addr,		/* in network byte order */
    358        1.9   thorpej 		struct interface *ifp)	/* as seen on this interface */
    359        1.9   thorpej {
    360        1.9   thorpej 	naddr mask = ripv1_mask_net(addr, ifp);
    361        1.9   thorpej 
    362        1.9   thorpej 
    363        1.9   thorpej 	/* If the computed netmask does not mask the address,
    364        1.9   thorpej 	 * then assume it is a host address
    365        1.9   thorpej 	 */
    366        1.9   thorpej 	if ((ntohl(addr) & ~mask) != 0)
    367        1.9   thorpej 		mask = HOST_MASK;
    368        1.9   thorpej 	return mask;
    369        1.9   thorpej }
    370        1.9   thorpej 
    371        1.9   thorpej 
    372        1.9   thorpej /* See if a IP address looks reasonable as a destination
    373        1.9   thorpej  */
    374        1.9   thorpej int					/* 0=bad */
    375        1.9   thorpej check_dst(naddr addr)
    376        1.9   thorpej {
    377        1.9   thorpej 	NTOHL(addr);
    378        1.9   thorpej 
    379        1.9   thorpej 	if (IN_CLASSA(addr)) {
    380        1.9   thorpej 		if (addr == 0)
    381        1.9   thorpej 			return 1;	/* default */
    382        1.9   thorpej 
    383        1.9   thorpej 		addr >>= IN_CLASSA_NSHIFT;
    384        1.9   thorpej 		return (addr != 0 && addr != IN_LOOPBACKNET);
    385        1.9   thorpej 	}
    386        1.9   thorpej 
    387        1.9   thorpej 	return (IN_CLASSB(addr) || IN_CLASSC(addr));
    388        1.9   thorpej }
    389        1.9   thorpej 
    390        1.9   thorpej 
    391       1.11  christos /* See a new interface duplicates an existing interface.
    392       1.11  christos  */
    393       1.11  christos struct interface *
    394       1.11  christos check_dup(naddr addr,			/* IP address, so network byte order */
    395       1.11  christos 	  naddr dstaddr,		/* ditto */
    396       1.11  christos 	  naddr mask,			/* mask, so host byte order */
    397       1.11  christos 	  int if_flags)
    398       1.11  christos {
    399       1.11  christos 	struct interface *ifp;
    400       1.11  christos 
    401       1.11  christos 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
    402       1.11  christos 		if (ifp->int_mask != mask)
    403       1.11  christos 			continue;
    404       1.11  christos 
    405       1.14   thorpej 		if (!iff_up(ifp->int_if_flags))
    406       1.11  christos 			continue;
    407       1.11  christos 
    408       1.11  christos 		/* The local address can only be shared with a point-to-point
    409       1.11  christos 		 * link.
    410       1.11  christos 		 */
    411       1.22  christos 		if ((!(ifp->int_state & IS_REMOTE) || !(if_flags & IS_REMOTE))
    412       1.22  christos 		    && ifp->int_addr == addr
    413       1.11  christos 		    && (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0))
    414       1.11  christos 			return ifp;
    415       1.11  christos 
    416       1.11  christos 		if (on_net(ifp->int_dstaddr, ntohl(dstaddr),mask))
    417       1.11  christos 			return ifp;
    418       1.11  christos 	}
    419       1.11  christos 	return 0;
    420       1.11  christos }
    421       1.11  christos 
    422       1.11  christos 
    423       1.11  christos /* See that a remote gateway is reachable.
    424       1.11  christos  *	Note that the answer can change as real interfaces come and go.
    425       1.11  christos  */
    426       1.11  christos int					/* 0=bad */
    427       1.11  christos check_remote(struct interface *ifp)
    428       1.11  christos {
    429       1.11  christos 	struct rt_entry *rt;
    430       1.11  christos 
    431       1.11  christos 	/* do not worry about other kinds */
    432       1.11  christos 	if (!(ifp->int_state & IS_REMOTE))
    433       1.11  christos 	    return 1;
    434       1.11  christos 
    435       1.11  christos 	rt = rtfind(ifp->int_addr);
    436       1.11  christos 	if (rt != 0
    437       1.11  christos 	    && rt->rt_ifp != 0
    438       1.11  christos 	    &&on_net(ifp->int_addr,
    439       1.11  christos 		     rt->rt_ifp->int_net, rt->rt_ifp->int_mask))
    440       1.11  christos 		return 1;
    441       1.11  christos 
    442       1.11  christos 	/* the gateway cannot be reached directly from one of our
    443       1.11  christos 	 * interfaces
    444       1.11  christos 	 */
    445       1.11  christos 	if (!(ifp->int_state & IS_BROKE)) {
    446       1.11  christos 		msglog("unreachable gateway %s in "_PATH_GATEWAYS,
    447       1.11  christos 		       naddr_ntoa(ifp->int_addr));
    448       1.11  christos 		if_bad(ifp);
    449       1.11  christos 	}
    450       1.11  christos 	return 0;
    451       1.11  christos }
    452       1.11  christos 
    453       1.11  christos 
    454        1.9   thorpej /* Delete an interface.
    455        1.9   thorpej  */
    456        1.9   thorpej static void
    457        1.9   thorpej ifdel(struct interface *ifp)
    458        1.9   thorpej {
    459        1.9   thorpej 	struct ip_mreq m;
    460        1.9   thorpej 	struct interface *ifp1;
    461        1.9   thorpej 
    462        1.9   thorpej 
    463        1.9   thorpej 	trace_if("Del", ifp);
    464        1.9   thorpej 
    465        1.9   thorpej 	ifp->int_state |= IS_BROKE;
    466        1.9   thorpej 
    467        1.9   thorpej 	/* unlink the interface
    468        1.9   thorpej 	 */
    469       1.11  christos 	*ifp->int_prev = ifp->int_next;
    470        1.9   thorpej 	if (ifp->int_next != 0)
    471        1.9   thorpej 		ifp->int_next->int_prev = ifp->int_prev;
    472       1.11  christos 	*ifp->int_ahash_prev = ifp->int_ahash;
    473       1.11  christos 	if (ifp->int_ahash != 0)
    474       1.11  christos 		ifp->int_ahash->int_ahash_prev = ifp->int_ahash_prev;
    475       1.11  christos 	*ifp->int_nhash_prev = ifp->int_nhash;
    476       1.11  christos 	if (ifp->int_nhash != 0)
    477       1.11  christos 		ifp->int_nhash->int_nhash_prev = ifp->int_nhash_prev;
    478       1.11  christos 	if (ifp->int_if_flags & IFF_BROADCAST) {
    479       1.11  christos 		*ifp->int_bhash_prev = ifp->int_bhash;
    480       1.11  christos 		if (ifp->int_bhash != 0)
    481       1.11  christos 			ifp->int_bhash->int_bhash_prev = ifp->int_bhash_prev;
    482       1.11  christos 	}
    483       1.11  christos 	if (ifp->int_state & IS_REMOTE) {
    484       1.11  christos 		*ifp->int_rlink_prev = ifp->int_rlink;
    485       1.11  christos 		if (ifp->int_rlink != 0)
    486       1.11  christos 			ifp->int_rlink->int_rlink_prev = ifp->int_rlink_prev;
    487       1.11  christos 	}
    488        1.9   thorpej 
    489        1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    490       1.11  christos 		/* delete aliases when the main interface dies
    491        1.9   thorpej 		 */
    492        1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    493        1.9   thorpej 			if (ifp1 != ifp
    494        1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    495        1.9   thorpej 				ifdel(ifp1);
    496        1.9   thorpej 		}
    497        1.9   thorpej 
    498        1.9   thorpej 		if ((ifp->int_if_flags & IFF_MULTICAST)
    499        1.9   thorpej #ifdef MCAST_PPP_BUG
    500        1.9   thorpej 		    && !(ifp->int_if_flags & IFF_POINTOPOINT)
    501        1.9   thorpej #endif
    502        1.9   thorpej 		    && rip_sock >= 0) {
    503        1.9   thorpej 			m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
    504       1.21    itojun #ifdef MCAST_IFINDEX
    505       1.21    itojun 			m.imr_interface.s_addr = htonl(ifp->int_index);
    506       1.21    itojun #else
    507        1.9   thorpej 			m.imr_interface.s_addr = ((ifp->int_if_flags
    508        1.9   thorpej 						   & IFF_POINTOPOINT)
    509        1.9   thorpej 						  ? ifp->int_dstaddr
    510        1.9   thorpej 						  : ifp->int_addr);
    511       1.21    itojun #endif
    512        1.9   thorpej 			if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,
    513        1.9   thorpej 				       &m, sizeof(m)) < 0
    514        1.9   thorpej 			    && errno != EADDRNOTAVAIL
    515        1.9   thorpej 			    && !TRACEACTIONS)
    516        1.9   thorpej 				LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)");
    517       1.11  christos 			if (rip_sock_mcast == ifp)
    518       1.11  christos 				rip_sock_mcast = 0;
    519        1.9   thorpej 		}
    520        1.9   thorpej 		if (ifp->int_rip_sock >= 0) {
    521        1.9   thorpej 			(void)close(ifp->int_rip_sock);
    522        1.9   thorpej 			ifp->int_rip_sock = -1;
    523        1.9   thorpej 			fix_select();
    524        1.9   thorpej 		}
    525        1.9   thorpej 
    526        1.9   thorpej 		tot_interfaces--;
    527        1.9   thorpej 		if (!IS_RIP_OFF(ifp->int_state))
    528        1.9   thorpej 			rip_interfaces--;
    529        1.9   thorpej 
    530        1.9   thorpej 		/* Zap all routes associated with this interface.
    531       1.14   thorpej 		 * Assume routes just using gateways beyond this interface
    532       1.14   thorpej 		 * will timeout naturally, and have probably already died.
    533        1.9   thorpej 		 */
    534        1.9   thorpej 		(void)rn_walktree(rhead, walk_bad, 0);
    535        1.9   thorpej 
    536        1.9   thorpej 		set_rdisc_mg(ifp, 0);
    537        1.9   thorpej 		if_bad_rdisc(ifp);
    538        1.9   thorpej 	}
    539        1.9   thorpej 
    540        1.9   thorpej 	free(ifp);
    541        1.9   thorpej }
    542        1.9   thorpej 
    543        1.9   thorpej 
    544        1.9   thorpej /* Mark an interface ill.
    545        1.9   thorpej  */
    546        1.9   thorpej void
    547        1.9   thorpej if_sick(struct interface *ifp)
    548        1.9   thorpej {
    549        1.9   thorpej 	if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) {
    550        1.9   thorpej 		ifp->int_state |= IS_SICK;
    551       1.11  christos 		ifp->int_act_time = NEVER;
    552        1.9   thorpej 		trace_if("Chg", ifp);
    553        1.9   thorpej 
    554        1.9   thorpej 		LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
    555        1.9   thorpej 	}
    556        1.9   thorpej }
    557        1.9   thorpej 
    558        1.9   thorpej 
    559        1.9   thorpej /* Mark an interface dead.
    560        1.9   thorpej  */
    561        1.9   thorpej void
    562        1.9   thorpej if_bad(struct interface *ifp)
    563        1.9   thorpej {
    564        1.9   thorpej 	struct interface *ifp1;
    565        1.9   thorpej 
    566        1.9   thorpej 
    567        1.9   thorpej 	if (ifp->int_state & IS_BROKE)
    568        1.9   thorpej 		return;
    569        1.9   thorpej 
    570        1.9   thorpej 	LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
    571        1.9   thorpej 
    572        1.9   thorpej 	ifp->int_state |= (IS_BROKE | IS_SICK);
    573       1.11  christos 	ifp->int_act_time = NEVER;
    574       1.11  christos 	ifp->int_query_time = NEVER;
    575       1.14   thorpej 	ifp->int_data.ts = now.tv_sec;
    576        1.9   thorpej 
    577        1.9   thorpej 	trace_if("Chg", ifp);
    578        1.9   thorpej 
    579        1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    580        1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    581        1.9   thorpej 			if (ifp1 != ifp
    582        1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    583        1.9   thorpej 				if_bad(ifp1);
    584        1.9   thorpej 		}
    585        1.9   thorpej 		(void)rn_walktree(rhead, walk_bad, 0);
    586        1.9   thorpej 		if_bad_rdisc(ifp);
    587        1.9   thorpej 	}
    588        1.9   thorpej }
    589        1.9   thorpej 
    590        1.9   thorpej 
    591        1.9   thorpej /* Mark an interface alive
    592        1.9   thorpej  */
    593        1.9   thorpej int					/* 1=it was dead */
    594        1.9   thorpej if_ok(struct interface *ifp,
    595       1.17  christos       const char *type)
    596        1.9   thorpej {
    597        1.9   thorpej 	struct interface *ifp1;
    598        1.9   thorpej 
    599        1.9   thorpej 
    600        1.9   thorpej 	if (!(ifp->int_state & IS_BROKE)) {
    601        1.9   thorpej 		if (ifp->int_state & IS_SICK) {
    602       1.11  christos 			trace_act("%sinterface %s to %s working better",
    603        1.9   thorpej 				  type,
    604       1.11  christos 				  ifp->int_name, naddr_ntoa(ifp->int_dstaddr));
    605        1.9   thorpej 			ifp->int_state &= ~IS_SICK;
    606        1.9   thorpej 		}
    607        1.9   thorpej 		return 0;
    608        1.9   thorpej 	}
    609        1.9   thorpej 
    610        1.9   thorpej 	msglog("%sinterface %s to %s restored",
    611       1.11  christos 	       type, ifp->int_name, naddr_ntoa(ifp->int_dstaddr));
    612        1.9   thorpej 	ifp->int_state &= ~(IS_BROKE | IS_SICK);
    613        1.9   thorpej 	ifp->int_data.ts = 0;
    614        1.9   thorpej 
    615        1.9   thorpej 	if (!(ifp->int_state & IS_ALIAS)) {
    616        1.9   thorpej 		for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
    617        1.9   thorpej 			if (ifp1 != ifp
    618        1.9   thorpej 			    && !strcmp(ifp->int_name, ifp1->int_name))
    619        1.9   thorpej 				if_ok(ifp1, type);
    620        1.9   thorpej 		}
    621        1.9   thorpej 		if_ok_rdisc(ifp);
    622        1.9   thorpej 	}
    623       1.11  christos 
    624       1.11  christos 	if (ifp->int_state & IS_REMOTE) {
    625       1.11  christos 		if (!addrouteforif(ifp))
    626       1.11  christos 			return 0;
    627       1.11  christos 	}
    628        1.9   thorpej 	return 1;
    629        1.9   thorpej }
    630        1.9   thorpej 
    631        1.9   thorpej 
    632        1.9   thorpej /* disassemble routing message
    633        1.9   thorpej  */
    634        1.9   thorpej void
    635        1.9   thorpej rt_xaddrs(struct rt_addrinfo *info,
    636        1.9   thorpej 	  struct sockaddr *sa,
    637        1.9   thorpej 	  struct sockaddr *lim,
    638        1.9   thorpej 	  int addrs)
    639        1.9   thorpej {
    640        1.9   thorpej 	int i;
    641        1.9   thorpej #ifdef _HAVE_SA_LEN
    642        1.9   thorpej 	static struct sockaddr sa_zero;
    643        1.9   thorpej #endif
    644        1.9   thorpej #ifdef sgi
    645        1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
    646        1.9   thorpej 		    : sizeof(__uint64_t))
    647        1.9   thorpej #else
    648        1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
    649        1.9   thorpej 		    : sizeof(long))
    650        1.9   thorpej #endif
    651        1.9   thorpej 
    652        1.9   thorpej 
    653       1.12     lukem 	memset(info, 0, sizeof(*info));
    654        1.9   thorpej 	info->rti_addrs = addrs;
    655        1.9   thorpej 	for (i = 0; i < RTAX_MAX && sa < lim; i++) {
    656        1.9   thorpej 		if ((addrs & (1 << i)) == 0)
    657        1.9   thorpej 			continue;
    658        1.9   thorpej #ifdef _HAVE_SA_LEN
    659        1.9   thorpej 		info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero;
    660        1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    661        1.9   thorpej 					 + ROUNDUP(sa->sa_len));
    662        1.9   thorpej #else
    663        1.9   thorpej 		info->rti_info[i] = sa;
    664        1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    665        1.9   thorpej 					 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
    666        1.9   thorpej #endif
    667        1.9   thorpej 	}
    668        1.9   thorpej }
    669        1.9   thorpej 
    670        1.9   thorpej 
    671        1.9   thorpej /* Find the network interfaces which have configured themselves.
    672        1.9   thorpej  *	This must be done regularly, if only for extra addresses
    673        1.9   thorpej  *	that come and go on interfaces.
    674        1.9   thorpej  */
    675        1.9   thorpej void
    676        1.9   thorpej ifinit(void)
    677        1.9   thorpej {
    678        1.9   thorpej 	static char *sysctl_buf;
    679        1.9   thorpej 	static size_t sysctl_buf_size = 0;
    680        1.9   thorpej 	uint complaints = 0;
    681        1.9   thorpej 	static u_int prev_complaints = 0;
    682       1.10  christos #	define COMP_NOT_INET	0x001
    683       1.11  christos #	define COMP_NOADDR	0x002
    684       1.11  christos #	define COMP_BADADDR	0x004
    685       1.11  christos #	define COMP_NODST	0x008
    686       1.11  christos #	define COMP_NOBADR	0x010
    687       1.11  christos #	define COMP_NOMASK	0x020
    688       1.11  christos #	define COMP_DUP		0x040
    689       1.11  christos #	define COMP_BAD_METRIC	0x080
    690       1.11  christos #	define COMP_NETMASK	0x100
    691        1.9   thorpej 
    692        1.9   thorpej 	struct interface ifs, ifs0, *ifp, *ifp1;
    693        1.9   thorpej 	struct rt_entry *rt;
    694        1.9   thorpej 	size_t needed;
    695        1.9   thorpej 	int mib[6];
    696        1.9   thorpej 	struct if_msghdr *ifm;
    697        1.9   thorpej 	struct ifa_msghdr *ifam, *ifam_lim, *ifam2;
    698        1.9   thorpej 	int in, ierr, out, oerr;
    699        1.9   thorpej 	struct intnet *intnetp;
    700        1.9   thorpej 	struct rt_addrinfo info;
    701        1.9   thorpej #ifdef SIOCGIFMETRIC
    702        1.9   thorpej 	struct ifreq ifr;
    703        1.9   thorpej #endif
    704        1.9   thorpej 
    705        1.9   thorpej 
    706       1.11  christos 	last_ifinit = now;
    707        1.9   thorpej 	ifinit_timer.tv_sec = now.tv_sec + (supplier
    708        1.9   thorpej 					    ? CHECK_ACT_INTERVAL
    709        1.9   thorpej 					    : CHECK_QUIET_INTERVAL);
    710        1.9   thorpej 
    711       1.16  christos 	/* mark all interfaces so we can get rid of those that disappear */
    712        1.9   thorpej 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
    713        1.9   thorpej 		ifp->int_state &= ~(IS_CHECKED | IS_DUP);
    714        1.9   thorpej 
    715        1.9   thorpej 	/* Fetch the interface list, without too many system calls
    716        1.9   thorpej 	 * since we do it repeatedly.
    717        1.9   thorpej 	 */
    718        1.9   thorpej 	mib[0] = CTL_NET;
    719        1.9   thorpej 	mib[1] = PF_ROUTE;
    720        1.9   thorpej 	mib[2] = 0;
    721        1.9   thorpej 	mib[3] = AF_INET;
    722        1.9   thorpej 	mib[4] = NET_RT_IFLIST;
    723        1.9   thorpej 	mib[5] = 0;
    724        1.9   thorpej 	for (;;) {
    725        1.9   thorpej 		if ((needed = sysctl_buf_size) != 0) {
    726        1.9   thorpej 			if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
    727        1.9   thorpej 				break;
    728       1.14   thorpej 			/* retry if the table grew */
    729        1.9   thorpej 			if (errno != ENOMEM && errno != EFAULT)
    730       1.14   thorpej 				BADERR(1, "ifinit: sysctl(RT_IFLIST)");
    731        1.9   thorpej 			free(sysctl_buf);
    732        1.9   thorpej 			needed = 0;
    733        1.9   thorpej 		}
    734        1.9   thorpej 		if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
    735       1.14   thorpej 			BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate");
    736       1.14   thorpej 		sysctl_buf = rtmalloc(sysctl_buf_size = needed,
    737       1.14   thorpej 				      "ifinit sysctl");
    738        1.9   thorpej 	}
    739        1.9   thorpej 
    740        1.9   thorpej 	ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
    741        1.9   thorpej 	for (ifam = (struct ifa_msghdr *)sysctl_buf;
    742        1.9   thorpej 	     ifam < ifam_lim;
    743        1.9   thorpej 	     ifam = ifam2) {
    744        1.9   thorpej 
    745        1.9   thorpej 		ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen);
    746        1.9   thorpej 
    747       1.18    bouyer #ifdef RTM_OIFINFO
    748       1.24  christos 		if (ifam->ifam_type == RTM_OIFINFO)
    749       1.24  christos 			continue;	/* just ignore compat message */
    750       1.18    bouyer #endif
    751        1.9   thorpej 		if (ifam->ifam_type == RTM_IFINFO) {
    752       1.26    dyoung 			const struct sockaddr_dl *sdl;
    753       1.11  christos 
    754        1.9   thorpej 			ifm = (struct if_msghdr *)ifam;
    755        1.9   thorpej 			/* make prototype structure for the IP aliases
    756        1.9   thorpej 			 */
    757       1.12     lukem 			memset(&ifs0, 0, sizeof(ifs0));
    758        1.9   thorpej 			ifs0.int_rip_sock = -1;
    759        1.9   thorpej 			ifs0.int_index = ifm->ifm_index;
    760        1.9   thorpej 			ifs0.int_if_flags = ifm->ifm_flags;
    761        1.9   thorpej 			ifs0.int_state = IS_CHECKED;
    762       1.11  christos 			ifs0.int_query_time = NEVER;
    763        1.9   thorpej 			ifs0.int_act_time = now.tv_sec;
    764        1.9   thorpej 			ifs0.int_data.ts = now.tv_sec;
    765        1.9   thorpej 			ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets;
    766        1.9   thorpej 			ifs0.int_data.ierrors = ifm->ifm_data.ifi_ierrors;
    767        1.9   thorpej 			ifs0.int_data.opackets = ifm->ifm_data.ifi_opackets;
    768        1.9   thorpej 			ifs0.int_data.oerrors = ifm->ifm_data.ifi_oerrors;
    769        1.9   thorpej #ifdef sgi
    770        1.9   thorpej 			ifs0.int_data.odrops = ifm->ifm_data.ifi_odrops;
    771        1.9   thorpej #endif
    772       1.26    dyoung 			sdl = (const struct sockaddr_dl *)(ifm + 1);
    773       1.26    dyoung 			/* NUL-termination by memset, above. */
    774       1.26    dyoung 			memcpy(ifs0.int_name, sdl->sdl_data,
    775       1.26    dyoung 				MIN(sizeof(ifs0.int_name) - 1, sdl->sdl_nlen));
    776        1.9   thorpej 			continue;
    777        1.9   thorpej 		}
    778        1.9   thorpej 		if (ifam->ifam_type != RTM_NEWADDR) {
    779       1.10  christos 			logbad(1,"ifinit: out of sync");
    780        1.9   thorpej 			continue;
    781        1.9   thorpej 		}
    782        1.9   thorpej 		rt_xaddrs(&info, (struct sockaddr *)(ifam+1),
    783        1.9   thorpej 			  (struct sockaddr *)ifam2,
    784        1.9   thorpej 			  ifam->ifam_addrs);
    785        1.9   thorpej 
    786       1.11  christos 		/* Prepare for the next address of this interface, which
    787       1.11  christos 		 * will be an alias.
    788       1.11  christos 		 * Do not output RIP or Router-Discovery packets via aliases.
    789       1.11  christos 		 */
    790       1.16  christos 		memcpy(&ifs, &ifs0, sizeof(ifs));
    791       1.14   thorpej 		ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC);
    792       1.11  christos 
    793        1.9   thorpej 		if (INFO_IFA(&info) == 0) {
    794       1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    795        1.9   thorpej 				if (!(prev_complaints & COMP_NOADDR))
    796       1.10  christos 					msglog("%s has no address",
    797       1.11  christos 					       ifs.int_name);
    798        1.9   thorpej 				complaints |= COMP_NOADDR;
    799        1.9   thorpej 			}
    800        1.9   thorpej 			continue;
    801        1.9   thorpej 		}
    802        1.9   thorpej 		if (INFO_IFA(&info)->sa_family != AF_INET) {
    803       1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    804        1.9   thorpej 				if (!(prev_complaints & COMP_NOT_INET))
    805       1.11  christos 					trace_act("%s: not AF_INET",
    806       1.11  christos 						  ifs.int_name);
    807        1.9   thorpej 				complaints |= COMP_NOT_INET;
    808        1.9   thorpej 			}
    809        1.9   thorpej 			continue;
    810        1.9   thorpej 		}
    811        1.9   thorpej 
    812        1.9   thorpej 		ifs.int_addr = S_ADDR(INFO_IFA(&info));
    813        1.9   thorpej 
    814       1.10  christos 		if (ntohl(ifs.int_addr)>>24 == 0
    815       1.10  christos 		    || ntohl(ifs.int_addr)>>24 == 0xff) {
    816       1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    817       1.10  christos 				if (!(prev_complaints & COMP_BADADDR))
    818       1.10  christos 					msglog("%s has a bad address",
    819       1.11  christos 					       ifs.int_name);
    820       1.10  christos 				complaints |= COMP_BADADDR;
    821       1.10  christos 			}
    822       1.10  christos 			continue;
    823       1.10  christos 		}
    824       1.10  christos 
    825       1.11  christos 		if (ifs.int_if_flags & IFF_LOOPBACK) {
    826       1.11  christos 			ifs.int_state |= IS_PASSIVE | IS_NO_RIP | IS_NO_RDISC;
    827        1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    828       1.11  christos 			ifs.int_mask = HOST_MASK;
    829       1.11  christos 			ifs.int_ripv1_mask = HOST_MASK;
    830       1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    831       1.11  christos 			ifs.int_net = ntohl(ifs.int_dstaddr);
    832       1.11  christos 			if (!foundloopback) {
    833       1.11  christos 				foundloopback = 1;
    834       1.11  christos 				loopaddr = ifs.int_addr;
    835       1.14   thorpej 				loop_rts.rts_gate = loopaddr;
    836       1.14   thorpej 				loop_rts.rts_router = loopaddr;
    837        1.9   thorpej 			}
    838        1.9   thorpej 
    839        1.9   thorpej 		} else if (ifs.int_if_flags & IFF_POINTOPOINT) {
    840        1.9   thorpej 			if (INFO_BRD(&info) == 0
    841        1.9   thorpej 			    || INFO_BRD(&info)->sa_family != AF_INET) {
    842       1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    843        1.9   thorpej 					if (!(prev_complaints & COMP_NODST))
    844        1.9   thorpej 						msglog("%s has a bad"
    845        1.9   thorpej 						       " destination address",
    846       1.11  christos 						       ifs.int_name);
    847        1.9   thorpej 					complaints |= COMP_NODST;
    848        1.9   thorpej 				}
    849        1.9   thorpej 				continue;
    850        1.9   thorpej 			}
    851        1.9   thorpej 			ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
    852       1.10  christos 			if (ntohl(ifs.int_dstaddr)>>24 == 0
    853       1.10  christos 			    || ntohl(ifs.int_dstaddr)>>24 == 0xff) {
    854       1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    855       1.10  christos 					if (!(prev_complaints & COMP_NODST))
    856       1.10  christos 						msglog("%s has a bad"
    857       1.10  christos 						       " destination address",
    858       1.11  christos 						       ifs.int_name);
    859       1.10  christos 					complaints |= COMP_NODST;
    860       1.10  christos 				}
    861       1.10  christos 				continue;
    862       1.10  christos 			}
    863        1.9   thorpej 			ifs.int_mask = HOST_MASK;
    864        1.9   thorpej 			ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    865       1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    866        1.9   thorpej 			ifs.int_net = ntohl(ifs.int_dstaddr);
    867        1.9   thorpej 
    868       1.11  christos 		}  else {
    869       1.11  christos 			if (INFO_MASK(&info) == 0) {
    870       1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    871       1.11  christos 					if (!(prev_complaints & COMP_NOMASK))
    872       1.11  christos 						msglog("%s has no netmask",
    873       1.11  christos 						       ifs.int_name);
    874       1.11  christos 					complaints |= COMP_NOMASK;
    875       1.11  christos 				}
    876       1.11  christos 				continue;
    877       1.11  christos 			}
    878        1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    879       1.11  christos 			ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    880       1.11  christos 			ifs.int_ripv1_mask = ifs.int_mask;
    881       1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_addr);
    882       1.11  christos 			ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask;
    883       1.11  christos 			if (ifs.int_mask != ifs.int_std_mask)
    884       1.11  christos 				ifs.int_state |= IS_SUBNET;
    885       1.11  christos 
    886       1.11  christos 			if (ifs.int_if_flags & IFF_BROADCAST) {
    887       1.11  christos 				if (INFO_BRD(&info) == 0) {
    888       1.14   thorpej 					if (iff_up(ifs.int_if_flags)) {
    889       1.11  christos 					    if (!(prev_complaints
    890       1.11  christos 						  & COMP_NOBADR))
    891       1.11  christos 						msglog("%s has"
    892       1.11  christos 						       "no broadcast address",
    893       1.11  christos 						       ifs.int_name);
    894       1.11  christos 					    complaints |= COMP_NOBADR;
    895       1.11  christos 					}
    896       1.11  christos 					continue;
    897       1.11  christos 				}
    898       1.11  christos 				ifs.int_brdaddr = S_ADDR(INFO_BRD(&info));
    899        1.9   thorpej 			}
    900        1.9   thorpej 		}
    901        1.9   thorpej 		ifs.int_std_net = ifs.int_net & ifs.int_std_mask;
    902        1.9   thorpej 		ifs.int_std_addr = htonl(ifs.int_std_net);
    903        1.9   thorpej 
    904        1.9   thorpej 		/* Use a minimum metric of one.  Treat the interface metric
    905        1.9   thorpej 		 * (default 0) as an increment to the hop count of one.
    906        1.9   thorpej 		 *
    907        1.9   thorpej 		 * The metric obtained from the routing socket dump of
    908        1.9   thorpej 		 * interface addresses is wrong.  It is not set by the
    909        1.9   thorpej 		 * SIOCSIFMETRIC ioctl.
    910        1.9   thorpej 		 */
    911        1.9   thorpej #ifdef SIOCGIFMETRIC
    912       1.11  christos 		strncpy(ifr.ifr_name, ifs.int_name, sizeof(ifr.ifr_name));
    913        1.9   thorpej 		if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) {
    914        1.9   thorpej 			DBGERR(1, "ioctl(SIOCGIFMETRIC)");
    915        1.9   thorpej 			ifs.int_metric = 0;
    916        1.9   thorpej 		} else {
    917        1.9   thorpej 			ifs.int_metric = ifr.ifr_metric;
    918        1.9   thorpej 		}
    919        1.9   thorpej #else
    920        1.9   thorpej 		ifs.int_metric = ifam->ifam_metric;
    921        1.9   thorpej #endif
    922        1.9   thorpej 		if (ifs.int_metric > HOPCNT_INFINITY) {
    923        1.9   thorpej 			ifs.int_metric = 0;
    924        1.9   thorpej 			if (!(prev_complaints & COMP_BAD_METRIC)
    925       1.14   thorpej 			    && iff_up(ifs.int_if_flags)) {
    926        1.9   thorpej 				complaints |= COMP_BAD_METRIC;
    927        1.9   thorpej 				msglog("%s has a metric of %d",
    928       1.11  christos 				       ifs.int_name, ifs.int_metric);
    929        1.9   thorpej 			}
    930        1.9   thorpej 		}
    931        1.9   thorpej 
    932        1.9   thorpej 		/* See if this is a familiar interface.
    933        1.9   thorpej 		 * If so, stop worrying about it if it is the same.
    934        1.9   thorpej 		 * Start it over if it now is to somewhere else, as happens
    935        1.9   thorpej 		 * frequently with PPP and SLIP.
    936        1.9   thorpej 		 */
    937       1.11  christos 		ifp = ifwithname(ifs.int_name, ((ifs.int_state & IS_ALIAS)
    938       1.11  christos 						? ifs.int_addr
    939       1.11  christos 						: 0));
    940        1.9   thorpej 		if (ifp != 0) {
    941        1.9   thorpej 			ifp->int_state |= IS_CHECKED;
    942        1.9   thorpej 
    943        1.9   thorpej 			if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags)
    944        1.9   thorpej 				  & (IFF_BROADCAST
    945        1.9   thorpej 				     | IFF_LOOPBACK
    946        1.9   thorpej 				     | IFF_POINTOPOINT
    947        1.9   thorpej 				     | IFF_MULTICAST))
    948        1.9   thorpej 			    || 0 != ((ifp->int_state ^ ifs.int_state)
    949        1.9   thorpej 				     & IS_ALIAS)
    950        1.9   thorpej 			    || ifp->int_addr != ifs.int_addr
    951        1.9   thorpej 			    || ifp->int_brdaddr != ifs.int_brdaddr
    952        1.9   thorpej 			    || ifp->int_dstaddr != ifs.int_dstaddr
    953        1.9   thorpej 			    || ifp->int_mask != ifs.int_mask
    954        1.9   thorpej 			    || ifp->int_metric != ifs.int_metric) {
    955        1.9   thorpej 				/* Forget old information about
    956        1.9   thorpej 				 * a changed interface.
    957        1.9   thorpej 				 */
    958       1.11  christos 				trace_act("interface %s has changed",
    959        1.9   thorpej 					  ifp->int_name);
    960        1.9   thorpej 				ifdel(ifp);
    961        1.9   thorpej 				ifp = 0;
    962        1.9   thorpej 			}
    963        1.9   thorpej 		}
    964        1.9   thorpej 
    965        1.9   thorpej 		if (ifp != 0) {
    966       1.10  christos 			/* The primary representative of an alias worries
    967       1.10  christos 			 * about how things are working.
    968       1.10  christos 			 */
    969        1.9   thorpej 			if (ifp->int_state & IS_ALIAS)
    970        1.9   thorpej 				continue;
    971        1.9   thorpej 
    972        1.9   thorpej 			/* note interfaces that have been turned off
    973        1.9   thorpej 			 */
    974       1.14   thorpej 			if (!iff_up(ifs.int_if_flags)) {
    975       1.14   thorpej 				if (iff_up(ifp->int_if_flags)) {
    976        1.9   thorpej 					msglog("interface %s to %s turned off",
    977        1.9   thorpej 					       ifp->int_name,
    978       1.11  christos 					       naddr_ntoa(ifp->int_dstaddr));
    979        1.9   thorpej 					if_bad(ifp);
    980       1.14   thorpej 					ifp->int_if_flags &= ~IFF_UP;
    981       1.14   thorpej 				} else if (now.tv_sec>(ifp->int_data.ts
    982       1.14   thorpej 						       + CHECK_BAD_INTERVAL)) {
    983       1.14   thorpej 					trace_act("interface %s has been off"
    984  1.26.10.1       mjf 						  " %lld seconds; forget it",
    985       1.14   thorpej 						  ifp->int_name,
    986  1.26.10.1       mjf 						  (long long)now.tv_sec -
    987  1.26.10.1       mjf 						  ifp->int_data.ts);
    988       1.14   thorpej 					ifdel(ifp);
    989       1.25  christos 					ifp = 0;
    990        1.9   thorpej 				}
    991        1.9   thorpej 				continue;
    992        1.9   thorpej 			}
    993        1.9   thorpej 			/* or that were off and are now ok */
    994       1.14   thorpej 			if (!iff_up(ifp->int_if_flags)) {
    995       1.14   thorpej 				ifp->int_if_flags |= IFF_UP;
    996        1.9   thorpej 				(void)if_ok(ifp, "");
    997        1.9   thorpej 			}
    998        1.9   thorpej 
    999        1.9   thorpej 			/* If it has been long enough,
   1000        1.9   thorpej 			 * see if the interface is broken.
   1001        1.9   thorpej 			 */
   1002        1.9   thorpej 			if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL)
   1003        1.9   thorpej 				continue;
   1004        1.9   thorpej 
   1005        1.9   thorpej 			in = ifs.int_data.ipackets - ifp->int_data.ipackets;
   1006        1.9   thorpej 			ierr = ifs.int_data.ierrors - ifp->int_data.ierrors;
   1007        1.9   thorpej 			out = ifs.int_data.opackets - ifp->int_data.opackets;
   1008        1.9   thorpej 			oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
   1009        1.9   thorpej #ifdef sgi
   1010        1.9   thorpej 			/* Through at least IRIX 6.2, PPP and SLIP
   1011       1.11  christos 			 * count packets dropped by the filters.
   1012        1.9   thorpej 			 * But FDDI rings stuck non-operational count
   1013        1.9   thorpej 			 * dropped packets as they wait for improvement.
   1014        1.9   thorpej 			 */
   1015        1.9   thorpej 			if (!(ifp->int_if_flags & IFF_POINTOPOINT))
   1016        1.9   thorpej 				oerr += (ifs.int_data.odrops
   1017        1.9   thorpej 					 - ifp->int_data.odrops);
   1018        1.9   thorpej #endif
   1019        1.9   thorpej 			/* If the interface just awoke, restart the counters.
   1020        1.9   thorpej 			 */
   1021        1.9   thorpej 			if (ifp->int_data.ts == 0) {
   1022        1.9   thorpej 				ifp->int_data = ifs.int_data;
   1023        1.9   thorpej 				continue;
   1024        1.9   thorpej 			}
   1025        1.9   thorpej 			ifp->int_data = ifs.int_data;
   1026        1.9   thorpej 
   1027       1.16  christos 			/* Withhold judgment when the short error
   1028        1.9   thorpej 			 * counters wrap or the interface is reset.
   1029        1.9   thorpej 			 */
   1030        1.9   thorpej 			if (ierr < 0 || in < 0 || oerr < 0 || out < 0) {
   1031        1.9   thorpej 				LIM_SEC(ifinit_timer,
   1032        1.9   thorpej 					now.tv_sec+CHECK_BAD_INTERVAL);
   1033        1.9   thorpej 				continue;
   1034        1.9   thorpej 			}
   1035        1.9   thorpej 
   1036        1.9   thorpej 			/* Withhold judgement when there is no traffic
   1037        1.9   thorpej 			 */
   1038        1.9   thorpej 			if (in == 0 && out == 0 && ierr == 0 && oerr == 0)
   1039        1.9   thorpej 				continue;
   1040        1.9   thorpej 
   1041        1.9   thorpej 			/* It is bad if input or output is not working.
   1042        1.9   thorpej 			 * Require presistent problems before marking it dead.
   1043        1.9   thorpej 			 */
   1044        1.9   thorpej 			if ((in <= ierr && ierr > 0)
   1045        1.9   thorpej 			    || (out <= oerr && oerr > 0)) {
   1046        1.9   thorpej 				if (!(ifp->int_state & IS_SICK)) {
   1047        1.9   thorpej 					trace_act("interface %s to %s"
   1048        1.9   thorpej 						  " sick: in=%d ierr=%d"
   1049       1.11  christos 						  " out=%d oerr=%d",
   1050        1.9   thorpej 						  ifp->int_name,
   1051       1.11  christos 						  naddr_ntoa(ifp->int_dstaddr),
   1052        1.9   thorpej 						  in, ierr, out, oerr);
   1053        1.9   thorpej 					if_sick(ifp);
   1054        1.9   thorpej 					continue;
   1055        1.9   thorpej 				}
   1056        1.9   thorpej 				if (!(ifp->int_state & IS_BROKE)) {
   1057       1.11  christos 					msglog("interface %s to %s broken:"
   1058        1.9   thorpej 					       " in=%d ierr=%d out=%d oerr=%d",
   1059        1.9   thorpej 					       ifp->int_name,
   1060       1.11  christos 					       naddr_ntoa(ifp->int_dstaddr),
   1061        1.9   thorpej 					       in, ierr, out, oerr);
   1062        1.9   thorpej 					if_bad(ifp);
   1063        1.9   thorpej 				}
   1064        1.9   thorpej 				continue;
   1065        1.9   thorpej 			}
   1066        1.9   thorpej 
   1067        1.9   thorpej 			/* otherwise, it is active and healthy
   1068        1.9   thorpej 			 */
   1069        1.9   thorpej 			ifp->int_act_time = now.tv_sec;
   1070        1.9   thorpej 			(void)if_ok(ifp, "");
   1071        1.9   thorpej 			continue;
   1072        1.9   thorpej 		}
   1073        1.9   thorpej 
   1074        1.9   thorpej 		/* This is a new interface.
   1075        1.9   thorpej 		 * If it is dead, forget it.
   1076        1.9   thorpej 		 */
   1077       1.14   thorpej 		if (!iff_up(ifs.int_if_flags))
   1078        1.9   thorpej 			continue;
   1079        1.9   thorpej 
   1080       1.11  christos 		/* If it duplicates an existing interface,
   1081       1.11  christos 		 * complain about it, mark the other one
   1082       1.11  christos 		 * duplicated, and forget this one.
   1083        1.9   thorpej 		 */
   1084       1.11  christos 		ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask,
   1085       1.11  christos 				ifs.int_if_flags);
   1086       1.11  christos 		if (ifp != 0) {
   1087       1.11  christos 			/* Ignore duplicates of itself, caused by having
   1088       1.11  christos 			 * IP aliases on the same network.
   1089        1.9   thorpej 			 */
   1090       1.11  christos 			if (!strcmp(ifp->int_name, ifs.int_name))
   1091        1.9   thorpej 				continue;
   1092        1.9   thorpej 
   1093        1.9   thorpej 			if (!(prev_complaints & COMP_DUP)) {
   1094        1.9   thorpej 				complaints |= COMP_DUP;
   1095       1.11  christos 				msglog("%s (%s%s%s) is duplicated by"
   1096       1.11  christos 				       " %s (%s%s%s)",
   1097       1.11  christos 				       ifs.int_name,
   1098       1.11  christos 				       addrname(ifs.int_addr,ifs.int_mask,1),
   1099       1.11  christos 				       ((ifs.int_if_flags & IFF_POINTOPOINT)
   1100       1.11  christos 					? "-->" : ""),
   1101       1.11  christos 				       ((ifs.int_if_flags & IFF_POINTOPOINT)
   1102       1.11  christos 					? naddr_ntoa(ifs.int_dstaddr) : ""),
   1103       1.11  christos 				       ifp->int_name,
   1104       1.11  christos 				       addrname(ifp->int_addr,ifp->int_mask,1),
   1105       1.11  christos 				       ((ifp->int_if_flags & IFF_POINTOPOINT)
   1106       1.11  christos 					? "-->" : ""),
   1107       1.11  christos 				       ((ifp->int_if_flags & IFF_POINTOPOINT)
   1108       1.11  christos 					? naddr_ntoa(ifp->int_dstaddr) : ""));
   1109        1.9   thorpej 			}
   1110        1.9   thorpej 			ifp->int_state |= IS_DUP;
   1111       1.11  christos 			continue;
   1112       1.11  christos 		}
   1113       1.11  christos 
   1114       1.11  christos 		if (0 == (ifs.int_if_flags & (IFF_POINTOPOINT | IFF_BROADCAST))
   1115       1.11  christos 		    && !(ifs.int_state & IS_PASSIVE)) {
   1116       1.11  christos 			trace_act("%s is neither broadcast, point-to-point,"
   1117       1.11  christos 				  " nor loopback",
   1118       1.11  christos 				  ifs.int_name);
   1119       1.11  christos 			if (!(ifs.int_state & IFF_MULTICAST))
   1120       1.11  christos 				ifs.int_state |= IS_NO_RDISC;
   1121        1.9   thorpej 		}
   1122        1.9   thorpej 
   1123        1.9   thorpej 
   1124       1.11  christos 		/* It is new and ok.   Add it to the list of interfaces
   1125        1.9   thorpej 		 */
   1126       1.14   thorpej 		ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp");
   1127       1.16  christos 		memcpy(ifp, &ifs, sizeof(*ifp));
   1128       1.11  christos 		get_parms(ifp);
   1129       1.11  christos 		if_link(ifp);
   1130        1.9   thorpej 		trace_if("Add", ifp);
   1131        1.9   thorpej 
   1132       1.10  christos 		/* Notice likely bad netmask.
   1133       1.10  christos 		 */
   1134       1.10  christos 		if (!(prev_complaints & COMP_NETMASK)
   1135       1.11  christos 		    && !(ifp->int_if_flags & IFF_POINTOPOINT)
   1136       1.11  christos 		    && ifp->int_addr != RIP_DEFAULT) {
   1137       1.10  christos 			for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
   1138       1.10  christos 				if (ifp1->int_mask == ifp->int_mask)
   1139       1.10  christos 					continue;
   1140       1.10  christos 				if (ifp1->int_if_flags & IFF_POINTOPOINT)
   1141       1.10  christos 					continue;
   1142       1.11  christos 				if (ifp1->int_dstaddr == RIP_DEFAULT)
   1143       1.22  christos 					continue;
   1144       1.22  christos 				/* ignore aliases on the right network */
   1145       1.22  christos 				if (!strcmp(ifp->int_name, ifp1->int_name))
   1146       1.11  christos 					continue;
   1147       1.11  christos 				if (on_net(ifp->int_dstaddr,
   1148       1.10  christos 					   ifp1->int_net, ifp1->int_mask)
   1149       1.11  christos 				    || on_net(ifp1->int_dstaddr,
   1150       1.10  christos 					      ifp->int_net, ifp->int_mask)) {
   1151       1.10  christos 					msglog("possible netmask problem"
   1152       1.11  christos 					       " between %s:%s and %s:%s",
   1153       1.10  christos 					       ifp->int_name,
   1154       1.10  christos 					       addrname(htonl(ifp->int_net),
   1155       1.10  christos 							ifp->int_mask, 1),
   1156       1.10  christos 					       ifp1->int_name,
   1157       1.10  christos 					       addrname(htonl(ifp1->int_net),
   1158       1.10  christos 							ifp1->int_mask, 1));
   1159       1.10  christos 					complaints |= COMP_NETMASK;
   1160       1.10  christos 				}
   1161       1.10  christos 			}
   1162       1.10  christos 		}
   1163       1.10  christos 
   1164        1.9   thorpej 		if (!(ifp->int_state & IS_ALIAS)) {
   1165       1.11  christos 			/* Count the # of directly connected networks.
   1166       1.11  christos 			 */
   1167        1.9   thorpej 			if (!(ifp->int_if_flags & IFF_LOOPBACK))
   1168        1.9   thorpej 				tot_interfaces++;
   1169        1.9   thorpej 			if (!IS_RIP_OFF(ifp->int_state))
   1170        1.9   thorpej 				rip_interfaces++;
   1171       1.11  christos 
   1172       1.11  christos 			/* turn on router discovery and RIP If needed */
   1173       1.11  christos 			if_ok_rdisc(ifp);
   1174       1.11  christos 			rip_on(ifp);
   1175        1.9   thorpej 		}
   1176        1.9   thorpej 	}
   1177        1.9   thorpej 
   1178       1.11  christos 	/* If we are multi-homed and have at least two interfaces
   1179        1.9   thorpej 	 * listening to RIP, then output by default.
   1180        1.9   thorpej 	 */
   1181        1.9   thorpej 	if (!supplier_set && rip_interfaces > 1)
   1182        1.9   thorpej 		set_supplier();
   1183        1.9   thorpej 
   1184        1.9   thorpej 	/* If we are multi-homed, optionally advertise a route to
   1185        1.9   thorpej 	 * our main address.
   1186        1.9   thorpej 	 */
   1187       1.25  christos 	if ((advertise_mhome && ifp)
   1188        1.9   thorpej 	    || (tot_interfaces > 1
   1189        1.9   thorpej 		&& mhome
   1190        1.9   thorpej 		&& (ifp = ifwithaddr(myaddr, 0, 0)) != 0
   1191        1.9   thorpej 		&& foundloopback)) {
   1192        1.9   thorpej 		advertise_mhome = 1;
   1193        1.9   thorpej 		rt = rtget(myaddr, HOST_MASK);
   1194        1.9   thorpej 		if (rt != 0) {
   1195        1.9   thorpej 			if (rt->rt_ifp != ifp
   1196        1.9   thorpej 			    || rt->rt_router != loopaddr) {
   1197        1.9   thorpej 				rtdelete(rt);
   1198        1.9   thorpej 				rt = 0;
   1199        1.9   thorpej 			} else {
   1200       1.14   thorpej 				loop_rts.rts_ifp = ifp;
   1201       1.14   thorpej 				loop_rts.rts_metric = 0;
   1202       1.14   thorpej 				loop_rts.rts_time = rt->rt_time;
   1203        1.9   thorpej 				rtchange(rt, rt->rt_state | RS_MHOME,
   1204       1.14   thorpej 					 &loop_rts, 0);
   1205        1.9   thorpej 			}
   1206        1.9   thorpej 		}
   1207       1.14   thorpej 		if (rt == 0) {
   1208       1.14   thorpej 			loop_rts.rts_ifp = ifp;
   1209       1.14   thorpej 			loop_rts.rts_metric = 0;
   1210       1.14   thorpej 			rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts);
   1211       1.14   thorpej 		}
   1212        1.9   thorpej 	}
   1213        1.9   thorpej 
   1214        1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp1) {
   1215        1.9   thorpej 		ifp1 = ifp->int_next;	/* because we may delete it */
   1216        1.9   thorpej 
   1217        1.9   thorpej 		/* Forget any interfaces that have disappeared.
   1218        1.9   thorpej 		 */
   1219        1.9   thorpej 		if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
   1220       1.11  christos 			trace_act("interface %s has disappeared",
   1221        1.9   thorpej 				  ifp->int_name);
   1222        1.9   thorpej 			ifdel(ifp);
   1223        1.9   thorpej 			continue;
   1224        1.9   thorpej 		}
   1225        1.9   thorpej 
   1226        1.9   thorpej 		if ((ifp->int_state & IS_BROKE)
   1227        1.9   thorpej 		    && !(ifp->int_state & IS_PASSIVE))
   1228        1.9   thorpej 			LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
   1229        1.9   thorpej 
   1230        1.9   thorpej 		/* If we ever have a RIPv1 interface, assume we always will.
   1231        1.9   thorpej 		 * It might come back if it ever goes away.
   1232        1.9   thorpej 		 */
   1233       1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier)
   1234       1.10  christos 			have_ripv1_out = 1;
   1235       1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_IN))
   1236       1.10  christos 			have_ripv1_in = 1;
   1237        1.9   thorpej 	}
   1238        1.9   thorpej 
   1239        1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
   1240        1.9   thorpej 		/* Ensure there is always a network route for interfaces,
   1241        1.9   thorpej 		 * after any dead interfaces have been deleted, which
   1242        1.9   thorpej 		 * might affect routes for point-to-point links.
   1243        1.9   thorpej 		 */
   1244       1.11  christos 		if (!addrouteforif(ifp))
   1245       1.11  christos 			continue;
   1246        1.9   thorpej 
   1247        1.9   thorpej 		/* Add routes to the local end of point-to-point interfaces
   1248        1.9   thorpej 		 * using loopback.
   1249        1.9   thorpej 		 */
   1250        1.9   thorpej 		if ((ifp->int_if_flags & IFF_POINTOPOINT)
   1251        1.9   thorpej 		    && !(ifp->int_state & IS_REMOTE)
   1252        1.9   thorpej 		    && foundloopback) {
   1253        1.9   thorpej 			/* Delete any routes to the network address through
   1254        1.9   thorpej 			 * foreign routers. Remove even static routes.
   1255        1.9   thorpej 			 */
   1256       1.14   thorpej 			del_static(ifp->int_addr, HOST_MASK, 0, 0);
   1257        1.9   thorpej 			rt = rtget(ifp->int_addr, HOST_MASK);
   1258        1.9   thorpej 			if (rt != 0 && rt->rt_router != loopaddr) {
   1259        1.9   thorpej 				rtdelete(rt);
   1260        1.9   thorpej 				rt = 0;
   1261        1.9   thorpej 			}
   1262        1.9   thorpej 			if (rt != 0) {
   1263        1.9   thorpej 				if (!(rt->rt_state & RS_LOCAL)
   1264        1.9   thorpej 				    || rt->rt_metric > ifp->int_metric) {
   1265        1.9   thorpej 					ifp1 = ifp;
   1266        1.9   thorpej 				} else {
   1267        1.9   thorpej 					ifp1 = rt->rt_ifp;
   1268        1.9   thorpej 				}
   1269       1.14   thorpej 				loop_rts.rts_ifp = ifp1;
   1270       1.14   thorpej 				loop_rts.rts_metric = 0;
   1271       1.14   thorpej 				loop_rts.rts_time = rt->rt_time;
   1272       1.14   thorpej 				rtchange(rt, ((rt->rt_state & ~RS_NET_SYN)
   1273       1.14   thorpej 					      | (RS_IF|RS_LOCAL)),
   1274       1.14   thorpej 					 &loop_rts, 0);
   1275        1.9   thorpej 			} else {
   1276       1.14   thorpej 				loop_rts.rts_ifp = ifp;
   1277       1.14   thorpej 				loop_rts.rts_metric = 0;
   1278        1.9   thorpej 				rtadd(ifp->int_addr, HOST_MASK,
   1279       1.14   thorpej 				      (RS_IF | RS_LOCAL), &loop_rts);
   1280        1.9   thorpej 			}
   1281        1.9   thorpej 		}
   1282        1.9   thorpej 	}
   1283        1.9   thorpej 
   1284        1.9   thorpej 	/* add the authority routes */
   1285        1.9   thorpej 	for (intnetp = intnets; intnetp!=0; intnetp = intnetp->intnet_next) {
   1286        1.9   thorpej 		rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask);
   1287        1.9   thorpej 		if (rt != 0
   1288        1.9   thorpej 		    && !(rt->rt_state & RS_NO_NET_SYN)
   1289        1.9   thorpej 		    && !(rt->rt_state & RS_NET_INT)) {
   1290        1.9   thorpej 			rtdelete(rt);
   1291        1.9   thorpej 			rt = 0;
   1292        1.9   thorpej 		}
   1293       1.14   thorpej 		if (rt == 0) {
   1294       1.14   thorpej 			loop_rts.rts_ifp = 0;
   1295       1.14   thorpej 			loop_rts.rts_metric = intnetp->intnet_metric-1;
   1296        1.9   thorpej 			rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
   1297       1.14   thorpej 			      RS_NET_SYN | RS_NET_INT, &loop_rts);
   1298       1.14   thorpej 		}
   1299        1.9   thorpej 	}
   1300        1.9   thorpej 
   1301        1.9   thorpej 	prev_complaints = complaints;
   1302        1.9   thorpej }
   1303        1.9   thorpej 
   1304        1.9   thorpej 
   1305        1.9   thorpej static void
   1306        1.9   thorpej check_net_syn(struct interface *ifp)
   1307        1.9   thorpej {
   1308        1.9   thorpej 	struct rt_entry *rt;
   1309       1.14   thorpej 	static struct rt_spare new;
   1310        1.9   thorpej 
   1311        1.9   thorpej 
   1312        1.9   thorpej 	/* Turn on the need to automatically synthesize a network route
   1313        1.9   thorpej 	 * for this interface only if we are running RIPv1 on some other
   1314        1.9   thorpej 	 * interface that is on a different class-A,B,or C network.
   1315        1.9   thorpej 	 */
   1316        1.9   thorpej 	if (have_ripv1_out || have_ripv1_in) {
   1317        1.9   thorpej 		ifp->int_state |= IS_NEED_NET_SYN;
   1318        1.9   thorpej 		rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
   1319        1.9   thorpej 		if (rt != 0
   1320        1.9   thorpej 		    && 0 == (rt->rt_state & RS_NO_NET_SYN)
   1321        1.9   thorpej 		    && (!(rt->rt_state & RS_NET_SYN)
   1322        1.9   thorpej 			|| rt->rt_metric > ifp->int_metric)) {
   1323        1.9   thorpej 			rtdelete(rt);
   1324        1.9   thorpej 			rt = 0;
   1325        1.9   thorpej 		}
   1326       1.14   thorpej 		if (rt == 0) {
   1327       1.14   thorpej 			new.rts_ifp = ifp;
   1328       1.14   thorpej 			new.rts_gate = ifp->int_addr;
   1329       1.14   thorpej 			new.rts_router = ifp->int_addr;
   1330       1.14   thorpej 			new.rts_metric = ifp->int_metric;
   1331        1.9   thorpej 			rtadd(ifp->int_std_addr, ifp->int_std_mask,
   1332       1.14   thorpej 			      RS_NET_SYN, &new);
   1333       1.14   thorpej 		}
   1334        1.9   thorpej 
   1335        1.9   thorpej 	} else {
   1336        1.9   thorpej 		ifp->int_state &= ~IS_NEED_NET_SYN;
   1337        1.9   thorpej 
   1338        1.9   thorpej 		rt = rtget(ifp->int_std_addr,
   1339        1.9   thorpej 			   ifp->int_std_mask);
   1340        1.9   thorpej 		if (rt != 0
   1341        1.9   thorpej 		    && (rt->rt_state & RS_NET_SYN)
   1342        1.9   thorpej 		    && rt->rt_ifp == ifp)
   1343        1.9   thorpej 			rtbad_sub(rt);
   1344        1.9   thorpej 	}
   1345        1.9   thorpej }
   1346        1.9   thorpej 
   1347        1.9   thorpej 
   1348        1.9   thorpej /* Add route for interface if not currently installed.
   1349        1.9   thorpej  * Create route to other end if a point-to-point link,
   1350        1.9   thorpej  * otherwise a route to this (sub)network.
   1351        1.9   thorpej  */
   1352       1.11  christos int					/* 0=bad interface */
   1353        1.9   thorpej addrouteforif(struct interface *ifp)
   1354        1.9   thorpej {
   1355        1.9   thorpej 	struct rt_entry *rt;
   1356       1.14   thorpej 	static struct rt_spare new;
   1357       1.14   thorpej 	naddr dst;
   1358        1.9   thorpej 
   1359        1.9   thorpej 
   1360        1.9   thorpej 	/* skip sick interfaces
   1361        1.9   thorpej 	 */
   1362        1.9   thorpej 	if (ifp->int_state & IS_BROKE)
   1363       1.11  christos 		return 0;
   1364        1.9   thorpej 
   1365        1.9   thorpej 	/* If the interface on a subnet, then install a RIPv1 route to
   1366        1.9   thorpej 	 * the network as well (unless it is sick).
   1367        1.9   thorpej 	 */
   1368        1.9   thorpej 	if (ifp->int_state & IS_SUBNET)
   1369        1.9   thorpej 		check_net_syn(ifp);
   1370        1.9   thorpej 
   1371       1.11  christos 	dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
   1372       1.11  christos 	       ? ifp->int_dstaddr
   1373       1.11  christos 	       : htonl(ifp->int_net));
   1374        1.9   thorpej 
   1375       1.14   thorpej 	new.rts_ifp = ifp;
   1376       1.14   thorpej 	new.rts_router = ifp->int_addr;
   1377       1.14   thorpej 	new.rts_gate = ifp->int_addr;
   1378       1.14   thorpej 	new.rts_metric = ifp->int_metric;
   1379       1.14   thorpej 	new.rts_time = now.tv_sec;
   1380       1.14   thorpej 
   1381       1.11  christos 	/* If we are going to send packets to the gateway,
   1382       1.11  christos 	 * it must be reachable using our physical interfaces
   1383       1.11  christos 	 */
   1384       1.11  christos 	if ((ifp->int_state & IS_REMOTE)
   1385       1.11  christos 	    && !(ifp->int_state & IS_EXTERNAL)
   1386       1.11  christos 	    && !check_remote(ifp))
   1387       1.11  christos 		return 0;
   1388        1.9   thorpej 
   1389        1.9   thorpej 	/* We are finished if the correct main interface route exists.
   1390        1.9   thorpej 	 * The right route must be for the right interface, not synthesized
   1391        1.9   thorpej 	 * from a subnet, be a "gateway" or not as appropriate, and so forth.
   1392        1.9   thorpej 	 */
   1393       1.14   thorpej 	del_static(dst, ifp->int_mask, 0, 0);
   1394        1.9   thorpej 	rt = rtget(dst, ifp->int_mask);
   1395        1.9   thorpej 	if (rt != 0) {
   1396        1.9   thorpej 		if ((rt->rt_ifp != ifp
   1397        1.9   thorpej 		     || rt->rt_router != ifp->int_addr)
   1398        1.9   thorpej 		    && (!(ifp->int_state & IS_DUP)
   1399        1.9   thorpej 			|| rt->rt_ifp == 0
   1400        1.9   thorpej 			|| (rt->rt_ifp->int_state & IS_BROKE))) {
   1401        1.9   thorpej 			rtdelete(rt);
   1402        1.9   thorpej 			rt = 0;
   1403        1.9   thorpej 		} else {
   1404        1.9   thorpej 			rtchange(rt, ((rt->rt_state | RS_IF)
   1405        1.9   thorpej 				      & ~(RS_NET_SYN | RS_LOCAL)),
   1406       1.14   thorpej 				 &new, 0);
   1407        1.9   thorpej 		}
   1408        1.9   thorpej 	}
   1409        1.9   thorpej 	if (rt == 0) {
   1410        1.9   thorpej 		if (ifp->int_transitions++ > 0)
   1411       1.11  christos 			trace_act("re-install interface %s",
   1412        1.9   thorpej 				  ifp->int_name);
   1413        1.9   thorpej 
   1414       1.14   thorpej 		rtadd(dst, ifp->int_mask, RS_IF, &new);
   1415        1.1       cgd 	}
   1416       1.11  christos 
   1417       1.11  christos 	return 1;
   1418        1.1       cgd }
   1419