input.c revision 1.20 1 /* $NetBSD: input.c,v 1.20 1997/09/15 10:38:14 lukem 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 #include <sys/cdefs.h>
40 __RCSID("$NetBSD: input.c,v 1.20 1997/09/15 10:38:14 lukem Exp $");
41 #endif
42
43 #include "defs.h"
44
45 static void input(struct sockaddr_in *, struct interface *, struct interface *,
46 struct rip *, int);
47 static void input_route(struct interface *, naddr,
48 naddr, naddr, naddr, struct netinfo *);
49 static int ck_passwd(struct interface *, struct rip *, void *,
50 naddr, struct msg_limit *);
51
52
53 /* process RIP input
54 */
55 void
56 read_rip(int sock,
57 struct interface *sifp)
58 {
59 struct sockaddr_in from;
60 struct interface *aifp;
61 int fromlen, cc;
62 #ifdef USE_PASSIFNAME
63 static struct msg_limit bad_name;
64 struct {
65 char ifname[IFNAMSIZ];
66 union pkt_buf pbuf;
67 } inbuf;
68 #else
69 struct {
70 union pkt_buf pbuf;
71 } inbuf;
72 #endif
73
74
75 for (;;) {
76 fromlen = sizeof(from);
77 cc = recvfrom(sock, &inbuf, sizeof(inbuf), 0,
78 (struct sockaddr*)&from, &fromlen);
79 if (cc <= 0) {
80 if (cc < 0 && errno != EWOULDBLOCK)
81 LOGERR("recvfrom(rip)");
82 break;
83 }
84 if (fromlen != sizeof(struct sockaddr_in))
85 logbad(1,"impossible recvfrom(rip) fromlen=%d",
86 fromlen);
87
88 /* aifp is the "authenticated" interface via which the packet
89 * arrived. In fact, it is only the interface on which
90 * the packet should have arrived based on is source
91 * address.
92 * sifp is interface associated with the socket through which
93 * the packet was received.
94 */
95 #ifdef USE_PASSIFNAME
96 if ((cc -= sizeof(inbuf.ifname)) < 0)
97 logbad(0,"missing USE_PASSIFNAME; only %d bytes",
98 cc+sizeof(inbuf.ifname));
99
100 /* check the remote interfaces first */
101 for (aifp = remote_if; aifp; aifp = aifp->int_rlink) {
102 if (aifp->int_addr == from.sin_addr.s_addr)
103 break;
104 }
105 if (aifp == 0) {
106 aifp = ifwithname(inbuf.ifname, 0);
107 if (aifp == 0) {
108 msglim(&bad_name, from.sin_addr.s_addr,
109 "impossible interface name %.*s",
110 IFNAMSIZ, inbuf.ifname);
111 } else if (((aifp->int_if_flags & IFF_POINTOPOINT)
112 && aifp->int_dstaddr!=from.sin_addr.s_addr)
113 || (!(aifp->int_if_flags & IFF_POINTOPOINT)
114 && !on_net(from.sin_addr.s_addr,
115 aifp->int_net,
116 aifp->int_mask))) {
117 /* If it came via the wrong interface, do not
118 * trust it.
119 */
120 aifp = 0;
121 }
122 }
123 #else
124 aifp = iflookup(from.sin_addr.s_addr);
125 #endif
126 if (sifp == 0)
127 sifp = aifp;
128
129 input(&from, sifp, aifp, &inbuf.pbuf.rip, cc);
130 }
131 }
132
133
134 /* Process a RIP packet
135 */
136 static void
137 input(struct sockaddr_in *from, /* received from this IP address */
138 struct interface *sifp, /* interface of incoming socket */
139 struct interface *aifp, /* "authenticated" interface */
140 struct rip *rip,
141 int cc)
142 {
143 # define FROM_NADDR from->sin_addr.s_addr
144 static struct msg_limit use_auth, bad_len, bad_mask;
145 static struct msg_limit unk_router, bad_router, bad_nhop;
146
147 struct rt_entry *rt;
148 struct netinfo *n, *lim;
149 struct interface *ifp1;
150 naddr gate, mask, v1_mask, dst, ddst_h = 0;
151 struct auth *ap;
152 int i;
153
154 /* Notice when we hear from a remote gateway
155 */
156 if (aifp != 0
157 && (aifp->int_state & IS_REMOTE))
158 aifp->int_act_time = now.tv_sec;
159
160 trace_rip("Recv", "from", from, sifp, rip, cc);
161
162 if (rip->rip_vers == 0) {
163 msglim(&bad_router, FROM_NADDR,
164 "RIP version 0, cmd %d, packet received from %s",
165 rip->rip_cmd, naddr_ntoa(FROM_NADDR));
166 return;
167 } else if (rip->rip_vers > RIPv2) {
168 rip->rip_vers = RIPv2;
169 }
170 if (cc > OVER_MAXPACKETSIZE) {
171 msglim(&bad_router, FROM_NADDR,
172 "packet at least %d bytes too long received from %s",
173 cc-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
174 return;
175 }
176
177 n = rip->rip_nets;
178 lim = (struct netinfo *)((char*)rip + cc);
179
180 /* Notice authentication.
181 * As required by section 4.2 in RFC 1723, discard authenticated
182 * RIPv2 messages, but only if configured for that silliness.
183 *
184 * RIPv2 authentication is lame. Why authenticate queries?
185 * Why should a RIPv2 implementation with authentication disabled
186 * not be able to listen to RIPv2 packets with authenication, while
187 * RIPv1 systems will listen? Crazy!
188 */
189 if (!auth_ok
190 && rip->rip_vers == RIPv2
191 && n < lim && n->n_family == RIP_AF_AUTH) {
192 msglim(&use_auth, FROM_NADDR,
193 "RIPv2 message with authentication from %s discarded",
194 naddr_ntoa(FROM_NADDR));
195 return;
196 }
197
198 switch (rip->rip_cmd) {
199 case RIPCMD_REQUEST:
200 /* For mere requests, be a little sloppy about the source
201 */
202 if (aifp == 0)
203 aifp = sifp;
204
205 /* Are we talking to ourself or a remote gateway?
206 */
207 ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
208 if (ifp1) {
209 if (ifp1->int_state & IS_REMOTE) {
210 /* remote gateway */
211 aifp = ifp1;
212 if (check_remote(aifp)) {
213 aifp->int_act_time = now.tv_sec;
214 (void)if_ok(aifp, "remote ");
215 }
216 } else if (from->sin_port == htons(RIP_PORT)) {
217 trace_pkt(" discard our own RIP request");
218 return;
219 }
220 }
221
222 /* did the request come from a router?
223 */
224 if (from->sin_port == htons(RIP_PORT)) {
225 /* yes, ignore the request if RIP is off so that
226 * the router does not depend on us.
227 */
228 if (rip_sock < 0
229 || (aifp != 0
230 && IS_RIP_OUT_OFF(aifp->int_state))) {
231 trace_pkt(" discard request while RIP off");
232 return;
233 }
234 }
235
236 /* According to RFC 1723, we should ignore unathenticated
237 * queries. That is too silly to bother with. Sheesh!
238 * Are forwarding tables supposed to be secret, when
239 * a bad guy can infer them with test traffic? When RIP
240 * is still the most common router-discovery protocol
241 * and so hosts need to send queries that will be answered?
242 * What about `rtquery`?
243 * Maybe on firewalls you'd care, but not enough to
244 * give up the diagnostic facilities of remote probing.
245 */
246
247 if (n >= lim) {
248 msglim(&bad_len, FROM_NADDR, "empty request from %s",
249 naddr_ntoa(FROM_NADDR));
250 return;
251 }
252 if (cc%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
253 msglim(&bad_len, FROM_NADDR,
254 "request of bad length (%d) from %s",
255 cc, naddr_ntoa(FROM_NADDR));
256 }
257
258 if (rip->rip_vers == RIPv2
259 && (aifp == 0 || (aifp->int_state & IS_NO_RIPV1_OUT))) {
260 v12buf.buf->rip_vers = RIPv2;
261 /* If we have a secret but it is a cleartext secret,
262 * do not disclose our secret unless the other guy
263 * already knows it.
264 */
265 ap = find_auth(aifp);
266 if (ap != 0 && ap->type == RIP_AUTH_PW
267 && n->n_family == RIP_AF_AUTH
268 && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth))
269 ap = 0;
270 } else {
271 v12buf.buf->rip_vers = RIPv1;
272 ap = 0;
273 }
274 clr_ws_buf(&v12buf, ap);
275
276 do {
277 NTOHL(n->n_metric);
278
279 /* A single entry with family RIP_AF_UNSPEC and
280 * metric HOPCNT_INFINITY means "all routes".
281 * We respond to routers only if we are acting
282 * as a supplier, or to anyone other than a router
283 * (i.e. a query).
284 */
285 if (n->n_family == RIP_AF_UNSPEC
286 && n->n_metric == HOPCNT_INFINITY) {
287 if (from->sin_port != htons(RIP_PORT)) {
288 /* Answer a query from a utility
289 * program with all we know.
290 */
291 supply(from, aifp, OUT_QUERY, 0,
292 rip->rip_vers, ap != 0);
293 return;
294 }
295
296 /* A router trying to prime its tables.
297 * Filter the answer in the about same way
298 * broadcasts are filtered.
299 *
300 * Only answer a router if we are a supplier
301 * to keep an unwary host that is just starting
302 * from picking us as a router. Respond with
303 * RIPv1 instead of RIPv2 if that is what we
304 * are broadcasting on the interface to keep
305 * the remote router from getting the wrong
306 * initial idea of the routes we send.
307 */
308 if (aifp == 0) {
309 trace_pkt("ignore distant router");
310 return;
311 }
312 if (!supplier
313 || IS_RIP_OFF(aifp->int_state)) {
314 trace_pkt("ignore; not supplying");
315 return;
316 }
317
318 supply(from, aifp, OUT_UNICAST, 0,
319 (aifp->int_state&IS_NO_RIPV1_OUT)
320 ? RIPv2 : RIPv1,
321 ap != 0);
322 return;
323 }
324
325 /* Ignore authentication */
326 if (n->n_family == RIP_AF_AUTH)
327 continue;
328
329 if (n->n_family != RIP_AF_INET) {
330 msglim(&bad_router, FROM_NADDR,
331 "request from %s for unsupported (af"
332 " %d) %s",
333 naddr_ntoa(FROM_NADDR),
334 ntohs(n->n_family),
335 naddr_ntoa(n->n_dst));
336 return;
337 }
338
339 /* We are being asked about a specific destination.
340 */
341 dst = n->n_dst;
342 if (!check_dst(dst)) {
343 msglim(&bad_router, FROM_NADDR,
344 "bad queried destination %s from %s",
345 naddr_ntoa(dst),
346 naddr_ntoa(FROM_NADDR));
347 return;
348 }
349
350 /* decide what mask was intended */
351 if (rip->rip_vers == RIPv1
352 || 0 == (mask = ntohl(n->n_mask))
353 || 0 != (ntohl(dst) & ~mask))
354 mask = ripv1_mask_host(dst, aifp);
355
356 /* try to find the answer */
357 rt = rtget(dst, mask);
358 if (!rt && dst != RIP_DEFAULT)
359 rt = rtfind(n->n_dst);
360
361 if (v12buf.buf->rip_vers != RIPv1)
362 v12buf.n->n_mask = mask;
363 if (rt == 0) {
364 /* we do not have the answer */
365 v12buf.n->n_metric = HOPCNT_INFINITY;
366 } else {
367 /* we have the answer, so compute the
368 * right metric and next hop.
369 */
370 v12buf.n->n_family = RIP_AF_INET;
371 v12buf.n->n_dst = dst;
372 v12buf.n->n_metric = (rt->rt_metric+1
373 + ((aifp!=0)
374 ? aifp->int_metric
375 : 1));
376 if (v12buf.n->n_metric > HOPCNT_INFINITY)
377 v12buf.n->n_metric = HOPCNT_INFINITY;
378 if (v12buf.buf->rip_vers != RIPv1) {
379 v12buf.n->n_tag = rt->rt_tag;
380 v12buf.n->n_mask = mask;
381 if (aifp != 0
382 && on_net(rt->rt_gate,
383 aifp->int_net,
384 aifp->int_mask)
385 && rt->rt_gate != aifp->int_addr)
386 v12buf.n->n_nhop = rt->rt_gate;
387 }
388 }
389 HTONL(v12buf.n->n_metric);
390
391 /* Stop paying attention if we fill the output buffer.
392 */
393 if (++v12buf.n >= v12buf.lim)
394 break;
395 } while (++n < lim);
396
397 /* Send the answer about specific routes.
398 */
399 if (ap != 0 && ap->type == RIP_AUTH_MD5)
400 end_md5_auth(&v12buf, ap);
401
402 if (from->sin_port != htons(RIP_PORT)) {
403 /* query */
404 (void)output(OUT_QUERY, from, aifp,
405 v12buf.buf,
406 ((char *)v12buf.n - (char*)v12buf.buf));
407 } else if (supplier) {
408 (void)output(OUT_UNICAST, from, aifp,
409 v12buf.buf,
410 ((char *)v12buf.n - (char*)v12buf.buf));
411 } else {
412 /* Only answer a router if we are a supplier
413 * to keep an unwary host that is just starting
414 * from picking us an a router.
415 */
416 ;
417 }
418 return;
419
420 case RIPCMD_TRACEON:
421 case RIPCMD_TRACEOFF:
422 /* verify message came from a privileged port */
423 if (ntohs(from->sin_port) > IPPORT_RESERVED) {
424 msglog("trace command from untrusted port on %s",
425 naddr_ntoa(FROM_NADDR));
426 return;
427 }
428 if (aifp == 0) {
429 msglog("trace command from unknown router %s",
430 naddr_ntoa(FROM_NADDR));
431 return;
432 }
433 if (rip->rip_cmd == RIPCMD_TRACEON) {
434 rip->rip_tracefile[cc-4] = '\0';
435 set_tracefile((char*)rip->rip_tracefile,
436 "trace command: %s\n", 0);
437 } else {
438 trace_off("tracing turned off by %s",
439 naddr_ntoa(FROM_NADDR));
440 }
441 return;
442
443 case RIPCMD_RESPONSE:
444 if (cc%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
445 msglim(&bad_len, FROM_NADDR,
446 "response of bad length (%d) from %s",
447 cc, naddr_ntoa(FROM_NADDR));
448 }
449
450 /* verify message came from a router */
451 if (from->sin_port != ntohs(RIP_PORT)) {
452 msglim(&bad_router, FROM_NADDR,
453 " discard RIP response from unknown port"
454 " %d", from->sin_port);
455 return;
456 }
457
458 if (rip_sock < 0) {
459 trace_pkt(" discard response while RIP off");
460 return;
461 }
462
463 /* Are we talking to ourself or a remote gateway?
464 */
465 ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
466 if (ifp1) {
467 if (ifp1->int_state & IS_REMOTE) {
468 /* remote gateway */
469 aifp = ifp1;
470 if (check_remote(aifp)) {
471 aifp->int_act_time = now.tv_sec;
472 (void)if_ok(aifp, "remote ");
473 }
474 } else {
475 trace_pkt(" discard our own RIP response");
476 return;
477 }
478 }
479
480 /* Accept routing packets from routers directly connected
481 * via broadcast or point-to-point networks, and from
482 * those listed in /etc/gateways.
483 */
484 if (aifp == 0) {
485 msglim(&unk_router, FROM_NADDR,
486 " discard response from %s"
487 " via unexpected interface",
488 naddr_ntoa(FROM_NADDR));
489 return;
490 }
491 if (IS_RIP_IN_OFF(aifp->int_state)) {
492 trace_pkt(" discard RIPv%d response"
493 " via disabled interface %s",
494 rip->rip_vers, aifp->int_name);
495 return;
496 }
497
498 if (n >= lim) {
499 msglim(&bad_len, FROM_NADDR, "empty response from %s",
500 naddr_ntoa(FROM_NADDR));
501 return;
502 }
503
504 if (((aifp->int_state & IS_NO_RIPV1_IN)
505 && rip->rip_vers == RIPv1)
506 || ((aifp->int_state & IS_NO_RIPV2_IN)
507 && rip->rip_vers != RIPv1)) {
508 trace_pkt(" discard RIPv%d response",
509 rip->rip_vers);
510 return;
511 }
512
513 /* Ignore routes via dead interface.
514 */
515 if (aifp->int_state & IS_BROKE) {
516 trace_pkt("%sdiscard response via broken interface %s",
517 aifp->int_name);
518 return;
519 }
520
521 /* If the interface cares, ignore bad routers.
522 * Trace but do not log this problem, because where it
523 * happens, it happens frequently.
524 */
525 if (aifp->int_state & IS_DISTRUST) {
526 struct tgate *tg = tgates;
527 while (tg->tgate_addr != FROM_NADDR) {
528 tg = tg->tgate_next;
529 if (tg == 0) {
530 trace_pkt(" discard RIP response"
531 " from untrusted router %s",
532 naddr_ntoa(FROM_NADDR));
533 return;
534 }
535 }
536 }
537
538 /* Authenticate the packet if we have a secret.
539 * If we do not have any secrets, ignore the error in
540 * RFC 1723 and accept it regardless.
541 */
542 if (aifp->int_auth[0].type != RIP_AUTH_NONE
543 && rip->rip_vers != RIPv1
544 && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth))
545 return;
546
547 do {
548 if (n->n_family == RIP_AF_AUTH)
549 continue;
550
551 NTOHL(n->n_metric);
552 dst = n->n_dst;
553 if (n->n_family != RIP_AF_INET
554 && (n->n_family != RIP_AF_UNSPEC
555 || dst != RIP_DEFAULT)) {
556 msglim(&bad_router, FROM_NADDR,
557 "route from %s to unsupported"
558 " address family=%d destination=%s",
559 naddr_ntoa(FROM_NADDR),
560 n->n_family,
561 naddr_ntoa(dst));
562 continue;
563 }
564 if (!check_dst(dst)) {
565 msglim(&bad_router, FROM_NADDR,
566 "bad destination %s from %s",
567 naddr_ntoa(dst),
568 naddr_ntoa(FROM_NADDR));
569 return;
570 }
571 if (n->n_metric == 0
572 || n->n_metric > HOPCNT_INFINITY) {
573 msglim(&bad_router, FROM_NADDR,
574 "bad metric %d from %s"
575 " for destination %s",
576 n->n_metric,
577 naddr_ntoa(FROM_NADDR),
578 naddr_ntoa(dst));
579 return;
580 }
581
582 /* Notice the next-hop.
583 */
584 gate = FROM_NADDR;
585 if (n->n_nhop != 0) {
586 if (rip->rip_vers == RIPv2) {
587 n->n_nhop = 0;
588 } else {
589 /* Use it only if it is valid. */
590 if (on_net(n->n_nhop,
591 aifp->int_net, aifp->int_mask)
592 && check_dst(n->n_nhop)) {
593 gate = n->n_nhop;
594 } else {
595 msglim(&bad_nhop, FROM_NADDR,
596 "router %s to %s"
597 " has bad next hop %s",
598 naddr_ntoa(FROM_NADDR),
599 naddr_ntoa(dst),
600 naddr_ntoa(n->n_nhop));
601 n->n_nhop = 0;
602 }
603 }
604 }
605
606 if (rip->rip_vers == RIPv1
607 || 0 == (mask = ntohl(n->n_mask))) {
608 mask = ripv1_mask_host(dst,aifp);
609 } else if ((ntohl(dst) & ~mask) != 0) {
610 msglim(&bad_mask, FROM_NADDR,
611 "router %s sent bad netmask"
612 " %#x with %s",
613 naddr_ntoa(FROM_NADDR),
614 mask,
615 naddr_ntoa(dst));
616 continue;
617 }
618 if (rip->rip_vers == RIPv1)
619 n->n_tag = 0;
620
621 /* Adjust metric according to incoming interface..
622 */
623 n->n_metric += aifp->int_metric;
624 if (n->n_metric > HOPCNT_INFINITY)
625 n->n_metric = HOPCNT_INFINITY;
626
627 /* Recognize and ignore a default route we faked
628 * which is being sent back to us by a machine with
629 * broken split-horizon.
630 * Be a little more paranoid than that, and reject
631 * default routes with the same metric we advertised.
632 */
633 if (aifp->int_d_metric != 0
634 && dst == RIP_DEFAULT
635 && n->n_metric >= aifp->int_d_metric)
636 continue;
637
638 /* We can receive aggregated RIPv2 routes that must
639 * be broken down before they are transmitted by
640 * RIPv1 via an interface on a subnet.
641 * We might also receive the same routes aggregated
642 * via other RIPv2 interfaces.
643 * This could cause duplicate routes to be sent on
644 * the RIPv1 interfaces. "Longest matching variable
645 * length netmasks" lets RIPv2 listeners understand,
646 * but breaking down the aggregated routes for RIPv1
647 * listeners can produce duplicate routes.
648 *
649 * Breaking down aggregated routes here bloats
650 * the daemon table, but does not hurt the kernel
651 * table, since routes are always aggregated for
652 * the kernel.
653 *
654 * Notice that this does not break down network
655 * routes corresponding to subnets. This is part
656 * of the defense against RS_NET_SYN.
657 */
658 if (have_ripv1_out
659 && (((rt = rtget(dst,mask)) == 0
660 || !(rt->rt_state & RS_NET_SYN)))
661 && (v1_mask = ripv1_mask_net(dst,0)) > mask) {
662 ddst_h = v1_mask & -v1_mask;
663 i = (v1_mask & ~mask)/ddst_h;
664 if (i >= 511) {
665 /* Punt if we would have to generate
666 * an unreasonable number of routes.
667 */
668 #ifdef DEBUG
669 msglog("accept %s from %s as 1"
670 " instead of %d routes",
671 addrname(dst,mask,0),
672 naddr_ntoa(FROM_NADDR),
673 i+1);
674 #endif
675 i = 0;
676 } else {
677 mask = v1_mask;
678 }
679 } else {
680 i = 0;
681 }
682
683 for (;;) {
684 input_route(aifp, FROM_NADDR,
685 dst, mask, gate, n);
686 if (i-- == 0)
687 break;
688 dst = htonl(ntohl(dst) + ddst_h);
689 }
690 } while (++n < lim);
691 break;
692 }
693 #undef FROM_NADDR
694 }
695
696
697 /* Process a single input route.
698 */
699 static void
700 input_route(struct interface *ifp,
701 naddr from,
702 naddr dst,
703 naddr mask,
704 naddr gate,
705 struct netinfo *n)
706 {
707 int i;
708 struct rt_entry *rt;
709 struct rt_spare *rts, *rts0;
710 struct interface *ifp1;
711 time_t new_time;
712
713
714 /* See if the other guy is telling us to send our packets to him.
715 * Sometimes network routes arrive over a point-to-point link for
716 * the network containing the address(es) of the link.
717 *
718 * If our interface is broken, switch to using the other guy.
719 */
720 ifp1 = ifwithaddr(dst, 1, 1);
721 if (ifp1 != 0
722 && (!(ifp1->int_state & IS_BROKE)
723 || (ifp1->int_state & IS_PASSIVE)))
724 return;
725
726 /* Look for the route in our table.
727 */
728 rt = rtget(dst, mask);
729
730 /* Consider adding the route if we do not already have it.
731 */
732 if (rt == 0) {
733 /* Ignore unknown routes being poisoned.
734 */
735 if (n->n_metric == HOPCNT_INFINITY)
736 return;
737
738 /* Ignore the route if it points to us */
739 if (n->n_nhop != 0
740 && 0 != ifwithaddr(n->n_nhop, 1, 0))
741 return;
742
743 /* If something has not gone crazy and tried to fill
744 * our memory, accept the new route.
745 */
746 if (total_routes < MAX_ROUTES)
747 rtadd(dst, mask, gate, from, n->n_metric,
748 n->n_tag, 0, ifp);
749 return;
750 }
751
752 /* We already know about the route. Consider this update.
753 *
754 * If (rt->rt_state & RS_NET_SYN), then this route
755 * is the same as a network route we have inferred
756 * for subnets we know, in order to tell RIPv1 routers
757 * about the subnets.
758 *
759 * It is impossible to tell if the route is coming
760 * from a distant RIPv2 router with the standard
761 * netmask because that router knows about the entire
762 * network, or if it is a round-about echo of a
763 * synthetic, RIPv1 network route of our own.
764 * The worst is that both kinds of routes might be
765 * received, and the bad one might have the smaller
766 * metric. Partly solve this problem by never
767 * aggregating into such a route. Also keep it
768 * around as long as the interface exists.
769 */
770
771 rts0 = rt->rt_spares;
772 for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
773 if (rts->rts_router == from)
774 break;
775 /* Note the worst slot to reuse,
776 * other than the current slot.
777 */
778 if (rts0 == rt->rt_spares
779 || BETTER_LINK(rt, rts0, rts))
780 rts0 = rts;
781 }
782 if (i != 0) {
783 /* Found the router
784 */
785 int old_metric = rts->rts_metric;
786
787 /* Keep poisoned routes around only long enough to pass
788 * the poison on. Get a new timestamp for good routes.
789 */
790 new_time =((old_metric == HOPCNT_INFINITY)
791 ? rts->rts_time
792 : now.tv_sec);
793
794 /* If this is an update for the router we currently prefer,
795 * then note it.
796 */
797 if (i == NUM_SPARES) {
798 rtchange(rt,rt->rt_state, gate,rt->rt_router,
799 n->n_metric, n->n_tag, ifp, new_time, 0);
800 /* If the route got worse, check for something better.
801 */
802 if (n->n_metric > old_metric)
803 rtswitch(rt, 0);
804 return;
805 }
806
807 /* This is an update for a spare route.
808 * Finished if the route is unchanged.
809 * Forget it if it has gone bad.
810 */
811 if (rts->rts_gate == gate
812 && old_metric == n->n_metric
813 && rts->rts_tag == n->n_tag) {
814 rts->rts_time = new_time;
815 return;
816 } else if (n->n_metric == HOPCNT_INFINITY) {
817 rts_delete(rt, rts);
818 return;
819 }
820
821 } else {
822 /* The update is for a route we know about,
823 * but not from a familiar router.
824 *
825 * Ignore the route if it points to us.
826 */
827 if (n->n_nhop != 0
828 && 0 != ifwithaddr(n->n_nhop, 1, 0))
829 return;
830
831 rts = rts0;
832
833 /* Save the route as a spare only if it has
834 * a better metric than our worst spare.
835 * This also ignores poisoned routes (those
836 * received with metric HOPCNT_INFINITY).
837 */
838 if (n->n_metric >= rts->rts_metric)
839 return;
840
841 new_time = now.tv_sec;
842 }
843
844 trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time);
845 rts->rts_gate = gate;
846 rts->rts_router = from;
847 rts->rts_metric = n->n_metric;
848 rts->rts_tag = n->n_tag;
849 rts->rts_time = new_time;
850 rts->rts_ifp = ifp;
851
852 /* try to switch to a better route */
853 rtswitch(rt, rts);
854 }
855
856
857 static int /* 0 if bad */
858 ck_passwd(struct interface *aifp,
859 struct rip *rip,
860 void *lim,
861 naddr from,
862 struct msg_limit *use_authp)
863 {
864 # define NA (rip->rip_auths)
865 struct netauth *na2;
866 struct auth *ap;
867 MD5_CTX md5_ctx;
868 u_char hash[RIP_AUTH_PW_LEN];
869 int i;
870
871
872 if ((void *)NA >= lim || NA->a_family != RIP_AF_AUTH) {
873 msglim(use_authp, from, "missing password from %s",
874 naddr_ntoa(from));
875 return 0;
876 }
877
878 /* accept any current (+/- 24 hours) password
879 */
880 for (ap = aifp->int_auth, i = 0; i < MAX_AUTH_KEYS; i++, ap++) {
881 if (ap->type != NA->a_type
882 || (u_long)ap->start > (u_long)clk.tv_sec+DAY
883 || (u_long)ap->end+DAY < (u_long)clk.tv_sec)
884 continue;
885
886 if (NA->a_type == RIP_AUTH_PW) {
887 if (!bcmp(NA->au.au_pw, ap->key, RIP_AUTH_PW_LEN))
888 return 1;
889
890 } else {
891 /* accept MD5 secret with the right key ID
892 */
893 if (NA->au.a_md5.md5_keyid != ap->keyid)
894 continue;
895
896 na2 = (struct netauth *)((char *)(NA+1)
897 + NA->au.a_md5.md5_pkt_len);
898 if (NA->au.a_md5.md5_pkt_len % sizeof(*NA) != 0
899 || lim < (void *)(na2+1)) {
900 msglim(use_authp, from,
901 "bad MD5 RIP-II pkt length %d from %s",
902 NA->au.a_md5.md5_pkt_len,
903 naddr_ntoa(from));
904 return 0;
905 }
906 MD5Init(&md5_ctx);
907 MD5Update(&md5_ctx, (u_char *)NA,
908 (char *)na2->au.au_pw - (char *)NA);
909 MD5Update(&md5_ctx,
910 (u_char *)ap->key, sizeof(ap->key));
911 MD5Final(hash, &md5_ctx);
912 if (na2->a_family != RIP_AF_AUTH
913 || na2->a_type != 1
914 || NA->au.a_md5.md5_auth_len != RIP_AUTH_PW_LEN
915 || bcmp(hash, na2->au.au_pw, sizeof(hash)))
916 return 0;
917 return 1;
918 }
919 }
920
921 msglim(use_authp, from, "bad password from %s",
922 naddr_ntoa(from));
923 return 0;
924 #undef NA
925 }
926