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