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