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