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