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