1 /* $NetBSD: input.c,v 1.18 1996/09/24 16:24:14 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 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[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; 38 #elif defined(__NetBSD__) 39 static char rcsid[] = "$NetBSD: input.c,v 1.18 1996/09/24 16:24:14 christos Exp $"; 40 #endif 41 42 #include "defs.h" 43 44 static void input(struct sockaddr_in *, struct interface*, struct rip *, int); 45 static void input_route(struct interface *, naddr, 46 naddr, naddr, naddr, struct netinfo *); 47 48 49 /* process RIP input 50 */ 51 void 52 read_rip(int sock, 53 struct interface *ifp) 54 { 55 struct sockaddr_in from; 56 int fromlen, cc; 57 union pkt_buf inbuf; 58 59 60 for (;;) { 61 fromlen = sizeof(from); 62 cc = recvfrom(sock, &inbuf, sizeof(inbuf), 0, 63 (struct sockaddr*)&from, &fromlen); 64 if (cc <= 0) { 65 if (cc < 0 && errno != EWOULDBLOCK) 66 LOGERR("recvfrom(rip)"); 67 break; 68 } 69 if (fromlen != sizeof(struct sockaddr_in)) 70 logbad(1,"impossible recvfrom(rip) fromlen=%d", 71 fromlen); 72 73 input(&from, ifp, &inbuf.rip, cc); 74 } 75 } 76 77 78 /* Process a RIP packet 79 */ 80 static void 81 input(struct sockaddr_in *from, /* received from this IP address */ 82 struct interface *sifp, /* interface by which it arrived */ 83 struct rip *rip, 84 int size) 85 { 86 # define FROM_NADDR from->sin_addr.s_addr 87 static naddr use_auth, bad_len, bad_mask; 88 static naddr unk_router, bad_router, bad_nhop; 89 90 struct interface *aifp; /* interface if via 1 hop */ 91 struct rt_entry *rt; 92 struct netinfo *n, *lim; 93 struct interface *ifp1; 94 naddr gate, mask, v1_mask, dst, ddst_h; 95 int i; 96 97 aifp = iflookup(from->sin_addr.s_addr); 98 if (sifp == 0) 99 sifp = aifp; 100 101 if (sifp != 0) 102 sifp->int_state |= IS_ACTIVE; 103 104 trace_rip("Recv", "from", from, sifp, rip, size); 105 106 if (rip->rip_vers == 0) { 107 if (from->sin_addr.s_addr != bad_router) 108 msglog("RIP version 0, cmd %d, packet received" 109 " from %s", 110 rip->rip_cmd, naddr_ntoa(FROM_NADDR)); 111 bad_router = from->sin_addr.s_addr; 112 return; 113 } else if (rip->rip_vers > RIPv2) { 114 rip->rip_vers = RIPv2; 115 } 116 if (size > MAXPACKETSIZE) { 117 if (from->sin_addr.s_addr != bad_router) 118 msglog("packet at least %d bytes too long received" 119 " from %s", 120 size-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR)); 121 bad_router = from->sin_addr.s_addr; 122 return; 123 } 124 125 n = rip->rip_nets; 126 lim = (struct netinfo *)((char*)rip + size); 127 128 /* Notice authentication. 129 * As required by section 4.2 in RFC 1723, discard authenticated 130 * RIPv2 messages, but only if configured for that silliness. 131 * 132 * RIPv2 authentication is lame, since snooping on the wire makes 133 * its simple passwords evident. Also, why authenticate queries? 134 * Why should a RIPv2 implementation with authentication disabled 135 * not be able to listen to RIPv2 packets with authenication, while 136 * RIPv1 systems will listen? Crazy! 137 */ 138 if (!auth_ok 139 && rip->rip_vers == RIPv2 140 && n < lim && n->n_family == RIP_AF_AUTH) { 141 if (from->sin_addr.s_addr != use_auth) 142 msglog("RIPv2 message with authentication" 143 " from %s discarded", 144 naddr_ntoa(FROM_NADDR)); 145 use_auth = from->sin_addr.s_addr; 146 trace_pkt("discard authenticated RIPv2 message\n"); 147 return; 148 } 149 150 switch (rip->rip_cmd) { 151 case RIPCMD_REQUEST: 152 /* did the request come from a router? 153 */ 154 if (from->sin_port == htons(RIP_PORT)) { 155 /* yes, ignore it if RIP is off so that it does not 156 * depend on us. 157 */ 158 if (rip_sock < 0) { 159 trace_pkt("ignore request while RIP off\n"); 160 return; 161 } 162 163 /* Ignore the request if we talking to ourself 164 * (and not a remote gateway). 165 */ 166 if (ifwithaddr(FROM_NADDR, 0, 0) != 0) { 167 trace_pkt("discard our own RIP request\n"); 168 return; 169 } 170 } 171 172 /* According to RFC 1723, we should ignore unathenticated 173 * queries. That is too silly to bother with. Sheesh! 174 * Are forwarding tables supposed to be secret? When 175 * a bad guy can infer them with test traffic? 176 * Maybe on firewalls you'd care, but not enough to 177 * give up the diagnostic facilities of remote probing. 178 */ 179 180 if (n >= lim 181 || size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) { 182 if (from->sin_addr.s_addr != bad_len) 183 msglog("request of bad length (%d) from %s", 184 size, naddr_ntoa(FROM_NADDR)); 185 bad_len = from->sin_addr.s_addr; 186 } 187 for (; n < lim; n++) { 188 n->n_metric = ntohl(n->n_metric); 189 190 /* A single entry with family RIP_AF_UNSPEC and 191 * metric HOPCNT_INFINITY means "all routes". 192 * We respond to routers only if we are acting 193 * as a supplier, or to anyone other than a router 194 * (i.e. a query). 195 */ 196 if (n->n_family == RIP_AF_UNSPEC 197 && n->n_metric == HOPCNT_INFINITY 198 && n == rip->rip_nets 199 && n+1 == lim) { 200 if (from->sin_port != htons(RIP_PORT)) { 201 /* Answer a query from a utility 202 * program with all we know. 203 */ 204 supply(from, sifp, OUT_QUERY, 0, 205 rip->rip_vers); 206 return; 207 } 208 /* A router trying to prime its tables. 209 * Filter the answer in the about same way 210 * broadcasts are filtered. 211 * 212 * Only answer a router if we are a supplier 213 * to keep an unwary host that is just starting 214 * from picking us as a router. Respond with 215 * RIPv1 instead of RIPv2 if that is what we 216 * are broadcasting on the interface to keep 217 * the remote router from getting the wrong 218 * initial idea of the routes we send. 219 */ 220 if (!supplier 221 || aifp == 0 222 || (aifp->int_state & IS_PASSIVE) 223 || (aifp->int_state & IS_ALIAS) 224 || ((aifp->int_state & IS_NO_RIPV1_OUT) 225 && (aifp->int_state&IS_NO_RIPV2_OUT))) 226 return; 227 228 supply(from, aifp, OUT_UNICAST, 0, 229 (aifp->int_state&IS_NO_RIPV1_OUT) 230 ? RIPv2 : RIPv1); 231 return; 232 } 233 234 if (n->n_family != RIP_AF_INET) { 235 if (from->sin_addr.s_addr != bad_router) 236 msglog("request from %s" 237 " for unsupported (af %d) %s", 238 naddr_ntoa(FROM_NADDR), 239 ntohs(n->n_family), 240 naddr_ntoa(n->n_dst)); 241 bad_router = from->sin_addr.s_addr; 242 return; 243 } 244 245 dst = n->n_dst; 246 if (!check_dst(dst)) { 247 if (from->sin_addr.s_addr != bad_router) 248 msglog("bad queried destination" 249 " %s from %s", 250 naddr_ntoa(dst), 251 naddr_ntoa(FROM_NADDR)); 252 bad_router = from->sin_addr.s_addr; 253 return; 254 } 255 256 if (rip->rip_vers == RIPv1 257 || 0 == (mask = ntohl(n->n_mask)) 258 || 0 != (ntohl(dst) & ~mask)) 259 mask = ripv1_mask_host(dst,sifp); 260 261 rt = rtget(dst, mask); 262 if (!rt && dst != RIP_DEFAULT) 263 rt = rtfind(n->n_dst); 264 265 n->n_tag = 0; 266 n->n_nhop = 0; 267 if (rip->rip_vers == RIPv1) { 268 n->n_mask = 0; 269 } else { 270 n->n_mask = mask; 271 } 272 if (rt == 0) { 273 n->n_metric = HOPCNT_INFINITY; 274 } else { 275 n->n_metric = rt->rt_metric+1; 276 n->n_metric += (sifp!=0)?sifp->int_metric : 1; 277 if (n->n_metric > HOPCNT_INFINITY) 278 n->n_metric = HOPCNT_INFINITY; 279 if (rip->rip_vers != RIPv1) { 280 n->n_tag = rt->rt_tag; 281 if (sifp != 0 282 && on_net(rt->rt_gate, 283 sifp->int_net, 284 sifp->int_mask) 285 && rt->rt_gate != sifp->int_addr) 286 n->n_nhop = rt->rt_gate; 287 } 288 } 289 HTONL(n->n_metric); 290 } 291 /* Answer about specific routes. 292 * Only answer a router if we are a supplier 293 * to keep an unwary host that is just starting 294 * from picking us an a router. 295 */ 296 rip->rip_cmd = RIPCMD_RESPONSE; 297 rip->rip_res1 = 0; 298 if (rip->rip_vers != RIPv1) 299 rip->rip_vers = RIPv2; 300 if (from->sin_port != htons(RIP_PORT)) { 301 /* query */ 302 (void)output(OUT_QUERY, from, sifp, rip, size); 303 } else if (supplier) { 304 (void)output(OUT_UNICAST, from, sifp, rip, size); 305 } 306 return; 307 308 case RIPCMD_TRACEON: 309 case RIPCMD_TRACEOFF: 310 /* verify message came from a privileged port */ 311 if (ntohs(from->sin_port) > IPPORT_RESERVED) { 312 msglog("trace command from untrusted port on %s", 313 naddr_ntoa(FROM_NADDR)); 314 return; 315 } 316 if (aifp == 0) { 317 msglog("trace command from unknown router %s", 318 naddr_ntoa(FROM_NADDR)); 319 return; 320 } 321 if (rip->rip_cmd == RIPCMD_TRACEON) { 322 rip->rip_tracefile[size-4] = '\0'; 323 trace_on((char*)rip->rip_tracefile, 0); 324 } else { 325 trace_off("tracing turned off by %s\n", 326 naddr_ntoa(FROM_NADDR)); 327 } 328 return; 329 330 case RIPCMD_RESPONSE: 331 if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) { 332 if (from->sin_addr.s_addr != bad_len) 333 msglog("response of bad length (%d) from %s", 334 size, naddr_ntoa(FROM_NADDR)); 335 bad_len = from->sin_addr.s_addr; 336 } 337 338 /* verify message came from a router */ 339 if (from->sin_port != ntohs(RIP_PORT)) { 340 trace_pkt("discard RIP response from unknown port\n"); 341 return; 342 } 343 344 if (rip_sock < 0) { 345 trace_pkt("discard response while RIP off\n"); 346 return; 347 } 348 349 /* Are we talking to ourself or a remote gateway? 350 */ 351 ifp1 = ifwithaddr(FROM_NADDR, 0, 1); 352 if (ifp1) { 353 if (ifp1->int_state & IS_REMOTE) { 354 if (ifp1->int_state & IS_PASSIVE) { 355 msglog("bogus input from %s on" 356 " supposedly passive %s", 357 naddr_ntoa(FROM_NADDR), 358 ifp1->int_name); 359 } else { 360 ifp1->int_act_time = now.tv_sec; 361 if (if_ok(ifp1, "remote ")) 362 addrouteforif(ifp1); 363 } 364 } else { 365 trace_pkt("discard our own RIP response\n"); 366 } 367 return; 368 } 369 370 /* Check the router from which message originated. We accept 371 * routing packets from routers directly connected via 372 * broadcast or point-to-point networks, and from 373 * those listed in /etc/gateways. 374 */ 375 if (!aifp) { 376 if (from->sin_addr.s_addr != unk_router) 377 msglog("discard packet from unknown router %s" 378 " or via unidentified interface", 379 naddr_ntoa(FROM_NADDR)); 380 unk_router = from->sin_addr.s_addr; 381 return; 382 } 383 if (aifp->int_state & IS_PASSIVE) { 384 trace_act("discard packet from %s" 385 " via passive interface %s\n", 386 naddr_ntoa(FROM_NADDR), 387 aifp->int_name); 388 return; 389 } 390 391 /* Check required version 392 */ 393 if (((aifp->int_state & IS_NO_RIPV1_IN) 394 && rip->rip_vers == RIPv1) 395 || ((aifp->int_state & IS_NO_RIPV2_IN) 396 && rip->rip_vers != RIPv1)) { 397 trace_pkt("discard RIPv%d response\n", 398 rip->rip_vers); 399 return; 400 } 401 402 /* Ignore routes via dead interface. 403 */ 404 if (aifp->int_state & IS_BROKE) { 405 trace_pkt("discard response via broken interface %s\n", 406 aifp->int_name); 407 return; 408 } 409 410 /* Authenticate the packet if we have a secret. 411 */ 412 if (aifp->int_passwd[0] != '\0') { 413 if (n >= lim 414 || n->n_family != RIP_AF_AUTH 415 || ((struct netauth*)n)->a_type != RIP_AUTH_PW) { 416 if (from->sin_addr.s_addr != use_auth) 417 msglog("missing password from %s", 418 naddr_ntoa(FROM_NADDR)); 419 use_auth = from->sin_addr.s_addr; 420 return; 421 422 } else if (0 != bcmp(((struct netauth*)n)->au.au_pw, 423 aifp->int_passwd, 424 sizeof(aifp->int_passwd))) { 425 if (from->sin_addr.s_addr != use_auth) 426 msglog("bad password from %s", 427 naddr_ntoa(FROM_NADDR)); 428 use_auth = from->sin_addr.s_addr; 429 return; 430 } 431 } 432 433 auth_ok: 434 435 for (; n < lim; n++) { 436 if (n->n_family == RIP_AF_AUTH) 437 continue; 438 439 NTOHL(n->n_metric); 440 dst = n->n_dst; 441 if (n->n_family != RIP_AF_INET 442 && (n->n_family != RIP_AF_UNSPEC 443 || dst != RIP_DEFAULT)) { 444 if (from->sin_addr.s_addr != bad_router) 445 msglog("route from %s to unsupported" 446 " address family %d," 447 " destination %s", 448 naddr_ntoa(FROM_NADDR), 449 n->n_family, 450 naddr_ntoa(dst)); 451 bad_router = from->sin_addr.s_addr; 452 continue; 453 } 454 if (!check_dst(dst)) { 455 if (from->sin_addr.s_addr != bad_router) 456 msglog("bad destination %s from %s", 457 naddr_ntoa(dst), 458 naddr_ntoa(FROM_NADDR)); 459 bad_router = from->sin_addr.s_addr; 460 return; 461 } 462 if (n->n_metric == 0 463 || n->n_metric > HOPCNT_INFINITY) { 464 if (from->sin_addr.s_addr != bad_router) 465 msglog("bad metric %d from %s" 466 " for destination %s", 467 n->n_metric, 468 naddr_ntoa(FROM_NADDR), 469 naddr_ntoa(dst)); 470 bad_router = from->sin_addr.s_addr; 471 return; 472 } 473 474 /* Notice the next-hop. 475 */ 476 gate = from->sin_addr.s_addr; 477 if (n->n_nhop != 0) { 478 if (rip->rip_vers == RIPv2) { 479 n->n_nhop = 0; 480 } else { 481 /* Use it only if it is valid. */ 482 if (on_net(n->n_nhop, 483 aifp->int_net, aifp->int_mask) 484 && check_dst(n->n_nhop)) { 485 gate = n->n_nhop; 486 } else { 487 if (bad_nhop != from->sin_addr.s_addr) 488 msglog("router %s to %s has" 489 " bad next hop %s", 490 naddr_ntoa(FROM_NADDR), 491 naddr_ntoa(dst), 492 naddr_ntoa(n->n_nhop)); 493 bad_nhop = from->sin_addr.s_addr; 494 n->n_nhop = 0; 495 } 496 } 497 } 498 499 if (rip->rip_vers == RIPv1 500 || 0 == (mask = ntohl(n->n_mask))) { 501 mask = ripv1_mask_host(dst,aifp); 502 } else if ((ntohl(dst) & ~mask) != 0) { 503 if (bad_mask != from->sin_addr.s_addr) { 504 msglog("router %s sent bad netmask" 505 " %#x with %s", 506 naddr_ntoa(FROM_NADDR), 507 mask, 508 naddr_ntoa(dst)); 509 bad_mask = from->sin_addr.s_addr; 510 } 511 continue; 512 } 513 if (rip->rip_vers == RIPv1) 514 n->n_tag = 0; 515 516 /* Adjust metric according to incoming interface.. 517 */ 518 n->n_metric += aifp->int_metric; 519 if (n->n_metric > HOPCNT_INFINITY) 520 n->n_metric = HOPCNT_INFINITY; 521 522 /* Recognize and ignore a default route we faked 523 * which is being sent back to us by a machine with 524 * broken split-horizon. 525 * Be a little more paranoid than that, and reject 526 * default routes with the same metric we advertised. 527 */ 528 if (aifp->int_d_metric != 0 529 && dst == RIP_DEFAULT 530 && n->n_metric >= aifp->int_d_metric) 531 continue; 532 533 /* We can receive aggregated RIPv2 routes that must 534 * be broken down before they are transmitted by 535 * RIPv1 via an interface on a subnet. 536 * We might also receive the same routes aggregated 537 * via other RIPv2 interfaces. 538 * This could cause duplicate routes to be sent on 539 * the RIPv1 interfaces. "Longest matching variable 540 * length netmasks" lets RIPv2 listeners understand, 541 * but breaking down the aggregated routes for RIPv1 542 * listeners can produce duplicate routes. 543 * 544 * Breaking down aggregated routes here bloats 545 * the daemon table, but does not hurt the kernel 546 * table, since routes are always aggregated for 547 * the kernel. 548 * 549 * Notice that this does not break down network 550 * routes corresponding to subnets. This is part 551 * of the defense against RS_NET_SYN. 552 */ 553 if (have_ripv1_out 554 && (v1_mask = ripv1_mask_net(dst,0)) > mask 555 && (((rt = rtget(dst,mask)) == 0 556 || !(rt->rt_state & RS_NET_SYN)))) { 557 ddst_h = v1_mask & -v1_mask; 558 i = (v1_mask & ~mask)/ddst_h; 559 if (i >= 511) { 560 /* Punt if we would have to generate 561 * an unreasonable number of routes. 562 */ 563 #ifdef DEBUG 564 msglog("accept %s from %s as 1" 565 " instead of %d routes", 566 addrname(dst,mask,0), 567 naddr_ntoa(FROM_NADDR), 568 i+1); 569 #endif 570 i = 0; 571 } else { 572 mask = v1_mask; 573 } 574 } else { 575 i = 0; 576 } 577 578 for (;;) { 579 input_route(aifp, FROM_NADDR, 580 dst, mask, gate, n); 581 if (i-- == 0) 582 break; 583 dst = htonl(ntohl(dst) + ddst_h); 584 } 585 } 586 break; 587 } 588 } 589 590 591 /* Process a single input route. 592 */ 593 static void 594 input_route(struct interface *ifp, 595 naddr from, 596 naddr dst, 597 naddr mask, 598 naddr gate, 599 struct netinfo *n) 600 { 601 int i; 602 struct rt_entry *rt; 603 struct rt_spare *rts, *rts0; 604 struct interface *ifp1; 605 time_t new_time; 606 607 608 /* See if the other guy is telling us to send our packets to him. 609 * Sometimes network routes arrive over a point-to-point link for 610 * the network containing the address(es) of the link. 611 * 612 * If our interface is broken, switch to using the other guy. 613 */ 614 ifp1 = ifwithaddr(dst, 1, 1); 615 if (ifp1 != 0 616 && !(ifp1->int_state & IS_BROKE)) 617 return; 618 619 /* Look for the route in our table. 620 */ 621 rt = rtget(dst, mask); 622 623 /* Consider adding the route if we do not already have it. 624 */ 625 if (rt == 0) { 626 /* Ignore unknown routes being poisoned. 627 */ 628 if (n->n_metric == HOPCNT_INFINITY) 629 return; 630 631 /* Ignore the route if it points to us */ 632 if (n->n_nhop != 0 633 && 0 != ifwithaddr(n->n_nhop, 1, 0)) 634 return; 635 636 /* If something has not gone crazy and tried to fill 637 * our memory, accept the new route. 638 */ 639 if (total_routes < MAX_ROUTES) 640 rtadd(dst, mask, gate, from, n->n_metric, 641 n->n_tag, 0, ifp); 642 return; 643 } 644 645 /* We already know about the route. Consider this update. 646 * 647 * If (rt->rt_state & RS_NET_SYN), then this route 648 * is the same as a network route we have inferred 649 * for subnets we know, in order to tell RIPv1 routers 650 * about the subnets. 651 * 652 * It is impossible to tell if the route is coming 653 * from a distant RIPv2 router with the standard 654 * netmask because that router knows about the entire 655 * network, or if it is a round-about echo of a 656 * synthetic, RIPv1 network route of our own. 657 * The worst is that both kinds of routes might be 658 * received, and the bad one might have the smaller 659 * metric. Partly solve this problem by never 660 * aggregating into such a route. Also keep it 661 * around as long as the interface exists. 662 */ 663 664 rts0 = rt->rt_spares; 665 for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) { 666 if (rts->rts_router == from) 667 break; 668 /* Note the worst slot to reuse, 669 * other than the current slot. 670 */ 671 if (rts0 == rt->rt_spares 672 || BETTER_LINK(rt, rts0, rts)) 673 rts0 = rts; 674 } 675 if (i != 0) { 676 /* Found the router 677 */ 678 int old_metric = rts->rts_metric; 679 680 /* Keep poisoned routes around only long enough to pass 681 * the poison on. Get a new timestamp for good routes. 682 */ 683 new_time =((old_metric == HOPCNT_INFINITY) 684 ? rts->rts_time 685 : now.tv_sec); 686 687 /* If this is an update for the router we currently prefer, 688 * then note it. 689 */ 690 if (i == NUM_SPARES) { 691 rtchange(rt,rt->rt_state, gate,rt->rt_router, 692 n->n_metric, n->n_tag, ifp, new_time, 0); 693 /* If the route got worse, check for something better. 694 */ 695 if (n->n_metric > old_metric) 696 rtswitch(rt, 0); 697 return; 698 } 699 700 /* This is an update for a spare route. 701 * Finished if the route is unchanged. 702 */ 703 if (rts->rts_gate == gate 704 && old_metric == n->n_metric 705 && rts->rts_tag == n->n_tag) { 706 rts->rts_time = new_time; 707 return; 708 } 709 710 } else { 711 /* The update is for a route we know about, 712 * but not from a familiar router. 713 * 714 * Ignore the route if it points to us. 715 */ 716 if (n->n_nhop != 0 717 && 0 != ifwithaddr(n->n_nhop, 1, 0)) 718 return; 719 720 rts = rts0; 721 722 /* Save the route as a spare only if it has 723 * a better metric than our worst spare. 724 * This also ignores poisoned routes (those 725 * received with metric HOPCNT_INFINITY). 726 */ 727 if (n->n_metric >= rts->rts_metric) 728 return; 729 730 new_time = now.tv_sec; 731 } 732 733 trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time); 734 735 rts->rts_gate = gate; 736 rts->rts_router = from; 737 rts->rts_metric = n->n_metric; 738 rts->rts_tag = n->n_tag; 739 rts->rts_time = new_time; 740 rts->rts_ifp = ifp; 741 742 /* try to switch to a better route */ 743 rtswitch(rt, rts); 744 } 745