Home | History | Annotate | Line # | Download | only in routed
if.c revision 1.29.6.1
      1  1.29.6.1      yamt /*	$NetBSD: if.c,v 1.29.6.1 2012/10/30 18:59:32 yamt 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.29.6.1      yamt __RCSID("$NetBSD: if.c,v 1.29.6.1 2012/10/30 18:59:32 yamt 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.28  christos 	addr = 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.28  christos 	addr = 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.29.6.1      yamt #if defined(__NetBSD__) && defined(RT_ROUNDUP)
    645  1.29.6.1      yamt #define ROUNDUP(a) RT_ROUNDUP(a)
    646  1.29.6.1      yamt #else
    647       1.9   thorpej #ifdef sgi
    648       1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
    649       1.9   thorpej 		    : sizeof(__uint64_t))
    650       1.9   thorpej #else
    651       1.9   thorpej #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
    652       1.9   thorpej 		    : sizeof(long))
    653       1.9   thorpej #endif
    654  1.29.6.1      yamt #endif /* defined(__NetBSD__) && defined(RT_ROUNDUP) */
    655       1.9   thorpej 
    656       1.9   thorpej 
    657      1.12     lukem 	memset(info, 0, sizeof(*info));
    658       1.9   thorpej 	info->rti_addrs = addrs;
    659       1.9   thorpej 	for (i = 0; i < RTAX_MAX && sa < lim; i++) {
    660       1.9   thorpej 		if ((addrs & (1 << i)) == 0)
    661       1.9   thorpej 			continue;
    662       1.9   thorpej #ifdef _HAVE_SA_LEN
    663       1.9   thorpej 		info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero;
    664       1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    665       1.9   thorpej 					 + ROUNDUP(sa->sa_len));
    666       1.9   thorpej #else
    667       1.9   thorpej 		info->rti_info[i] = sa;
    668       1.9   thorpej 		sa = (struct sockaddr *)((char*)(sa)
    669       1.9   thorpej 					 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
    670       1.9   thorpej #endif
    671       1.9   thorpej 	}
    672       1.9   thorpej }
    673       1.9   thorpej 
    674       1.9   thorpej 
    675       1.9   thorpej /* Find the network interfaces which have configured themselves.
    676       1.9   thorpej  *	This must be done regularly, if only for extra addresses
    677       1.9   thorpej  *	that come and go on interfaces.
    678       1.9   thorpej  */
    679       1.9   thorpej void
    680       1.9   thorpej ifinit(void)
    681       1.9   thorpej {
    682       1.9   thorpej 	static char *sysctl_buf;
    683       1.9   thorpej 	static size_t sysctl_buf_size = 0;
    684       1.9   thorpej 	uint complaints = 0;
    685       1.9   thorpej 	static u_int prev_complaints = 0;
    686      1.10  christos #	define COMP_NOT_INET	0x001
    687      1.11  christos #	define COMP_NOADDR	0x002
    688      1.11  christos #	define COMP_BADADDR	0x004
    689      1.11  christos #	define COMP_NODST	0x008
    690      1.11  christos #	define COMP_NOBADR	0x010
    691      1.11  christos #	define COMP_NOMASK	0x020
    692      1.11  christos #	define COMP_DUP		0x040
    693      1.11  christos #	define COMP_BAD_METRIC	0x080
    694      1.11  christos #	define COMP_NETMASK	0x100
    695       1.9   thorpej 
    696       1.9   thorpej 	struct interface ifs, ifs0, *ifp, *ifp1;
    697       1.9   thorpej 	struct rt_entry *rt;
    698       1.9   thorpej 	size_t needed;
    699       1.9   thorpej 	int mib[6];
    700      1.29    martin 	struct if_msghdr ifm;
    701       1.9   thorpej 	struct ifa_msghdr *ifam, *ifam_lim, *ifam2;
    702       1.9   thorpej 	int in, ierr, out, oerr;
    703       1.9   thorpej 	struct intnet *intnetp;
    704       1.9   thorpej 	struct rt_addrinfo info;
    705       1.9   thorpej #ifdef SIOCGIFMETRIC
    706       1.9   thorpej 	struct ifreq ifr;
    707       1.9   thorpej #endif
    708       1.9   thorpej 
    709       1.9   thorpej 
    710      1.11  christos 	last_ifinit = now;
    711       1.9   thorpej 	ifinit_timer.tv_sec = now.tv_sec + (supplier
    712       1.9   thorpej 					    ? CHECK_ACT_INTERVAL
    713       1.9   thorpej 					    : CHECK_QUIET_INTERVAL);
    714       1.9   thorpej 
    715      1.16  christos 	/* mark all interfaces so we can get rid of those that disappear */
    716       1.9   thorpej 	for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
    717       1.9   thorpej 		ifp->int_state &= ~(IS_CHECKED | IS_DUP);
    718       1.9   thorpej 
    719       1.9   thorpej 	/* Fetch the interface list, without too many system calls
    720       1.9   thorpej 	 * since we do it repeatedly.
    721       1.9   thorpej 	 */
    722       1.9   thorpej 	mib[0] = CTL_NET;
    723       1.9   thorpej 	mib[1] = PF_ROUTE;
    724       1.9   thorpej 	mib[2] = 0;
    725       1.9   thorpej 	mib[3] = AF_INET;
    726       1.9   thorpej 	mib[4] = NET_RT_IFLIST;
    727       1.9   thorpej 	mib[5] = 0;
    728       1.9   thorpej 	for (;;) {
    729       1.9   thorpej 		if ((needed = sysctl_buf_size) != 0) {
    730       1.9   thorpej 			if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
    731       1.9   thorpej 				break;
    732      1.14   thorpej 			/* retry if the table grew */
    733       1.9   thorpej 			if (errno != ENOMEM && errno != EFAULT)
    734      1.14   thorpej 				BADERR(1, "ifinit: sysctl(RT_IFLIST)");
    735       1.9   thorpej 			free(sysctl_buf);
    736       1.9   thorpej 			needed = 0;
    737       1.9   thorpej 		}
    738       1.9   thorpej 		if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
    739      1.14   thorpej 			BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate");
    740      1.14   thorpej 		sysctl_buf = rtmalloc(sysctl_buf_size = needed,
    741      1.14   thorpej 				      "ifinit sysctl");
    742       1.9   thorpej 	}
    743       1.9   thorpej 
    744       1.9   thorpej 	ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
    745       1.9   thorpej 	for (ifam = (struct ifa_msghdr *)sysctl_buf;
    746       1.9   thorpej 	     ifam < ifam_lim;
    747       1.9   thorpej 	     ifam = ifam2) {
    748       1.9   thorpej 
    749       1.9   thorpej 		ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen);
    750       1.9   thorpej 
    751      1.18    bouyer #ifdef RTM_OIFINFO
    752      1.24  christos 		if (ifam->ifam_type == RTM_OIFINFO)
    753      1.24  christos 			continue;	/* just ignore compat message */
    754      1.18    bouyer #endif
    755       1.9   thorpej 		if (ifam->ifam_type == RTM_IFINFO) {
    756      1.26    dyoung 			const struct sockaddr_dl *sdl;
    757      1.11  christos 
    758      1.29    martin 			memcpy(&ifm, ifam, sizeof ifm);
    759       1.9   thorpej 			/* make prototype structure for the IP aliases
    760       1.9   thorpej 			 */
    761      1.12     lukem 			memset(&ifs0, 0, sizeof(ifs0));
    762       1.9   thorpej 			ifs0.int_rip_sock = -1;
    763      1.29    martin 			ifs0.int_index = ifm.ifm_index;
    764      1.29    martin 			ifs0.int_if_flags = ifm.ifm_flags;
    765       1.9   thorpej 			ifs0.int_state = IS_CHECKED;
    766      1.11  christos 			ifs0.int_query_time = NEVER;
    767       1.9   thorpej 			ifs0.int_act_time = now.tv_sec;
    768       1.9   thorpej 			ifs0.int_data.ts = now.tv_sec;
    769      1.29    martin 			ifs0.int_data.ipackets = ifm.ifm_data.ifi_ipackets;
    770      1.29    martin 			ifs0.int_data.ierrors = ifm.ifm_data.ifi_ierrors;
    771      1.29    martin 			ifs0.int_data.opackets = ifm.ifm_data.ifi_opackets;
    772      1.29    martin 			ifs0.int_data.oerrors = ifm.ifm_data.ifi_oerrors;
    773       1.9   thorpej #ifdef sgi
    774      1.29    martin 			ifs0.int_data.odrops = ifm.ifm_data.ifi_odrops;
    775       1.9   thorpej #endif
    776      1.29    martin 			sdl = (const struct sockaddr_dl *)
    777      1.29    martin 				((struct if_msghdr *)ifam + 1);
    778      1.26    dyoung 			/* NUL-termination by memset, above. */
    779      1.26    dyoung 			memcpy(ifs0.int_name, sdl->sdl_data,
    780      1.26    dyoung 				MIN(sizeof(ifs0.int_name) - 1, sdl->sdl_nlen));
    781       1.9   thorpej 			continue;
    782       1.9   thorpej 		}
    783       1.9   thorpej 		if (ifam->ifam_type != RTM_NEWADDR) {
    784      1.10  christos 			logbad(1,"ifinit: out of sync");
    785       1.9   thorpej 			continue;
    786       1.9   thorpej 		}
    787       1.9   thorpej 		rt_xaddrs(&info, (struct sockaddr *)(ifam+1),
    788       1.9   thorpej 			  (struct sockaddr *)ifam2,
    789       1.9   thorpej 			  ifam->ifam_addrs);
    790       1.9   thorpej 
    791      1.11  christos 		/* Prepare for the next address of this interface, which
    792      1.11  christos 		 * will be an alias.
    793      1.11  christos 		 * Do not output RIP or Router-Discovery packets via aliases.
    794      1.11  christos 		 */
    795      1.16  christos 		memcpy(&ifs, &ifs0, sizeof(ifs));
    796      1.14   thorpej 		ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC);
    797      1.11  christos 
    798       1.9   thorpej 		if (INFO_IFA(&info) == 0) {
    799      1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    800       1.9   thorpej 				if (!(prev_complaints & COMP_NOADDR))
    801      1.10  christos 					msglog("%s has no address",
    802      1.11  christos 					       ifs.int_name);
    803       1.9   thorpej 				complaints |= COMP_NOADDR;
    804       1.9   thorpej 			}
    805       1.9   thorpej 			continue;
    806       1.9   thorpej 		}
    807       1.9   thorpej 		if (INFO_IFA(&info)->sa_family != AF_INET) {
    808      1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    809       1.9   thorpej 				if (!(prev_complaints & COMP_NOT_INET))
    810      1.11  christos 					trace_act("%s: not AF_INET",
    811      1.11  christos 						  ifs.int_name);
    812       1.9   thorpej 				complaints |= COMP_NOT_INET;
    813       1.9   thorpej 			}
    814       1.9   thorpej 			continue;
    815       1.9   thorpej 		}
    816       1.9   thorpej 
    817       1.9   thorpej 		ifs.int_addr = S_ADDR(INFO_IFA(&info));
    818       1.9   thorpej 
    819      1.10  christos 		if (ntohl(ifs.int_addr)>>24 == 0
    820      1.10  christos 		    || ntohl(ifs.int_addr)>>24 == 0xff) {
    821      1.14   thorpej 			if (iff_up(ifs.int_if_flags)) {
    822      1.10  christos 				if (!(prev_complaints & COMP_BADADDR))
    823      1.10  christos 					msglog("%s has a bad address",
    824      1.11  christos 					       ifs.int_name);
    825      1.10  christos 				complaints |= COMP_BADADDR;
    826      1.10  christos 			}
    827      1.10  christos 			continue;
    828      1.10  christos 		}
    829      1.10  christos 
    830      1.11  christos 		if (ifs.int_if_flags & IFF_LOOPBACK) {
    831      1.11  christos 			ifs.int_state |= IS_PASSIVE | IS_NO_RIP | IS_NO_RDISC;
    832       1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    833      1.11  christos 			ifs.int_mask = HOST_MASK;
    834      1.11  christos 			ifs.int_ripv1_mask = HOST_MASK;
    835      1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    836      1.11  christos 			ifs.int_net = ntohl(ifs.int_dstaddr);
    837      1.11  christos 			if (!foundloopback) {
    838      1.11  christos 				foundloopback = 1;
    839      1.11  christos 				loopaddr = ifs.int_addr;
    840      1.14   thorpej 				loop_rts.rts_gate = loopaddr;
    841      1.14   thorpej 				loop_rts.rts_router = loopaddr;
    842       1.9   thorpej 			}
    843       1.9   thorpej 
    844       1.9   thorpej 		} else if (ifs.int_if_flags & IFF_POINTOPOINT) {
    845       1.9   thorpej 			if (INFO_BRD(&info) == 0
    846       1.9   thorpej 			    || INFO_BRD(&info)->sa_family != AF_INET) {
    847      1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    848       1.9   thorpej 					if (!(prev_complaints & COMP_NODST))
    849       1.9   thorpej 						msglog("%s has a bad"
    850       1.9   thorpej 						       " destination address",
    851      1.11  christos 						       ifs.int_name);
    852       1.9   thorpej 					complaints |= COMP_NODST;
    853       1.9   thorpej 				}
    854       1.9   thorpej 				continue;
    855       1.9   thorpej 			}
    856       1.9   thorpej 			ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
    857      1.10  christos 			if (ntohl(ifs.int_dstaddr)>>24 == 0
    858      1.10  christos 			    || ntohl(ifs.int_dstaddr)>>24 == 0xff) {
    859      1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    860      1.10  christos 					if (!(prev_complaints & COMP_NODST))
    861      1.10  christos 						msglog("%s has a bad"
    862      1.10  christos 						       " destination address",
    863      1.11  christos 						       ifs.int_name);
    864      1.10  christos 					complaints |= COMP_NODST;
    865      1.10  christos 				}
    866      1.10  christos 				continue;
    867      1.10  christos 			}
    868       1.9   thorpej 			ifs.int_mask = HOST_MASK;
    869       1.9   thorpej 			ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    870      1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_dstaddr);
    871       1.9   thorpej 			ifs.int_net = ntohl(ifs.int_dstaddr);
    872       1.9   thorpej 
    873      1.11  christos 		}  else {
    874      1.11  christos 			if (INFO_MASK(&info) == 0) {
    875      1.14   thorpej 				if (iff_up(ifs.int_if_flags)) {
    876      1.11  christos 					if (!(prev_complaints & COMP_NOMASK))
    877      1.11  christos 						msglog("%s has no netmask",
    878      1.11  christos 						       ifs.int_name);
    879      1.11  christos 					complaints |= COMP_NOMASK;
    880      1.11  christos 				}
    881      1.11  christos 				continue;
    882      1.11  christos 			}
    883       1.9   thorpej 			ifs.int_dstaddr = ifs.int_addr;
    884      1.11  christos 			ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info)));
    885      1.11  christos 			ifs.int_ripv1_mask = ifs.int_mask;
    886      1.11  christos 			ifs.int_std_mask = std_mask(ifs.int_addr);
    887      1.11  christos 			ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask;
    888      1.11  christos 			if (ifs.int_mask != ifs.int_std_mask)
    889      1.11  christos 				ifs.int_state |= IS_SUBNET;
    890      1.11  christos 
    891      1.11  christos 			if (ifs.int_if_flags & IFF_BROADCAST) {
    892      1.11  christos 				if (INFO_BRD(&info) == 0) {
    893      1.14   thorpej 					if (iff_up(ifs.int_if_flags)) {
    894      1.11  christos 					    if (!(prev_complaints
    895      1.11  christos 						  & COMP_NOBADR))
    896      1.11  christos 						msglog("%s has"
    897      1.11  christos 						       "no broadcast address",
    898      1.11  christos 						       ifs.int_name);
    899      1.11  christos 					    complaints |= COMP_NOBADR;
    900      1.11  christos 					}
    901      1.11  christos 					continue;
    902      1.11  christos 				}
    903      1.11  christos 				ifs.int_brdaddr = S_ADDR(INFO_BRD(&info));
    904       1.9   thorpej 			}
    905       1.9   thorpej 		}
    906       1.9   thorpej 		ifs.int_std_net = ifs.int_net & ifs.int_std_mask;
    907       1.9   thorpej 		ifs.int_std_addr = htonl(ifs.int_std_net);
    908       1.9   thorpej 
    909       1.9   thorpej 		/* Use a minimum metric of one.  Treat the interface metric
    910       1.9   thorpej 		 * (default 0) as an increment to the hop count of one.
    911       1.9   thorpej 		 *
    912       1.9   thorpej 		 * The metric obtained from the routing socket dump of
    913       1.9   thorpej 		 * interface addresses is wrong.  It is not set by the
    914       1.9   thorpej 		 * SIOCSIFMETRIC ioctl.
    915       1.9   thorpej 		 */
    916       1.9   thorpej #ifdef SIOCGIFMETRIC
    917      1.11  christos 		strncpy(ifr.ifr_name, ifs.int_name, sizeof(ifr.ifr_name));
    918       1.9   thorpej 		if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) {
    919       1.9   thorpej 			DBGERR(1, "ioctl(SIOCGIFMETRIC)");
    920       1.9   thorpej 			ifs.int_metric = 0;
    921       1.9   thorpej 		} else {
    922       1.9   thorpej 			ifs.int_metric = ifr.ifr_metric;
    923       1.9   thorpej 		}
    924       1.9   thorpej #else
    925       1.9   thorpej 		ifs.int_metric = ifam->ifam_metric;
    926       1.9   thorpej #endif
    927       1.9   thorpej 		if (ifs.int_metric > HOPCNT_INFINITY) {
    928       1.9   thorpej 			ifs.int_metric = 0;
    929       1.9   thorpej 			if (!(prev_complaints & COMP_BAD_METRIC)
    930      1.14   thorpej 			    && iff_up(ifs.int_if_flags)) {
    931       1.9   thorpej 				complaints |= COMP_BAD_METRIC;
    932       1.9   thorpej 				msglog("%s has a metric of %d",
    933      1.11  christos 				       ifs.int_name, ifs.int_metric);
    934       1.9   thorpej 			}
    935       1.9   thorpej 		}
    936       1.9   thorpej 
    937       1.9   thorpej 		/* See if this is a familiar interface.
    938       1.9   thorpej 		 * If so, stop worrying about it if it is the same.
    939       1.9   thorpej 		 * Start it over if it now is to somewhere else, as happens
    940       1.9   thorpej 		 * frequently with PPP and SLIP.
    941       1.9   thorpej 		 */
    942      1.11  christos 		ifp = ifwithname(ifs.int_name, ((ifs.int_state & IS_ALIAS)
    943      1.11  christos 						? ifs.int_addr
    944      1.11  christos 						: 0));
    945       1.9   thorpej 		if (ifp != 0) {
    946       1.9   thorpej 			ifp->int_state |= IS_CHECKED;
    947       1.9   thorpej 
    948       1.9   thorpej 			if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags)
    949       1.9   thorpej 				  & (IFF_BROADCAST
    950       1.9   thorpej 				     | IFF_LOOPBACK
    951       1.9   thorpej 				     | IFF_POINTOPOINT
    952       1.9   thorpej 				     | IFF_MULTICAST))
    953       1.9   thorpej 			    || 0 != ((ifp->int_state ^ ifs.int_state)
    954       1.9   thorpej 				     & IS_ALIAS)
    955       1.9   thorpej 			    || ifp->int_addr != ifs.int_addr
    956       1.9   thorpej 			    || ifp->int_brdaddr != ifs.int_brdaddr
    957       1.9   thorpej 			    || ifp->int_dstaddr != ifs.int_dstaddr
    958       1.9   thorpej 			    || ifp->int_mask != ifs.int_mask
    959       1.9   thorpej 			    || ifp->int_metric != ifs.int_metric) {
    960       1.9   thorpej 				/* Forget old information about
    961       1.9   thorpej 				 * a changed interface.
    962       1.9   thorpej 				 */
    963      1.11  christos 				trace_act("interface %s has changed",
    964       1.9   thorpej 					  ifp->int_name);
    965       1.9   thorpej 				ifdel(ifp);
    966       1.9   thorpej 				ifp = 0;
    967       1.9   thorpej 			}
    968       1.9   thorpej 		}
    969       1.9   thorpej 
    970       1.9   thorpej 		if (ifp != 0) {
    971      1.10  christos 			/* The primary representative of an alias worries
    972      1.10  christos 			 * about how things are working.
    973      1.10  christos 			 */
    974       1.9   thorpej 			if (ifp->int_state & IS_ALIAS)
    975       1.9   thorpej 				continue;
    976       1.9   thorpej 
    977       1.9   thorpej 			/* note interfaces that have been turned off
    978       1.9   thorpej 			 */
    979      1.14   thorpej 			if (!iff_up(ifs.int_if_flags)) {
    980      1.14   thorpej 				if (iff_up(ifp->int_if_flags)) {
    981       1.9   thorpej 					msglog("interface %s to %s turned off",
    982       1.9   thorpej 					       ifp->int_name,
    983      1.11  christos 					       naddr_ntoa(ifp->int_dstaddr));
    984       1.9   thorpej 					if_bad(ifp);
    985      1.14   thorpej 					ifp->int_if_flags &= ~IFF_UP;
    986      1.14   thorpej 				} else if (now.tv_sec>(ifp->int_data.ts
    987      1.14   thorpej 						       + CHECK_BAD_INTERVAL)) {
    988      1.14   thorpej 					trace_act("interface %s has been off"
    989      1.27  christos 						  " %lld seconds; forget it",
    990      1.14   thorpej 						  ifp->int_name,
    991      1.27  christos 						  (long long)now.tv_sec -
    992      1.27  christos 						  ifp->int_data.ts);
    993      1.14   thorpej 					ifdel(ifp);
    994      1.25  christos 					ifp = 0;
    995       1.9   thorpej 				}
    996       1.9   thorpej 				continue;
    997       1.9   thorpej 			}
    998       1.9   thorpej 			/* or that were off and are now ok */
    999      1.14   thorpej 			if (!iff_up(ifp->int_if_flags)) {
   1000      1.14   thorpej 				ifp->int_if_flags |= IFF_UP;
   1001       1.9   thorpej 				(void)if_ok(ifp, "");
   1002       1.9   thorpej 			}
   1003       1.9   thorpej 
   1004       1.9   thorpej 			/* If it has been long enough,
   1005       1.9   thorpej 			 * see if the interface is broken.
   1006       1.9   thorpej 			 */
   1007       1.9   thorpej 			if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL)
   1008       1.9   thorpej 				continue;
   1009       1.9   thorpej 
   1010       1.9   thorpej 			in = ifs.int_data.ipackets - ifp->int_data.ipackets;
   1011       1.9   thorpej 			ierr = ifs.int_data.ierrors - ifp->int_data.ierrors;
   1012       1.9   thorpej 			out = ifs.int_data.opackets - ifp->int_data.opackets;
   1013       1.9   thorpej 			oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
   1014       1.9   thorpej #ifdef sgi
   1015       1.9   thorpej 			/* Through at least IRIX 6.2, PPP and SLIP
   1016      1.11  christos 			 * count packets dropped by the filters.
   1017       1.9   thorpej 			 * But FDDI rings stuck non-operational count
   1018       1.9   thorpej 			 * dropped packets as they wait for improvement.
   1019       1.9   thorpej 			 */
   1020       1.9   thorpej 			if (!(ifp->int_if_flags & IFF_POINTOPOINT))
   1021       1.9   thorpej 				oerr += (ifs.int_data.odrops
   1022       1.9   thorpej 					 - ifp->int_data.odrops);
   1023       1.9   thorpej #endif
   1024       1.9   thorpej 			/* If the interface just awoke, restart the counters.
   1025       1.9   thorpej 			 */
   1026       1.9   thorpej 			if (ifp->int_data.ts == 0) {
   1027       1.9   thorpej 				ifp->int_data = ifs.int_data;
   1028       1.9   thorpej 				continue;
   1029       1.9   thorpej 			}
   1030       1.9   thorpej 			ifp->int_data = ifs.int_data;
   1031       1.9   thorpej 
   1032      1.16  christos 			/* Withhold judgment when the short error
   1033       1.9   thorpej 			 * counters wrap or the interface is reset.
   1034       1.9   thorpej 			 */
   1035       1.9   thorpej 			if (ierr < 0 || in < 0 || oerr < 0 || out < 0) {
   1036       1.9   thorpej 				LIM_SEC(ifinit_timer,
   1037       1.9   thorpej 					now.tv_sec+CHECK_BAD_INTERVAL);
   1038       1.9   thorpej 				continue;
   1039       1.9   thorpej 			}
   1040       1.9   thorpej 
   1041       1.9   thorpej 			/* Withhold judgement when there is no traffic
   1042       1.9   thorpej 			 */
   1043       1.9   thorpej 			if (in == 0 && out == 0 && ierr == 0 && oerr == 0)
   1044       1.9   thorpej 				continue;
   1045       1.9   thorpej 
   1046       1.9   thorpej 			/* It is bad if input or output is not working.
   1047       1.9   thorpej 			 * Require presistent problems before marking it dead.
   1048       1.9   thorpej 			 */
   1049       1.9   thorpej 			if ((in <= ierr && ierr > 0)
   1050       1.9   thorpej 			    || (out <= oerr && oerr > 0)) {
   1051       1.9   thorpej 				if (!(ifp->int_state & IS_SICK)) {
   1052       1.9   thorpej 					trace_act("interface %s to %s"
   1053       1.9   thorpej 						  " sick: in=%d ierr=%d"
   1054      1.11  christos 						  " out=%d oerr=%d",
   1055       1.9   thorpej 						  ifp->int_name,
   1056      1.11  christos 						  naddr_ntoa(ifp->int_dstaddr),
   1057       1.9   thorpej 						  in, ierr, out, oerr);
   1058       1.9   thorpej 					if_sick(ifp);
   1059       1.9   thorpej 					continue;
   1060       1.9   thorpej 				}
   1061       1.9   thorpej 				if (!(ifp->int_state & IS_BROKE)) {
   1062      1.11  christos 					msglog("interface %s to %s broken:"
   1063       1.9   thorpej 					       " in=%d ierr=%d out=%d oerr=%d",
   1064       1.9   thorpej 					       ifp->int_name,
   1065      1.11  christos 					       naddr_ntoa(ifp->int_dstaddr),
   1066       1.9   thorpej 					       in, ierr, out, oerr);
   1067       1.9   thorpej 					if_bad(ifp);
   1068       1.9   thorpej 				}
   1069       1.9   thorpej 				continue;
   1070       1.9   thorpej 			}
   1071       1.9   thorpej 
   1072       1.9   thorpej 			/* otherwise, it is active and healthy
   1073       1.9   thorpej 			 */
   1074       1.9   thorpej 			ifp->int_act_time = now.tv_sec;
   1075       1.9   thorpej 			(void)if_ok(ifp, "");
   1076       1.9   thorpej 			continue;
   1077       1.9   thorpej 		}
   1078       1.9   thorpej 
   1079       1.9   thorpej 		/* This is a new interface.
   1080       1.9   thorpej 		 * If it is dead, forget it.
   1081       1.9   thorpej 		 */
   1082      1.14   thorpej 		if (!iff_up(ifs.int_if_flags))
   1083       1.9   thorpej 			continue;
   1084       1.9   thorpej 
   1085      1.11  christos 		/* If it duplicates an existing interface,
   1086      1.11  christos 		 * complain about it, mark the other one
   1087      1.11  christos 		 * duplicated, and forget this one.
   1088       1.9   thorpej 		 */
   1089      1.11  christos 		ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask,
   1090      1.11  christos 				ifs.int_if_flags);
   1091      1.11  christos 		if (ifp != 0) {
   1092      1.11  christos 			/* Ignore duplicates of itself, caused by having
   1093      1.11  christos 			 * IP aliases on the same network.
   1094       1.9   thorpej 			 */
   1095      1.11  christos 			if (!strcmp(ifp->int_name, ifs.int_name))
   1096       1.9   thorpej 				continue;
   1097       1.9   thorpej 
   1098       1.9   thorpej 			if (!(prev_complaints & COMP_DUP)) {
   1099       1.9   thorpej 				complaints |= COMP_DUP;
   1100      1.11  christos 				msglog("%s (%s%s%s) is duplicated by"
   1101      1.11  christos 				       " %s (%s%s%s)",
   1102      1.11  christos 				       ifs.int_name,
   1103      1.11  christos 				       addrname(ifs.int_addr,ifs.int_mask,1),
   1104      1.11  christos 				       ((ifs.int_if_flags & IFF_POINTOPOINT)
   1105      1.11  christos 					? "-->" : ""),
   1106      1.11  christos 				       ((ifs.int_if_flags & IFF_POINTOPOINT)
   1107      1.11  christos 					? naddr_ntoa(ifs.int_dstaddr) : ""),
   1108      1.11  christos 				       ifp->int_name,
   1109      1.11  christos 				       addrname(ifp->int_addr,ifp->int_mask,1),
   1110      1.11  christos 				       ((ifp->int_if_flags & IFF_POINTOPOINT)
   1111      1.11  christos 					? "-->" : ""),
   1112      1.11  christos 				       ((ifp->int_if_flags & IFF_POINTOPOINT)
   1113      1.11  christos 					? naddr_ntoa(ifp->int_dstaddr) : ""));
   1114       1.9   thorpej 			}
   1115       1.9   thorpej 			ifp->int_state |= IS_DUP;
   1116      1.11  christos 			continue;
   1117      1.11  christos 		}
   1118      1.11  christos 
   1119      1.11  christos 		if (0 == (ifs.int_if_flags & (IFF_POINTOPOINT | IFF_BROADCAST))
   1120      1.11  christos 		    && !(ifs.int_state & IS_PASSIVE)) {
   1121      1.11  christos 			trace_act("%s is neither broadcast, point-to-point,"
   1122      1.11  christos 				  " nor loopback",
   1123      1.11  christos 				  ifs.int_name);
   1124      1.11  christos 			if (!(ifs.int_state & IFF_MULTICAST))
   1125      1.11  christos 				ifs.int_state |= IS_NO_RDISC;
   1126       1.9   thorpej 		}
   1127       1.9   thorpej 
   1128       1.9   thorpej 
   1129      1.11  christos 		/* It is new and ok.   Add it to the list of interfaces
   1130       1.9   thorpej 		 */
   1131      1.14   thorpej 		ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp");
   1132      1.16  christos 		memcpy(ifp, &ifs, sizeof(*ifp));
   1133      1.11  christos 		get_parms(ifp);
   1134      1.11  christos 		if_link(ifp);
   1135       1.9   thorpej 		trace_if("Add", ifp);
   1136       1.9   thorpej 
   1137      1.10  christos 		/* Notice likely bad netmask.
   1138      1.10  christos 		 */
   1139      1.10  christos 		if (!(prev_complaints & COMP_NETMASK)
   1140      1.11  christos 		    && !(ifp->int_if_flags & IFF_POINTOPOINT)
   1141      1.11  christos 		    && ifp->int_addr != RIP_DEFAULT) {
   1142      1.10  christos 			for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
   1143      1.10  christos 				if (ifp1->int_mask == ifp->int_mask)
   1144      1.10  christos 					continue;
   1145      1.10  christos 				if (ifp1->int_if_flags & IFF_POINTOPOINT)
   1146      1.10  christos 					continue;
   1147      1.11  christos 				if (ifp1->int_dstaddr == RIP_DEFAULT)
   1148      1.22  christos 					continue;
   1149      1.22  christos 				/* ignore aliases on the right network */
   1150      1.22  christos 				if (!strcmp(ifp->int_name, ifp1->int_name))
   1151      1.11  christos 					continue;
   1152      1.11  christos 				if (on_net(ifp->int_dstaddr,
   1153      1.10  christos 					   ifp1->int_net, ifp1->int_mask)
   1154      1.11  christos 				    || on_net(ifp1->int_dstaddr,
   1155      1.10  christos 					      ifp->int_net, ifp->int_mask)) {
   1156      1.10  christos 					msglog("possible netmask problem"
   1157      1.11  christos 					       " between %s:%s and %s:%s",
   1158      1.10  christos 					       ifp->int_name,
   1159      1.10  christos 					       addrname(htonl(ifp->int_net),
   1160      1.10  christos 							ifp->int_mask, 1),
   1161      1.10  christos 					       ifp1->int_name,
   1162      1.10  christos 					       addrname(htonl(ifp1->int_net),
   1163      1.10  christos 							ifp1->int_mask, 1));
   1164      1.10  christos 					complaints |= COMP_NETMASK;
   1165      1.10  christos 				}
   1166      1.10  christos 			}
   1167      1.10  christos 		}
   1168      1.10  christos 
   1169       1.9   thorpej 		if (!(ifp->int_state & IS_ALIAS)) {
   1170      1.11  christos 			/* Count the # of directly connected networks.
   1171      1.11  christos 			 */
   1172       1.9   thorpej 			if (!(ifp->int_if_flags & IFF_LOOPBACK))
   1173       1.9   thorpej 				tot_interfaces++;
   1174       1.9   thorpej 			if (!IS_RIP_OFF(ifp->int_state))
   1175       1.9   thorpej 				rip_interfaces++;
   1176      1.11  christos 
   1177      1.11  christos 			/* turn on router discovery and RIP If needed */
   1178      1.11  christos 			if_ok_rdisc(ifp);
   1179      1.11  christos 			rip_on(ifp);
   1180       1.9   thorpej 		}
   1181       1.9   thorpej 	}
   1182       1.9   thorpej 
   1183      1.11  christos 	/* If we are multi-homed and have at least two interfaces
   1184       1.9   thorpej 	 * listening to RIP, then output by default.
   1185       1.9   thorpej 	 */
   1186       1.9   thorpej 	if (!supplier_set && rip_interfaces > 1)
   1187       1.9   thorpej 		set_supplier();
   1188       1.9   thorpej 
   1189       1.9   thorpej 	/* If we are multi-homed, optionally advertise a route to
   1190       1.9   thorpej 	 * our main address.
   1191       1.9   thorpej 	 */
   1192      1.25  christos 	if ((advertise_mhome && ifp)
   1193       1.9   thorpej 	    || (tot_interfaces > 1
   1194       1.9   thorpej 		&& mhome
   1195       1.9   thorpej 		&& (ifp = ifwithaddr(myaddr, 0, 0)) != 0
   1196       1.9   thorpej 		&& foundloopback)) {
   1197       1.9   thorpej 		advertise_mhome = 1;
   1198       1.9   thorpej 		rt = rtget(myaddr, HOST_MASK);
   1199       1.9   thorpej 		if (rt != 0) {
   1200       1.9   thorpej 			if (rt->rt_ifp != ifp
   1201       1.9   thorpej 			    || rt->rt_router != loopaddr) {
   1202       1.9   thorpej 				rtdelete(rt);
   1203       1.9   thorpej 				rt = 0;
   1204       1.9   thorpej 			} else {
   1205      1.14   thorpej 				loop_rts.rts_ifp = ifp;
   1206      1.14   thorpej 				loop_rts.rts_metric = 0;
   1207      1.14   thorpej 				loop_rts.rts_time = rt->rt_time;
   1208       1.9   thorpej 				rtchange(rt, rt->rt_state | RS_MHOME,
   1209      1.14   thorpej 					 &loop_rts, 0);
   1210       1.9   thorpej 			}
   1211       1.9   thorpej 		}
   1212      1.14   thorpej 		if (rt == 0) {
   1213      1.14   thorpej 			loop_rts.rts_ifp = ifp;
   1214      1.14   thorpej 			loop_rts.rts_metric = 0;
   1215      1.14   thorpej 			rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts);
   1216      1.14   thorpej 		}
   1217       1.9   thorpej 	}
   1218       1.9   thorpej 
   1219       1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp1) {
   1220       1.9   thorpej 		ifp1 = ifp->int_next;	/* because we may delete it */
   1221       1.9   thorpej 
   1222       1.9   thorpej 		/* Forget any interfaces that have disappeared.
   1223       1.9   thorpej 		 */
   1224       1.9   thorpej 		if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
   1225      1.11  christos 			trace_act("interface %s has disappeared",
   1226       1.9   thorpej 				  ifp->int_name);
   1227       1.9   thorpej 			ifdel(ifp);
   1228       1.9   thorpej 			continue;
   1229       1.9   thorpej 		}
   1230       1.9   thorpej 
   1231       1.9   thorpej 		if ((ifp->int_state & IS_BROKE)
   1232       1.9   thorpej 		    && !(ifp->int_state & IS_PASSIVE))
   1233       1.9   thorpej 			LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
   1234       1.9   thorpej 
   1235       1.9   thorpej 		/* If we ever have a RIPv1 interface, assume we always will.
   1236       1.9   thorpej 		 * It might come back if it ever goes away.
   1237       1.9   thorpej 		 */
   1238      1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier)
   1239      1.10  christos 			have_ripv1_out = 1;
   1240      1.10  christos 		if (!(ifp->int_state & IS_NO_RIPV1_IN))
   1241      1.10  christos 			have_ripv1_in = 1;
   1242       1.9   thorpej 	}
   1243       1.9   thorpej 
   1244       1.9   thorpej 	for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
   1245       1.9   thorpej 		/* Ensure there is always a network route for interfaces,
   1246       1.9   thorpej 		 * after any dead interfaces have been deleted, which
   1247       1.9   thorpej 		 * might affect routes for point-to-point links.
   1248       1.9   thorpej 		 */
   1249      1.11  christos 		if (!addrouteforif(ifp))
   1250      1.11  christos 			continue;
   1251       1.9   thorpej 
   1252       1.9   thorpej 		/* Add routes to the local end of point-to-point interfaces
   1253       1.9   thorpej 		 * using loopback.
   1254       1.9   thorpej 		 */
   1255       1.9   thorpej 		if ((ifp->int_if_flags & IFF_POINTOPOINT)
   1256       1.9   thorpej 		    && !(ifp->int_state & IS_REMOTE)
   1257       1.9   thorpej 		    && foundloopback) {
   1258       1.9   thorpej 			/* Delete any routes to the network address through
   1259       1.9   thorpej 			 * foreign routers. Remove even static routes.
   1260       1.9   thorpej 			 */
   1261      1.14   thorpej 			del_static(ifp->int_addr, HOST_MASK, 0, 0);
   1262       1.9   thorpej 			rt = rtget(ifp->int_addr, HOST_MASK);
   1263       1.9   thorpej 			if (rt != 0 && rt->rt_router != loopaddr) {
   1264       1.9   thorpej 				rtdelete(rt);
   1265       1.9   thorpej 				rt = 0;
   1266       1.9   thorpej 			}
   1267       1.9   thorpej 			if (rt != 0) {
   1268       1.9   thorpej 				if (!(rt->rt_state & RS_LOCAL)
   1269       1.9   thorpej 				    || rt->rt_metric > ifp->int_metric) {
   1270       1.9   thorpej 					ifp1 = ifp;
   1271       1.9   thorpej 				} else {
   1272       1.9   thorpej 					ifp1 = rt->rt_ifp;
   1273       1.9   thorpej 				}
   1274      1.14   thorpej 				loop_rts.rts_ifp = ifp1;
   1275      1.14   thorpej 				loop_rts.rts_metric = 0;
   1276      1.14   thorpej 				loop_rts.rts_time = rt->rt_time;
   1277      1.14   thorpej 				rtchange(rt, ((rt->rt_state & ~RS_NET_SYN)
   1278      1.14   thorpej 					      | (RS_IF|RS_LOCAL)),
   1279      1.14   thorpej 					 &loop_rts, 0);
   1280       1.9   thorpej 			} else {
   1281      1.14   thorpej 				loop_rts.rts_ifp = ifp;
   1282      1.14   thorpej 				loop_rts.rts_metric = 0;
   1283       1.9   thorpej 				rtadd(ifp->int_addr, HOST_MASK,
   1284      1.14   thorpej 				      (RS_IF | RS_LOCAL), &loop_rts);
   1285       1.9   thorpej 			}
   1286       1.9   thorpej 		}
   1287       1.9   thorpej 	}
   1288       1.9   thorpej 
   1289       1.9   thorpej 	/* add the authority routes */
   1290       1.9   thorpej 	for (intnetp = intnets; intnetp!=0; intnetp = intnetp->intnet_next) {
   1291       1.9   thorpej 		rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask);
   1292       1.9   thorpej 		if (rt != 0
   1293       1.9   thorpej 		    && !(rt->rt_state & RS_NO_NET_SYN)
   1294       1.9   thorpej 		    && !(rt->rt_state & RS_NET_INT)) {
   1295       1.9   thorpej 			rtdelete(rt);
   1296       1.9   thorpej 			rt = 0;
   1297       1.9   thorpej 		}
   1298      1.14   thorpej 		if (rt == 0) {
   1299      1.14   thorpej 			loop_rts.rts_ifp = 0;
   1300      1.14   thorpej 			loop_rts.rts_metric = intnetp->intnet_metric-1;
   1301       1.9   thorpej 			rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
   1302      1.14   thorpej 			      RS_NET_SYN | RS_NET_INT, &loop_rts);
   1303      1.14   thorpej 		}
   1304       1.9   thorpej 	}
   1305       1.9   thorpej 
   1306       1.9   thorpej 	prev_complaints = complaints;
   1307       1.9   thorpej }
   1308       1.9   thorpej 
   1309       1.9   thorpej 
   1310       1.9   thorpej static void
   1311       1.9   thorpej check_net_syn(struct interface *ifp)
   1312       1.9   thorpej {
   1313       1.9   thorpej 	struct rt_entry *rt;
   1314      1.14   thorpej 	static struct rt_spare new;
   1315       1.9   thorpej 
   1316       1.9   thorpej 
   1317       1.9   thorpej 	/* Turn on the need to automatically synthesize a network route
   1318       1.9   thorpej 	 * for this interface only if we are running RIPv1 on some other
   1319       1.9   thorpej 	 * interface that is on a different class-A,B,or C network.
   1320       1.9   thorpej 	 */
   1321       1.9   thorpej 	if (have_ripv1_out || have_ripv1_in) {
   1322       1.9   thorpej 		ifp->int_state |= IS_NEED_NET_SYN;
   1323       1.9   thorpej 		rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
   1324       1.9   thorpej 		if (rt != 0
   1325       1.9   thorpej 		    && 0 == (rt->rt_state & RS_NO_NET_SYN)
   1326       1.9   thorpej 		    && (!(rt->rt_state & RS_NET_SYN)
   1327       1.9   thorpej 			|| rt->rt_metric > ifp->int_metric)) {
   1328       1.9   thorpej 			rtdelete(rt);
   1329       1.9   thorpej 			rt = 0;
   1330       1.9   thorpej 		}
   1331      1.14   thorpej 		if (rt == 0) {
   1332      1.14   thorpej 			new.rts_ifp = ifp;
   1333      1.14   thorpej 			new.rts_gate = ifp->int_addr;
   1334      1.14   thorpej 			new.rts_router = ifp->int_addr;
   1335      1.14   thorpej 			new.rts_metric = ifp->int_metric;
   1336       1.9   thorpej 			rtadd(ifp->int_std_addr, ifp->int_std_mask,
   1337      1.14   thorpej 			      RS_NET_SYN, &new);
   1338      1.14   thorpej 		}
   1339       1.9   thorpej 
   1340       1.9   thorpej 	} else {
   1341       1.9   thorpej 		ifp->int_state &= ~IS_NEED_NET_SYN;
   1342       1.9   thorpej 
   1343       1.9   thorpej 		rt = rtget(ifp->int_std_addr,
   1344       1.9   thorpej 			   ifp->int_std_mask);
   1345       1.9   thorpej 		if (rt != 0
   1346       1.9   thorpej 		    && (rt->rt_state & RS_NET_SYN)
   1347       1.9   thorpej 		    && rt->rt_ifp == ifp)
   1348       1.9   thorpej 			rtbad_sub(rt);
   1349       1.9   thorpej 	}
   1350       1.9   thorpej }
   1351       1.9   thorpej 
   1352       1.9   thorpej 
   1353       1.9   thorpej /* Add route for interface if not currently installed.
   1354       1.9   thorpej  * Create route to other end if a point-to-point link,
   1355       1.9   thorpej  * otherwise a route to this (sub)network.
   1356       1.9   thorpej  */
   1357      1.11  christos int					/* 0=bad interface */
   1358       1.9   thorpej addrouteforif(struct interface *ifp)
   1359       1.9   thorpej {
   1360       1.9   thorpej 	struct rt_entry *rt;
   1361      1.14   thorpej 	static struct rt_spare new;
   1362      1.14   thorpej 	naddr dst;
   1363       1.9   thorpej 
   1364       1.9   thorpej 
   1365       1.9   thorpej 	/* skip sick interfaces
   1366       1.9   thorpej 	 */
   1367       1.9   thorpej 	if (ifp->int_state & IS_BROKE)
   1368      1.11  christos 		return 0;
   1369       1.9   thorpej 
   1370       1.9   thorpej 	/* If the interface on a subnet, then install a RIPv1 route to
   1371       1.9   thorpej 	 * the network as well (unless it is sick).
   1372       1.9   thorpej 	 */
   1373       1.9   thorpej 	if (ifp->int_state & IS_SUBNET)
   1374       1.9   thorpej 		check_net_syn(ifp);
   1375       1.9   thorpej 
   1376      1.11  christos 	dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
   1377      1.11  christos 	       ? ifp->int_dstaddr
   1378      1.11  christos 	       : htonl(ifp->int_net));
   1379       1.9   thorpej 
   1380      1.14   thorpej 	new.rts_ifp = ifp;
   1381      1.14   thorpej 	new.rts_router = ifp->int_addr;
   1382      1.14   thorpej 	new.rts_gate = ifp->int_addr;
   1383      1.14   thorpej 	new.rts_metric = ifp->int_metric;
   1384      1.14   thorpej 	new.rts_time = now.tv_sec;
   1385      1.14   thorpej 
   1386      1.11  christos 	/* If we are going to send packets to the gateway,
   1387      1.11  christos 	 * it must be reachable using our physical interfaces
   1388      1.11  christos 	 */
   1389      1.11  christos 	if ((ifp->int_state & IS_REMOTE)
   1390      1.11  christos 	    && !(ifp->int_state & IS_EXTERNAL)
   1391      1.11  christos 	    && !check_remote(ifp))
   1392      1.11  christos 		return 0;
   1393       1.9   thorpej 
   1394       1.9   thorpej 	/* We are finished if the correct main interface route exists.
   1395       1.9   thorpej 	 * The right route must be for the right interface, not synthesized
   1396       1.9   thorpej 	 * from a subnet, be a "gateway" or not as appropriate, and so forth.
   1397       1.9   thorpej 	 */
   1398      1.14   thorpej 	del_static(dst, ifp->int_mask, 0, 0);
   1399       1.9   thorpej 	rt = rtget(dst, ifp->int_mask);
   1400       1.9   thorpej 	if (rt != 0) {
   1401       1.9   thorpej 		if ((rt->rt_ifp != ifp
   1402       1.9   thorpej 		     || rt->rt_router != ifp->int_addr)
   1403       1.9   thorpej 		    && (!(ifp->int_state & IS_DUP)
   1404       1.9   thorpej 			|| rt->rt_ifp == 0
   1405       1.9   thorpej 			|| (rt->rt_ifp->int_state & IS_BROKE))) {
   1406       1.9   thorpej 			rtdelete(rt);
   1407       1.9   thorpej 			rt = 0;
   1408       1.9   thorpej 		} else {
   1409       1.9   thorpej 			rtchange(rt, ((rt->rt_state | RS_IF)
   1410       1.9   thorpej 				      & ~(RS_NET_SYN | RS_LOCAL)),
   1411      1.14   thorpej 				 &new, 0);
   1412       1.9   thorpej 		}
   1413       1.9   thorpej 	}
   1414       1.9   thorpej 	if (rt == 0) {
   1415       1.9   thorpej 		if (ifp->int_transitions++ > 0)
   1416      1.11  christos 			trace_act("re-install interface %s",
   1417       1.9   thorpej 				  ifp->int_name);
   1418       1.9   thorpej 
   1419      1.14   thorpej 		rtadd(dst, ifp->int_mask, RS_IF, &new);
   1420       1.1       cgd 	}
   1421      1.11  christos 
   1422      1.11  christos 	return 1;
   1423       1.1       cgd }
   1424