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