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