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