Clean (void) casts from sbin
[dragonfly.git] / sbin / routed / output.c
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 acknowledgment:
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  * $FreeBSD: src/sbin/routed/output.c,v 1.5.2.1 2000/08/14 17:00:03 sheldonh Exp $
34  * $DragonFly: src/sbin/routed/output.c,v 1.4 2004/12/18 21:43:40 swildner Exp $
35  */
36
37 #include "defs.h"
38
39 #if !defined(sgi) && !defined(__NetBSD__)
40 static char sccsid[] __attribute__((unused)) = "@(#)output.c    8.1 (Berkeley) 6/5/93";
41 #elif defined(__NetBSD__)
42 __RCSID("$NetBSD$");
43 #endif
44 #ident "$FreeBSD: src/sbin/routed/output.c,v 1.5.2.1 2000/08/14 17:00:03 sheldonh Exp $"
45
46
47 u_int update_seqno;
48
49
50 /* walk the tree of routes with this for output
51  */
52 struct {
53         struct sockaddr_in to;
54         naddr   to_mask;
55         naddr   to_net;
56         naddr   to_std_mask;
57         naddr   to_std_net;
58         struct interface *ifp;          /* usually output interface */
59         struct auth *a;
60         char    metric;                 /* adjust metrics by interface */
61         int     npackets;
62         int     gen_limit;
63         u_int   state;
64 #define     WS_ST_FLASH     0x001       /* send only changed routes */
65 #define     WS_ST_RIP2_ALL  0x002       /* send full featured RIPv2 */
66 #define     WS_ST_AG        0x004       /* ok to aggregate subnets */
67 #define     WS_ST_SUPER_AG  0x008       /* ok to aggregate networks */
68 #define     WS_ST_QUERY     0x010       /* responding to a query */
69 #define     WS_ST_TO_ON_NET 0x020       /* sending onto one of our nets */
70 #define     WS_ST_DEFAULT   0x040       /* faking a default */
71 } ws;
72
73 /* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
74 struct ws_buf v12buf;
75 union pkt_buf ripv12_buf;
76
77 /* Another for only RIPv2 listeners */
78 struct ws_buf v2buf;
79 union pkt_buf rip_v2_buf;
80
81
82
83 void
84 bufinit(void)
85 {
86         ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE;
87         v12buf.buf = &ripv12_buf.rip;
88         v12buf.base = &v12buf.buf->rip_nets[0];
89
90         rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
91         rip_v2_buf.rip.rip_vers = RIPv2;
92         v2buf.buf = &rip_v2_buf.rip;
93         v2buf.base = &v2buf.buf->rip_nets[0];
94 }
95
96
97 /* Send the contents of the global buffer via the non-multicast socket
98  */
99 int                                     /* <0 on failure */
100 output(enum output_type type,
101        struct sockaddr_in *dst,         /* send to here */
102        struct interface *ifp,
103        struct rip *buf,
104        int size)                        /* this many bytes */
105 {
106         struct sockaddr_in sin;
107         int flags;
108         const char *msg;
109         int res;
110         naddr tgt_mcast;
111         int soc;
112         int serrno;
113
114         sin = *dst;
115         if (sin.sin_port == 0)
116                 sin.sin_port = htons(RIP_PORT);
117 #ifdef _HAVE_SIN_LEN
118         if (sin.sin_len == 0)
119                 sin.sin_len = sizeof(sin);
120 #endif
121
122         soc = rip_sock;
123         flags = 0;
124
125         switch (type) {
126         case OUT_QUERY:
127                 msg = "Answer Query";
128                 if (soc < 0)
129                         soc = ifp->int_rip_sock;
130                 break;
131         case OUT_UNICAST:
132                 msg = "Send";
133                 if (soc < 0)
134                         soc = ifp->int_rip_sock;
135                 flags = MSG_DONTROUTE;
136                 break;
137         case OUT_BROADCAST:
138                 if (ifp->int_if_flags & IFF_POINTOPOINT) {
139                         msg = "Send";
140                 } else {
141                         msg = "Send bcast";
142                 }
143                 flags = MSG_DONTROUTE;
144                 break;
145         case OUT_MULTICAST:
146                 if (ifp->int_if_flags & IFF_POINTOPOINT) {
147                         msg = "Send pt-to-pt";
148                 } else if (ifp->int_state & IS_DUP) {
149                         trace_act("abort multicast output via %s"
150                                   " with duplicate address",
151                                   ifp->int_name);
152                         return 0;
153                 } else {
154                         msg = "Send mcast";
155                         if (rip_sock_mcast != ifp) {
156 #ifdef MCAST_PPP_BUG
157                                 /* Do not specify the primary interface
158                                  * explicitly if we have the multicast
159                                  * point-to-point kernel bug, since the
160                                  * kernel will do the wrong thing if the
161                                  * local address of a point-to-point link
162                                  * is the same as the address of an ordinary
163                                  * interface.
164                                  */
165                                 if (ifp->int_addr == myaddr) {
166                                         tgt_mcast = 0;
167                                 } else
168 #endif
169                                 tgt_mcast = ifp->int_addr;
170                                 if (0 > setsockopt(rip_sock,
171                                                    IPPROTO_IP, IP_MULTICAST_IF,
172                                                    &tgt_mcast,
173                                                    sizeof(tgt_mcast))) {
174                                         serrno = errno;
175                                         LOGERR("setsockopt(rip_sock,"
176                                                "IP_MULTICAST_IF)");
177                                         errno = serrno;
178                                         ifp = 0;
179                                         return -1;
180                                 }
181                                 rip_sock_mcast = ifp;
182                         }
183                         sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
184                 }
185                 break;
186
187         case NO_OUT_MULTICAST:
188         case NO_OUT_RIPV2:
189         default:
190 #ifdef DEBUG
191                 abort();
192 #endif
193                 return -1;
194         }
195
196         trace_rip(msg, "to", &sin, ifp, buf, size);
197
198         res = sendto(soc, buf, size, flags,
199                      (struct sockaddr *)&sin, sizeof(sin));
200         if (res < 0
201             && (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
202                 serrno = errno;
203                 msglog("%s sendto(%s%s%s.%d): %s", msg,
204                        ifp != 0 ? ifp->int_name : "",
205                        ifp != 0 ? ", " : "",
206                        inet_ntoa(sin.sin_addr),
207                        ntohs(sin.sin_port),
208                        strerror(errno));
209                 errno = serrno;
210         }
211
212         return res;
213 }
214
215
216 /* Find the first key for a packet to send.
217  * Try for a key that is eligible and has not expired, but settle for
218  * the last key if they have all expired.
219  * If no key is ready yet, give up.
220  */
221 struct auth *
222 find_auth(struct interface *ifp)
223 {
224         struct auth *ap, *res;
225         int i;
226
227
228         if (ifp == 0)
229                 return 0;
230
231         res = 0;
232         ap = ifp->int_auth;
233         for (i = 0; i < MAX_AUTH_KEYS; i++, ap++) {
234                 /* stop looking after the last key */
235                 if (ap->type == RIP_AUTH_NONE)
236                         break;
237
238                 /* ignore keys that are not ready yet */
239                 if ((u_long)ap->start > (u_long)clk.tv_sec)
240                         continue;
241
242                 if ((u_long)ap->end < (u_long)clk.tv_sec) {
243                         /* note best expired password as a fall-back */
244                         if (res == 0 || (u_long)ap->end > (u_long)res->end)
245                                 res = ap;
246                         continue;
247                 }
248
249                 /* note key with the best future */
250                 if (res == 0 || (u_long)res->end < (u_long)ap->end)
251                         res = ap;
252         }
253         return res;
254 }
255
256
257 void
258 clr_ws_buf(struct ws_buf *wb,
259            struct auth *ap)
260 {
261         struct netauth *na;
262
263         wb->lim = wb->base + NETS_LEN;
264         wb->n = wb->base;
265         memset(wb->n, 0, NETS_LEN*sizeof(*wb->n));
266
267         /* (start to) install authentication if appropriate
268          */
269         if (ap == 0)
270                 return;
271
272         na = (struct netauth*)wb->n;
273         if (ap->type == RIP_AUTH_PW) {
274                 na->a_family = RIP_AF_AUTH;
275                 na->a_type = RIP_AUTH_PW;
276                 memcpy(na->au.au_pw, ap->key, sizeof(na->au.au_pw));
277                 wb->n++;
278
279         } else if (ap->type ==  RIP_AUTH_MD5) {
280                 na->a_family = RIP_AF_AUTH;
281                 na->a_type = RIP_AUTH_MD5;
282                 na->au.a_md5.md5_keyid = ap->keyid;
283                 na->au.a_md5.md5_auth_len = RIP_AUTH_MD5_LEN;
284                 na->au.a_md5.md5_seqno = htonl(clk.tv_sec);
285                 wb->n++;
286                 wb->lim--;              /* make room for trailer */
287         }
288 }
289
290
291 void
292 end_md5_auth(struct ws_buf *wb,
293              struct auth *ap)
294 {
295         struct netauth *na, *na2;
296         MD5_CTX md5_ctx;
297         int len;
298
299
300         na = (struct netauth*)wb->base;
301         na2 = (struct netauth*)wb->n;
302         len = (char *)na2-(char *)wb->buf;
303         na2->a_family = RIP_AF_AUTH;
304         na2->a_type = htons(1);
305         na->au.a_md5.md5_pkt_len = htons(len);
306         MD5Init(&md5_ctx);
307         MD5Update(&md5_ctx, (u_char *)wb->buf, len);
308         MD5Update(&md5_ctx, ap->key, RIP_AUTH_MD5_LEN);
309         MD5Final(na2->au.au_pw, &md5_ctx);
310         wb->n++;
311 }
312
313
314 /* Send the buffer
315  */
316 static void
317 supply_write(struct ws_buf *wb)
318 {
319         /* Output multicast only if legal.
320          * If we would multicast and it would be illegal, then discard the
321          * packet.
322          */
323         switch (wb->type) {
324         case NO_OUT_MULTICAST:
325                 trace_pkt("skip multicast to %s because impossible",
326                           naddr_ntoa(ws.to.sin_addr.s_addr));
327                 break;
328         case NO_OUT_RIPV2:
329                 break;
330         default:
331                 if (ws.a != 0 && ws.a->type == RIP_AUTH_MD5)
332                         end_md5_auth(wb,ws.a);
333                 if (output(wb->type, &ws.to, ws.ifp, wb->buf,
334                            ((char *)wb->n - (char*)wb->buf)) < 0
335                     && ws.ifp != 0)
336                         if_sick(ws.ifp);
337                 ws.npackets++;
338                 break;
339         }
340
341         clr_ws_buf(wb,ws.a);
342 }
343
344
345 /* put an entry into the packet
346  */
347 static void
348 supply_out(struct ag_info *ag)
349 {
350         int i;
351         naddr mask, v1_mask, dst_h, ddst_h = 0;
352         struct ws_buf *wb;
353
354
355         /* Skip this route if doing a flash update and it and the routes
356          * it aggregates have not changed recently.
357          */
358         if (ag->ag_seqno < update_seqno
359             && (ws.state & WS_ST_FLASH))
360                 return;
361
362         dst_h = ag->ag_dst_h;
363         mask = ag->ag_mask;
364         v1_mask = ripv1_mask_host(htonl(dst_h),
365                                   (ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0);
366         i = 0;
367
368         /* If we are sending RIPv2 packets that cannot (or must not) be
369          * heard by RIPv1 listeners, do not worry about sub- or supernets.
370          * Subnets (from other networks) can only be sent via multicast.
371          * A pair of subnet routes might have been promoted so that they
372          * are legal to send by RIPv1.
373          * If RIPv1 is off, use the multicast buffer.
374          */
375         if ((ws.state & WS_ST_RIP2_ALL)
376             || ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) {
377                 /* use the RIPv2-only buffer */
378                 wb = &v2buf;
379
380         } else {
381                 /* use the RIPv1-or-RIPv2 buffer */
382                 wb = &v12buf;
383
384                 /* Convert supernet route into corresponding set of network
385                  * routes for RIPv1, but leave non-contiguous netmasks
386                  * to ag_check().
387                  */
388                 if (v1_mask > mask
389                     && mask + (mask & -mask) == 0) {
390                         ddst_h = v1_mask & -v1_mask;
391                         i = (v1_mask & ~mask)/ddst_h;
392
393                         if (i > ws.gen_limit) {
394                                 /* Punt if we would have to generate an
395                                  * unreasonable number of routes.
396                                  */
397                                 if (TRACECONTENTS)
398                                         trace_misc("sending %s-->%s as 1"
399                                                    " instead of %d routes",
400                                                    addrname(htonl(dst_h), mask,
401                                                         1),
402                                                    naddr_ntoa(ws.to.sin_addr
403                                                         .s_addr),
404                                                    i+1);
405                                 i = 0;
406
407                         } else {
408                                 mask = v1_mask;
409                                 ws.gen_limit -= i;
410                         }
411                 }
412         }
413
414         do {
415                 wb->n->n_family = RIP_AF_INET;
416                 wb->n->n_dst = htonl(dst_h);
417                 /* If the route is from router-discovery or we are
418                  * shutting down, admit only a bad metric.
419                  */
420                 wb->n->n_metric = ((stopint || ag->ag_metric < 1)
421                                    ? HOPCNT_INFINITY
422                                    : ag->ag_metric);
423                 wb->n->n_metric = htonl(wb->n->n_metric);
424                 /* Any non-zero bits in the supposedly unused RIPv1 fields
425                  * cause the old `routed` to ignore the route.
426                  * That means the mask and so forth cannot be sent
427                  * in the hybrid RIPv1/RIPv2 mode.
428                  */
429                 if (ws.state & WS_ST_RIP2_ALL) {
430                         if (ag->ag_nhop != 0
431                             && ((ws.state & WS_ST_QUERY)
432                                 || (ag->ag_nhop != ws.ifp->int_addr
433                                     && on_net(ag->ag_nhop,
434                                               ws.ifp->int_net,
435                                               ws.ifp->int_mask))))
436                                 wb->n->n_nhop = ag->ag_nhop;
437                         wb->n->n_mask = htonl(mask);
438                         wb->n->n_tag = ag->ag_tag;
439                 }
440                 dst_h += ddst_h;
441
442                 if (++wb->n >= wb->lim)
443                         supply_write(wb);
444         } while (i-- != 0);
445 }
446
447
448 /* supply one route from the table
449  */
450 /* ARGSUSED */
451 static int
452 walk_supply(struct radix_node *rn,
453             struct walkarg *argp UNUSED)
454 {
455 #define RT ((struct rt_entry *)rn)
456         u_short ags;
457         char metric, pref;
458         naddr dst, nhop;
459         struct rt_spare *rts;
460         int i;
461
462
463         /* Do not advertise external remote interfaces or passive interfaces.
464          */
465         if ((RT->rt_state & RS_IF)
466             && RT->rt_ifp != 0
467             && (RT->rt_ifp->int_state & IS_PASSIVE)
468             && !(RT->rt_state & RS_MHOME))
469                 return 0;
470
471         /* If being quiet about our ability to forward, then
472          * do not say anything unless responding to a query,
473          * except about our main interface.
474          */
475         if (!supplier && !(ws.state & WS_ST_QUERY)
476             && !(RT->rt_state & RS_MHOME))
477                 return 0;
478
479         dst = RT->rt_dst;
480
481         /* do not collide with the fake default route */
482         if (dst == RIP_DEFAULT
483             && (ws.state & WS_ST_DEFAULT))
484                 return 0;
485
486         if (RT->rt_state & RS_NET_SYN) {
487                 if (RT->rt_state & RS_NET_INT) {
488                         /* Do not send manual synthetic network routes
489                          * into the subnet.
490                          */
491                         if (on_net(ws.to.sin_addr.s_addr,
492                                    ntohl(dst), RT->rt_mask))
493                                 return 0;
494
495                 } else {
496                         /* Do not send automatic synthetic network routes
497                          * if they are not needed because no RIPv1 listeners
498                          * can hear them.
499                          */
500                         if (ws.state & WS_ST_RIP2_ALL)
501                                 return 0;
502
503                         /* Do not send automatic synthetic network routes to
504                          * the real subnet.
505                          */
506                         if (on_net(ws.to.sin_addr.s_addr,
507                                    ntohl(dst), RT->rt_mask))
508                                 return 0;
509                 }
510                 nhop = 0;
511
512         } else {
513                 /* Advertise the next hop if this is not a route for one
514                  * of our interfaces and the next hop is on the same
515                  * network as the target.
516                  * The final determination is made by supply_out().
517                  */
518                 if (!(RT->rt_state & RS_IF)
519                     && RT->rt_gate != myaddr
520                     && RT->rt_gate != loopaddr)
521                         nhop = RT->rt_gate;
522                 else
523                         nhop = 0;
524         }
525
526         metric = RT->rt_metric;
527         ags = 0;
528
529         if (RT->rt_state & RS_MHOME) {
530                 /* retain host route of multi-homed servers */
531                 ;
532
533         } else if (RT_ISHOST(RT)) {
534                 /* We should always suppress (into existing network routes)
535                  * the host routes for the local end of our point-to-point
536                  * links.
537                  * If we are suppressing host routes in general, then do so.
538                  * Avoid advertising host routes onto their own network,
539                  * where they should be handled by proxy-ARP.
540                  */
541                 if ((RT->rt_state & RS_LOCAL)
542                     || ridhosts
543                     || on_net(dst, ws.to_net, ws.to_mask))
544                         ags |= AGS_SUPPRESS;
545
546                 /* Aggregate stray host routes into network routes if allowed.
547                  * We cannot aggregate host routes into small network routes
548                  * without confusing RIPv1 listeners into thinking the
549                  * network routes are host routes.
550                  */
551                 if ((ws.state & WS_ST_AG)
552                     && !(ws.state & WS_ST_RIP2_ALL))
553                         ags |= AGS_AGGREGATE;
554
555         } else {
556                 /* Always suppress network routes into other, existing
557                  * network routes
558                  */
559                 ags |= AGS_SUPPRESS;
560
561                 /* Generate supernets if allowed.
562                  * If we can be heard by RIPv1 systems, we will
563                  * later convert back to ordinary nets.
564                  * This unifies dealing with received supernets.
565                  */
566                 if ((ws.state & WS_ST_AG)
567                     && ((RT->rt_state & RS_SUBNET)
568                         || (ws.state & WS_ST_SUPER_AG)))
569                         ags |= AGS_AGGREGATE;
570         }
571
572         /* Do not send RIPv1 advertisements of subnets to other
573          * networks. If possible, multicast them by RIPv2.
574          */
575         if ((RT->rt_state & RS_SUBNET)
576             && !(ws.state & WS_ST_RIP2_ALL)
577             && !on_net(dst, ws.to_std_net, ws.to_std_mask))
578                 ags |= AGS_RIPV2 | AGS_AGGREGATE;
579
580
581         /* Do not send a route back to where it came from, except in
582          * response to a query.  This is "split-horizon".  That means not
583          * advertising back to the same network and so via the same interface.
584          *
585          * We want to suppress routes that might have been fragmented
586          * from this route by a RIPv1 router and sent back to us, and so we
587          * cannot forget this route here.  Let the split-horizon route
588          * suppress the fragmented routes and then itself be forgotten.
589          *
590          * Include the routes for both ends of point-to-point interfaces
591          * among those suppressed by split-horizon, since the other side
592          * should knows them as well as we do.
593          *
594          * Notice spare routes with the same metric that we are about to
595          * advertise, to split the horizon on redundant, inactive paths.
596          */
597         if (ws.ifp != 0
598             && !(ws.state & WS_ST_QUERY)
599             && (ws.state & WS_ST_TO_ON_NET)
600             && (!(RT->rt_state & RS_IF)
601                 || ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
602                 for (rts = RT->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) {
603                         if (rts->rts_metric > metric
604                             || rts->rts_ifp != ws.ifp)
605                                 continue;
606
607                         /* If we do not mark the route with AGS_SPLIT_HZ here,
608                          * it will be poisoned-reverse, or advertised back
609                          * toward its source with an infinite metric.
610                          * If we have recently advertised the route with a
611                          * better metric than we now have, then we should
612                          * poison-reverse the route before suppressing it for
613                          * split-horizon.
614                          *
615                          * In almost all cases, if there is no spare for the
616                          * route then it is either old and dead or a brand
617                          * new route. If it is brand new, there is no need
618                          * for poison-reverse. If it is old and dead, it
619                          * is already poisoned.
620                          */
621                         if (RT->rt_poison_time < now_expire
622                             || RT->rt_poison_metric >= metric
623                             || RT->rt_spares[1].rts_gate == 0) {
624                                 ags |= AGS_SPLIT_HZ;
625                                 ags &= ~AGS_SUPPRESS;
626                         }
627                         metric = HOPCNT_INFINITY;
628                         break;
629                 }
630         }
631
632         /* Keep track of the best metric with which the
633          * route has been advertised recently.
634          */
635         if (RT->rt_poison_metric >= metric
636             || RT->rt_poison_time < now_expire) {
637                 RT->rt_poison_time = now.tv_sec;
638                 RT->rt_poison_metric = metric;
639         }
640
641         /* Adjust the outgoing metric by the cost of the link.
642          * Avoid aggregation when a route is counting to infinity.
643          */
644         pref = RT->rt_poison_metric + ws.metric;
645         metric += ws.metric;
646
647         /* Do not advertise stable routes that will be ignored,
648          * unless we are answering a query.
649          * If the route recently was advertised with a metric that
650          * would have been less than infinity through this interface,
651          * we need to continue to advertise it in order to poison it.
652          */
653         if (metric >= HOPCNT_INFINITY) {
654                 if (!(ws.state & WS_ST_QUERY)
655                     && (pref >= HOPCNT_INFINITY
656                         || RT->rt_poison_time < now_garbage))
657                         return 0;
658
659                 metric = HOPCNT_INFINITY;
660         }
661
662         ag_check(dst, RT->rt_mask, 0, nhop, metric, pref,
663                  RT->rt_seqno, RT->rt_tag, ags, supply_out);
664         return 0;
665 #undef RT
666 }
667
668
669 /* Supply dst with the contents of the routing tables.
670  * If this won't fit in one packet, chop it up into several.
671  */
672 void
673 supply(struct sockaddr_in *dst,
674        struct interface *ifp,           /* output interface */
675        enum output_type type,
676        int flash,                       /* 1=flash update */
677        int vers,                        /* RIP version */
678        int passwd_ok)                   /* OK to include cleartext password */
679 {
680         struct rt_entry *rt;
681         int def_metric;
682
683
684         ws.state = 0;
685         ws.gen_limit = 1024;
686
687         ws.to = *dst;
688         ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
689         ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;
690
691         if (ifp != 0) {
692                 ws.to_mask = ifp->int_mask;
693                 ws.to_net = ifp->int_net;
694                 if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
695                         ws.state |= WS_ST_TO_ON_NET;
696
697         } else {
698                 ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
699                 ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
700                 rt = rtfind(dst->sin_addr.s_addr);
701                 if (rt)
702                         ifp = rt->rt_ifp;
703         }
704
705         ws.npackets = 0;
706         if (flash)
707                 ws.state |= WS_ST_FLASH;
708
709         if ((ws.ifp = ifp) == 0) {
710                 ws.metric = 1;
711         } else {
712                 /* Adjust the advertised metric by the outgoing interface
713                  * metric.
714                  */
715                 ws.metric = ifp->int_metric+1;
716         }
717
718         ripv12_buf.rip.rip_vers = vers;
719
720         switch (type) {
721         case OUT_MULTICAST:
722                 if (ifp->int_if_flags & IFF_MULTICAST)
723                         v2buf.type = OUT_MULTICAST;
724                 else
725                         v2buf.type = NO_OUT_MULTICAST;
726                 v12buf.type = OUT_BROADCAST;
727                 break;
728
729         case OUT_QUERY:
730                 ws.state |= WS_ST_QUERY;
731                 /* fall through */
732         case OUT_BROADCAST:
733         case OUT_UNICAST:
734                 v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
735                 v12buf.type = type;
736                 break;
737
738         case NO_OUT_MULTICAST:
739         case NO_OUT_RIPV2:
740                 break;                  /* no output */
741         }
742
743         if (vers == RIPv2) {
744                 /* full RIPv2 only if cannot be heard by RIPv1 listeners */
745                 if (type != OUT_BROADCAST)
746                         ws.state |= WS_ST_RIP2_ALL;
747                 if ((ws.state & WS_ST_QUERY)
748                     || !(ws.state & WS_ST_TO_ON_NET)) {
749                         ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
750                 } else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) {
751                         ws.state |= WS_ST_AG;
752                         if (type != OUT_BROADCAST
753                             && (ifp == 0
754                                 || !(ifp->int_state & IS_NO_SUPER_AG)))
755                                 ws.state |= WS_ST_SUPER_AG;
756                 }
757         }
758
759         ws.a = (vers == RIPv2) ? find_auth(ifp) : 0;
760         if (!passwd_ok && ws.a != 0 && ws.a->type == RIP_AUTH_PW)
761                 ws.a = 0;
762         clr_ws_buf(&v12buf,ws.a);
763         clr_ws_buf(&v2buf,ws.a);
764
765         /*  Fake a default route if asked and if there is not already
766          * a better, real default route.
767          */
768         if (supplier && (def_metric = ifp->int_d_metric) != 0) {
769                 if (0 == (rt = rtget(RIP_DEFAULT, 0))
770                     || rt->rt_metric+ws.metric >= def_metric) {
771                         ws.state |= WS_ST_DEFAULT;
772                         ag_check(0, 0, 0, 0, def_metric, def_metric,
773                                  0, 0, 0, supply_out);
774                 } else {
775                         def_metric = rt->rt_metric+ws.metric;
776                 }
777
778                 /* If both RIPv2 and the poor-man's router discovery
779                  * kludge are on, arrange to advertise an extra
780                  * default route via RIPv1.
781                  */
782                 if ((ws.state & WS_ST_RIP2_ALL)
783                     && (ifp->int_state & IS_PM_RDISC)) {
784                         ripv12_buf.rip.rip_vers = RIPv1;
785                         v12buf.n->n_family = RIP_AF_INET;
786                         v12buf.n->n_dst = htonl(RIP_DEFAULT);
787                         v12buf.n->n_metric = htonl(def_metric);
788                         v12buf.n++;
789                 }
790         }
791
792         rn_walktree(rhead, walk_supply, 0);
793         ag_flush(0,0,supply_out);
794
795         /* Flush the packet buffers, provided they are not empty and
796          * do not contain only the password.
797          */
798         if (v12buf.n != v12buf.base
799             && (v12buf.n > v12buf.base+1
800                 || v12buf.base->n_family != RIP_AF_AUTH))
801                 supply_write(&v12buf);
802         if (v2buf.n != v2buf.base
803             && (v2buf.n > v2buf.base+1
804                 || v2buf.base->n_family != RIP_AF_AUTH))
805                 supply_write(&v2buf);
806
807         /* If we sent nothing and this is an answer to a query, send
808          * an empty buffer.
809          */
810         if (ws.npackets == 0
811             && (ws.state & WS_ST_QUERY))
812                 supply_write(&v12buf);
813 }
814
815
816 /* send all of the routing table or just do a flash update
817  */
818 void
819 rip_bcast(int flash)
820 {
821 #ifdef _HAVE_SIN_LEN
822         static struct sockaddr_in dst = {sizeof(dst), AF_INET, 0, {0}, {0}};
823 #else
824         static struct sockaddr_in dst = {AF_INET};
825 #endif
826         struct interface *ifp;
827         enum output_type type;
828         int vers;
829         struct timeval rtime;
830
831
832         need_flash = 0;
833         intvl_random(&rtime, MIN_WAITTIME, MAX_WAITTIME);
834         no_flash = rtime;
835         timevaladd(&no_flash, &now);
836
837         if (rip_sock < 0)
838                 return;
839
840         trace_act("send %s and inhibit dynamic updates for %.3f sec",
841                   flash ? "dynamic update" : "all routes",
842                   rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
843
844         for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
845                 /* Skip interfaces not doing RIP.
846                  * Do try broken interfaces to see if they have healed.
847                  */
848                 if (IS_RIP_OUT_OFF(ifp->int_state))
849                         continue;
850
851                 /* skip turned off interfaces */
852                 if (!iff_up(ifp->int_if_flags))
853                         continue;
854
855                 vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1;
856
857                 if (ifp->int_if_flags & IFF_BROADCAST) {
858                         /* ordinary, hardware interface */
859                         dst.sin_addr.s_addr = ifp->int_brdaddr;
860
861                         if (vers == RIPv2
862                             && !(ifp->int_state  & IS_NO_RIP_MCAST)) {
863                                 type = OUT_MULTICAST;
864                         } else {
865                                 type = OUT_BROADCAST;
866                         }
867
868                 } else if (ifp->int_if_flags & IFF_POINTOPOINT) {
869                         /* point-to-point hardware interface */
870                         dst.sin_addr.s_addr = ifp->int_dstaddr;
871                         type = OUT_UNICAST;
872
873                 } else if (ifp->int_state & IS_REMOTE) {
874                         /* remote interface */
875                         dst.sin_addr.s_addr = ifp->int_addr;
876                         type = OUT_UNICAST;
877
878                 } else {
879                         /* ATM, HIPPI, etc. */
880                         continue;
881                 }
882
883                 supply(&dst, ifp, type, flash, vers, 1);
884         }
885
886         update_seqno++;                 /* all routes are up to date */
887 }
888
889
890 /* Ask for routes
891  * Do it only once to an interface, and not even after the interface
892  * was broken and recovered.
893  */
894 void
895 rip_query(void)
896 {
897 #ifdef _HAVE_SIN_LEN
898         static struct sockaddr_in dst = {sizeof(dst), AF_INET, 0, {0}, {0}};
899 #else
900         static struct sockaddr_in dst = {AF_INET};
901 #endif
902         struct interface *ifp;
903         struct rip buf;
904         enum output_type type;
905
906
907         if (rip_sock < 0)
908                 return;
909
910         memset(&buf, 0, sizeof(buf));
911
912         for (ifp = ifnet; ifp; ifp = ifp->int_next) {
913                 /* Skip interfaces those already queried.
914                  * Do not ask via interfaces through which we don't
915                  * accept input.  Do not ask via interfaces that cannot
916                  * send RIP packets.
917                  * Do try broken interfaces to see if they have healed.
918                  */
919                 if (IS_RIP_IN_OFF(ifp->int_state)
920                     || ifp->int_query_time != NEVER)
921                         continue;
922
923                 /* skip turned off interfaces */
924                 if (!iff_up(ifp->int_if_flags))
925                         continue;
926
927                 buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1;
928                 buf.rip_cmd = RIPCMD_REQUEST;
929                 buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
930                 buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
931
932                 /* Send a RIPv1 query only if allowed and if we will
933                  * listen to RIPv1 routers.
934                  */
935                 if ((ifp->int_state & IS_NO_RIPV1_OUT)
936                     || (ifp->int_state & IS_NO_RIPV1_IN)) {
937                         buf.rip_vers = RIPv2;
938                 } else {
939                         buf.rip_vers = RIPv1;
940                 }
941
942                 if (ifp->int_if_flags & IFF_BROADCAST) {
943                         /* ordinary, hardware interface */
944                         dst.sin_addr.s_addr = ifp->int_brdaddr;
945
946                         /* Broadcast RIPv1 queries and RIPv2 queries
947                          * when the hardware cannot multicast.
948                          */
949                         if (buf.rip_vers == RIPv2
950                             && (ifp->int_if_flags & IFF_MULTICAST)
951                             && !(ifp->int_state  & IS_NO_RIP_MCAST)) {
952                                 type = OUT_MULTICAST;
953                         } else {
954                                 type = OUT_BROADCAST;
955                         }
956
957                 } else if (ifp->int_if_flags & IFF_POINTOPOINT) {
958                         /* point-to-point hardware interface */
959                         dst.sin_addr.s_addr = ifp->int_dstaddr;
960                         type = OUT_UNICAST;
961
962                 } else if (ifp->int_state & IS_REMOTE) {
963                         /* remote interface */
964                         dst.sin_addr.s_addr = ifp->int_addr;
965                         type = OUT_UNICAST;
966
967                 } else {
968                         /* ATM, HIPPI, etc. */
969                         continue;
970                 }
971
972                 ifp->int_query_time = now.tv_sec+SUPPLY_INTERVAL;
973                 if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
974                         if_sick(ifp);
975         }
976 }