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