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