Home | History | Annotate | Line # | Download | only in routed
output.c revision 1.10
      1 /*	$NetBSD: output.c,v 1.10 1996/08/10 01:29:26 thorpej 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)
     37 #if 0
     38 static char sccsid[] = "@(#)output.c	8.1 (Berkeley) 6/5/93";
     39 #else
     40 static char rcsid[] = "$NetBSD: output.c,v 1.10 1996/08/10 01:29:26 thorpej Exp $";
     41 #endif
     42 #endif /* not lint */
     43 
     44 #include "defs.h"
     45 
     46 
     47 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 ws_buf {			/* info for each buffer */
     60 	    struct rip	*buf;
     61 	    struct netinfo *n;
     62 	    struct netinfo *base;
     63 	    struct netinfo *lim;
     64 	    enum output_type type;
     65 	} v12, v2;
     66 	char	metric;			/* adjust metrics by interface */
     67 	int	npackets;
     68 	u_int	state;
     69 #define	    WS_ST_FLASH	    0x001	/* send only changed routes */
     70 #define	    WS_ST_RIP2_SAFE 0x002	/* send RIPv2 safe for RIPv1 */
     71 #define	    WS_ST_RIP2_ALL  0x004	/* send full featured RIPv2 */
     72 #define	    WS_ST_AG	    0x008	/* ok to aggregate subnets */
     73 #define	    WS_ST_SUPER_AG  0x010	/* ok to aggregate networks */
     74 #define	    WS_ST_SUB_AG    0x020	/* aggregate subnets in odd case */
     75 #define	    WS_ST_QUERY	    0x040	/* responding to a query */
     76 #define	    WS_ST_TO_ON_NET 0x080	/* sending onto one of our nets */
     77 #define	    WS_ST_DEFAULT   0x100	/* faking a default */
     78 #define	    WS_ST_PM_RDISC  0x200	/* poor-man's router discovery */
     79 } ws;
     80 
     81 /* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
     82 union pkt_buf ripv12_buf;
     83 
     84 /* Another for only RIPv2 listeners */
     85 union pkt_buf rip_v2_buf;
     86 
     87 
     88 
     89 /* Send the contents of the global buffer via the non-multicast socket
     90  */
     91 int					/* <0 on failure */
     92 output(enum output_type type,
     93        struct sockaddr_in *dst,		/* send to here */
     94        struct interface *ifp,
     95        struct rip *buf,
     96        int size)			/* this many bytes */
     97 {
     98 	struct sockaddr_in sin;
     99 	int flags;
    100 	char *msg;
    101 	int res;
    102 	naddr tgt_mcast;
    103 	int soc;
    104 	int serrno;
    105 
    106 	sin = *dst;
    107 	if (sin.sin_port == 0)
    108 		sin.sin_port = htons(RIP_PORT);
    109 #ifdef _HAVE_SIN_LEN
    110 	if (sin.sin_len == 0)
    111 		sin.sin_len = sizeof(sin);
    112 #endif
    113 
    114 	soc = rip_sock;
    115 	flags = 0;
    116 
    117 	switch (type) {
    118 	case OUT_QUERY:
    119 		msg = "Answer Query";
    120 		if (soc < 0)
    121 			soc = ifp->int_rip_sock;
    122 		break;
    123 	case OUT_UNICAST:
    124 		msg = "Send";
    125 		if (soc < 0)
    126 			soc = ifp->int_rip_sock;
    127 		flags = MSG_DONTROUTE;
    128 		break;
    129 	case OUT_BROADCAST:
    130 		if (ifp->int_if_flags & IFF_POINTOPOINT) {
    131 			msg = "Send";
    132 		} else {
    133 			msg = "Send bcast";
    134 		}
    135 		flags = MSG_DONTROUTE;
    136 		break;
    137 	case OUT_MULTICAST:
    138 		if (ifp->int_if_flags & IFF_POINTOPOINT) {
    139 			msg = "Send pt-to-pt";
    140 		} else if (ifp->int_state & IS_DUP) {
    141 			trace_act("abort multicast output via %s"
    142 				  " with duplicate address\n",
    143 				  ifp->int_name);
    144 			return 0;
    145 		} else {
    146 			msg = "Send mcast";
    147 			if (rip_sock_mcast != ifp) {
    148 #ifdef MCAST_PPP_BUG
    149 				/* Do not specifiy the primary interface
    150 				 * explicitly if we have the multicast
    151 				 * point-to-point kernel bug, since the
    152 				 * kernel will do the wrong thing if the
    153 				 * local address of a point-to-point link
    154 				 * is the same as the address of an ordinary
    155 				 * interface.
    156 				 */
    157 				if (ifp->int_addr == myaddr) {
    158 					tgt_mcast = 0;
    159 				} else
    160 #endif
    161 				tgt_mcast = ifp->int_addr;
    162 				if (0 > setsockopt(rip_sock,
    163 						   IPPROTO_IP, IP_MULTICAST_IF,
    164 						   &tgt_mcast,
    165 						   sizeof(tgt_mcast))) {
    166 					serrno = errno;
    167 					LOGERR("setsockopt(rip_sock,"
    168 					       "IP_MULTICAST_IF)");
    169 					errno = serrno;
    170 					ifp = 0;
    171 					return -1;
    172 				}
    173 				rip_sock_mcast = ifp;
    174 			}
    175 			sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
    176 		}
    177 		break;
    178 
    179 	default:
    180 		/* Nothing; keep compilers happy. */
    181 	}
    182 
    183 	trace_rip(msg, "to", &sin, ifp, buf, size);
    184 
    185 	res = sendto(soc, buf, size, flags,
    186 		     (struct sockaddr *)&sin, sizeof(sin));
    187 	if (res < 0
    188 	    && (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
    189 		serrno = errno;
    190 		msglog("%s sendto(%s%s%s.%d): %s", msg,
    191 		       ifp != 0 ? ifp->int_name : "",
    192 		       ifp != 0 ? ", " : "",
    193 		       inet_ntoa(sin.sin_addr),
    194 		       ntohs(sin.sin_port),
    195 		       strerror(errno));
    196 		errno = serrno;
    197 	}
    198 
    199 	return res;
    200 }
    201 
    202 
    203 /* install authentication if appropriate
    204  */
    205 static void
    206 set_auth(struct ws_buf *w)
    207 {
    208 	if (ws.ifp != 0
    209 	    && ws.ifp->int_passwd[0] != '\0'
    210 	    && (ws.state & WS_ST_RIP2_SAFE)) {
    211 		w->n->n_family = RIP_AF_AUTH;
    212 		((struct netauth*)w->n)->a_type = RIP_AUTH_PW;
    213 		bcopy(ws.ifp->int_passwd, ((struct netauth*)w->n)->au.au_pw,
    214 		      sizeof(((struct netauth*)w->n)->au.au_pw));
    215 		w->n++;
    216 	}
    217 }
    218 
    219 
    220 /* Send the buffer
    221  */
    222 static void
    223 supply_write(struct ws_buf *wb)
    224 {
    225 	/* Output multicast only if legal.
    226 	 * If we would multcast and it would be illegal, then discard the
    227 	 * packet.
    228 	 */
    229 	switch (wb->type) {
    230 	case NO_OUT_MULTICAST:
    231 		trace_pkt("skip multicast to %s because impossible\n",
    232 			  naddr_ntoa(ws.to.sin_addr.s_addr));
    233 		break;
    234 	case NO_OUT_RIPV2:
    235 		break;
    236 	default:
    237 		if (output(wb->type, &ws.to, ws.ifp, wb->buf,
    238 			   ((char *)wb->n - (char*)wb->buf)) < 0
    239 		    && ws.ifp != 0)
    240 			if_sick(ws.ifp);
    241 		ws.npackets++;
    242 		break;
    243 	}
    244 
    245 	bzero(wb->n = wb->base, sizeof(*wb->n)*NETS_LEN);
    246 	if (wb->buf->rip_vers == RIPv2)
    247 		set_auth(wb);
    248 }
    249 
    250 
    251 /* put an entry into the packet
    252  */
    253 static void
    254 supply_out(struct ag_info *ag)
    255 {
    256 	int i;
    257 	naddr mask, v1_mask, s_mask, dst_h, ddst_h;
    258 	struct ws_buf *wb;
    259 
    260 
    261 	/* Skip this route if doing a flash update and it and the routes
    262 	 * it aggregates have not changed recently.
    263 	 */
    264 	if (ag->ag_seqno < update_seqno
    265 	    && (ws.state & WS_ST_FLASH))
    266 		return;
    267 
    268 	/* Skip this route if required by split-horizon
    269 	 */
    270 	if (ag->ag_state & AGS_SPLIT_HZ)
    271 		return;
    272 
    273 	dst_h = ag->ag_dst_h;
    274 	mask = ag->ag_mask;
    275 	v1_mask = ripv1_mask_host(htonl(dst_h),
    276 				  (ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0);
    277 	s_mask = std_mask(htonl(dst_h));
    278 	i = 0;
    279 
    280 	/* If we are sending RIPv2 packets that cannot (or must not) be
    281 	 * heard by RIPv1 listeners, do not worry about sub- or supernets.
    282 	 * Subnets (from other networks) can only be sent via multicast.
    283 	 * A pair of subnet routes might have been promoted so that they
    284 	 * are legal to send by RIPv1.
    285 	 * If RIPv1 is off, use the multicast buffer, unless this is the
    286 	 * fake default route and it is acting as a poor-man's router-
    287 	 * discovery mechanism.
    288 	 */
    289 	if (((ws.state & WS_ST_RIP2_ALL)
    290 	     && (dst_h != RIP_DEFAULT || !(ws.state & WS_ST_PM_RDISC)))
    291 	    || ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) {
    292 		/* use the RIPv2-only buffer */
    293 		wb = &ws.v2;
    294 
    295 	} else {
    296 		/* use the RIPv1-or-RIPv2 buffer */
    297 		wb = &ws.v12;
    298 
    299 		/* Convert supernet route into corresponding set of network
    300 		 * routes for RIPv1, but leave non-contiguous netmasks
    301 		 * to ag_check().
    302 		 */
    303 		if (v1_mask > mask
    304 		    && mask + (mask & -mask) == 0) {
    305 			ddst_h = v1_mask & -v1_mask;
    306 			i = (v1_mask & ~mask)/ddst_h;
    307 
    308 			if (i >= 1024) {
    309 				/* Punt if we would have to generate an
    310 				 * unreasonable number of routes.
    311 				 */
    312 #ifdef DEBUG
    313 				msglog("sending %s to %s as-is instead"
    314 				       " of as %d routes",
    315 				       addrname(htonl(dst_h),mask,0),
    316 				       naddr_ntoa(ws.to.sin_addr.s_addr), i);
    317 #endif
    318 				i = 0;
    319 
    320 			} else {
    321 				mask = v1_mask;
    322 			}
    323 		}
    324 	}
    325 
    326 	do {
    327 		wb->n->n_family = RIP_AF_INET;
    328 		wb->n->n_dst = htonl(dst_h);
    329 		/* If the route is from router-discovery or we are
    330 		 * shutting down, admit only a bad metric.
    331 		 */
    332 		wb->n->n_metric = ((stopint || ag->ag_metric < 1)
    333 				   ? HOPCNT_INFINITY
    334 				   : ag->ag_metric);
    335 		HTONL(wb->n->n_metric);
    336 		if (wb->buf->rip_vers == RIPv2) {
    337 			if (ag->ag_nhop != 0
    338 			    && (ws.state & WS_ST_RIP2_SAFE)
    339 			    && ((ws.state & WS_ST_QUERY)
    340 				|| (ag->ag_nhop != ws.ifp->int_addr
    341 				    && on_net(ag->ag_nhop,
    342 					      ws.ifp->int_net,
    343 					      ws.ifp->int_mask))))
    344 				wb->n->n_nhop = ag->ag_nhop;
    345 			if ((ws.state & WS_ST_RIP2_ALL)
    346 			    || mask != s_mask)
    347 				wb->n->n_mask = htonl(mask);
    348 			wb->n->n_tag = ag->ag_tag;
    349 		}
    350 		dst_h += ddst_h;
    351 
    352 		if (++wb->n >= wb->lim)
    353 			supply_write(wb);
    354 	} while (i-- != 0);
    355 }
    356 
    357 
    358 /* supply one route from the table
    359  */
    360 /* ARGSUSED */
    361 static int
    362 walk_supply(struct radix_node *rn, void *argp)
    363 {
    364 #define RT ((struct rt_entry *)rn)
    365 #if 0
    366 	struct walkarg *w = argp;	/* not used */
    367 #endif
    368 	u_short ags = 0;
    369 	char metric, pref;
    370 	naddr dst, nhop;
    371 
    372 
    373 	/* Do not advertise the loopback interface
    374 	 * or external remote interfaces
    375 	 */
    376 	if (RT->rt_ifp != 0
    377 	    && ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK)
    378 		|| (RT->rt_ifp->int_state & IS_EXTERNAL))
    379 	    && !(RT->rt_state & RS_MHOME))
    380 		return 0;
    381 
    382 	/* If being quiet about our ability to forward, then
    383 	 * do not say anything unless responding to a query.
    384 	 */
    385 	if (!supplier && !(ws.state & WS_ST_QUERY))
    386 		return 0;
    387 
    388 	dst = RT->rt_dst;
    389 
    390 	/* do not collide with the fake default route */
    391 	if (dst == RIP_DEFAULT
    392 	    && (ws.state & WS_ST_DEFAULT))
    393 		return 0;
    394 
    395 	if (RT->rt_state & RS_NET_SYN) {
    396 		if (RT->rt_state & RS_NET_INT) {
    397 			/* Do not send manual synthetic network routes
    398 			 * into the subnet.
    399 			 */
    400 			if (on_net(ws.to.sin_addr.s_addr,
    401 				   ntohl(dst), RT->rt_mask))
    402 				return 0;
    403 
    404 		} else {
    405 			/* Do not send automatic synthetic network routes
    406 			 * if they are not needed becaus no RIPv1 listeners
    407 			 * can hear them.
    408 			 */
    409 			if (ws.state & WS_ST_RIP2_ALL)
    410 				return 0;
    411 
    412 			/* Do not send automatic synthetic network routes to
    413 			 * the real subnet.
    414 			 */
    415 			if (on_net(ws.to.sin_addr.s_addr,
    416 				   ntohl(dst), RT->rt_mask))
    417 				return 0;
    418 		}
    419 		nhop = 0;
    420 
    421 	} else {
    422 		/* Advertise the next hop if this is not a route for one
    423 		 * of our interfaces and the next hop is on the same
    424 		 * network as the target.
    425 		 */
    426 		if (!(RT->rt_state & RS_IF)
    427 		    && RT->rt_gate != myaddr
    428 		    && RT->rt_gate != loopaddr)
    429 			nhop = RT->rt_gate;
    430 		else
    431 			nhop = 0;
    432 	}
    433 
    434 	/* Adjust the outgoing metric by the cost of the link.
    435 	 */
    436 	pref = metric = RT->rt_metric + ws.metric;
    437 	if (pref < HOPCNT_INFINITY) {
    438 		/* Keep track of the best metric with which the
    439 		 * route has been advertised recently.
    440 		 */
    441 		if (RT->rt_poison_metric >= metric
    442 		    || RT->rt_poison_time <= now_garbage) {
    443 			RT->rt_poison_time = now.tv_sec;
    444 			RT->rt_poison_metric = RT->rt_metric;
    445 		}
    446 
    447 	} else {
    448 		/* Do not advertise stable routes that will be ignored,
    449 		 * unless they are being held down and poisoned.  If the
    450 		 * route recently was advertised with a metric that would
    451 		 * have been less than infinity through this interface, we
    452 		 * need to continue to advertise it in order to poison it.
    453 		 */
    454 		pref = RT->rt_poison_metric + ws.metric;
    455 		if (pref >= HOPCNT_INFINITY)
    456 			return 0;
    457 
    458 		metric = HOPCNT_INFINITY;
    459 	}
    460 
    461 	if (RT->rt_state & RS_MHOME) {
    462 		/* retain host route of multi-homed servers */
    463 		;
    464 
    465 	} else if (RT_ISHOST(RT)) {
    466 		/* We should always aggregate the host routes
    467 		 * for the local end of our point-to-point links.
    468 		 * If we are suppressing host routes in general, then do so.
    469 		 * Avoid advertising host routes onto their own network,
    470 		 * where they should be handled by proxy-ARP.
    471 		 */
    472 		if ((RT->rt_state & RS_LOCAL)
    473 		    || ridhosts
    474 		    || (ws.state & WS_ST_SUPER_AG)
    475 		    || on_net(dst, ws.to_net, ws.to_mask))
    476 			ags |= AGS_SUPPRESS;
    477 
    478 		if (ws.state & WS_ST_SUPER_AG)
    479 			ags |= AGS_PROMOTE;
    480 
    481 	} else if (ws.state & WS_ST_AG) {
    482 		/* Aggregate network routes, if we are allowed.
    483 		 */
    484 		ags |= AGS_SUPPRESS;
    485 
    486 		/* Generate supernets if allowed.
    487 		 * If we can be heard by RIPv1 systems, we will
    488 		 * later convert back to ordinary nets.
    489 		 * This unifies dealing with received supernets.
    490 		 */
    491 		if ((RT->rt_state & RS_SUBNET)
    492 		    || (ws.state & WS_ST_SUPER_AG))
    493 			ags |= AGS_PROMOTE;
    494 
    495 	}
    496 
    497 	/* Do not send RIPv1 advertisements of subnets to other
    498 	 * networks. If possible, multicast them by RIPv2.
    499 	 */
    500 	if ((RT->rt_state & RS_SUBNET)
    501 	    && !(ws.state & WS_ST_RIP2_ALL)
    502 	    && !on_net(dst, ws.to_std_net, ws.to_std_mask)) {
    503 		ags |= AGS_RIPV2 | AGS_PROMOTE;
    504 		if (ws.state & WS_ST_SUB_AG)
    505 			ags |= AGS_SUPPRESS;
    506 	}
    507 
    508 	/* Do not send a route back to where it came from, except in
    509 	 * response to a query.  This is "split-horizon".  That means not
    510 	 * advertising back to the same network	and so via the same interface.
    511 	 *
    512 	 * We want to suppress routes that might have been fragmented
    513 	 * from this route by a RIPv1 router and sent back to us, and so we
    514 	 * cannot forget this route here.  Let the split-horizon route
    515 	 * aggregate (suppress) the fragmented routes and then itself be
    516 	 * forgotten.
    517 	 *
    518 	 * Include the routes for both ends of point-to-point interfaces
    519 	 * since the other side presumably knows them as well as we do.
    520 	 */
    521 	if (RT->rt_ifp == ws.ifp && ws.ifp != 0
    522 	    && !(ws.state & WS_ST_QUERY)
    523 	    && (ws.state & WS_ST_TO_ON_NET)
    524 	    && (!(RT->rt_state & RS_IF)
    525 		|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
    526 		ags |= AGS_SPLIT_HZ;
    527 		ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
    528 	}
    529 
    530 	ag_check(dst, RT->rt_mask, 0, nhop, metric, pref,
    531 		 RT->rt_seqno, RT->rt_tag, ags, supply_out);
    532 	return 0;
    533 #undef RT
    534 }
    535 
    536 
    537 /* Supply dst with the contents of the routing tables.
    538  * If this won't fit in one packet, chop it up into several.
    539  */
    540 void
    541 supply(struct sockaddr_in *dst,
    542        struct interface *ifp,		/* output interface */
    543        enum output_type type,
    544        int flash,			/* 1=flash update */
    545        int vers)			/* RIP version */
    546 {
    547 	static int init = 1;
    548 	struct rt_entry *rt;
    549 
    550 
    551 	ws.state = 0;
    552 
    553 	ws.to = *dst;
    554 	ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
    555 	ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;
    556 
    557 	if (ifp != 0) {
    558 		ws.to_mask = ifp->int_mask;
    559 		ws.to_net = ifp->int_net;
    560 		if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
    561 			ws.state |= WS_ST_TO_ON_NET;
    562 
    563 	} else {
    564 		ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
    565 		ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
    566 		rt = rtfind(dst->sin_addr.s_addr);
    567 		if (rt)
    568 			ifp = rt->rt_ifp;
    569 	}
    570 
    571 	ws.npackets = 0;
    572 	if (flash)
    573 		ws.state |= WS_ST_FLASH;
    574 	if (type == OUT_QUERY)
    575 		ws.state |= WS_ST_QUERY;
    576 
    577 	if ((ws.ifp = ifp) == 0) {
    578 		ws.metric = 1;
    579 	} else {
    580 		/* Adjust the advertised metric by the outgoing interface
    581 		 * metric.
    582 		 */
    583 		ws.metric = ifp->int_metric+1;
    584 	}
    585 
    586 	if (init) {
    587 		init = 0;
    588 
    589 		bzero(&ripv12_buf, sizeof(ripv12_buf));
    590 		ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE;
    591 		ws.v12.buf = &ripv12_buf.rip;
    592 		ws.v12.base = &ws.v12.buf->rip_nets[0];
    593 		ws.v12.lim = ws.v12.base + NETS_LEN;
    594 
    595 		bzero(&rip_v2_buf, sizeof(rip_v2_buf));
    596 		rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
    597 		rip_v2_buf.rip.rip_vers = RIPv2;
    598 		ws.v2.buf = &rip_v2_buf.rip;
    599 		ws.v2.base = &ws.v2.buf->rip_nets[0];
    600 		ws.v2.lim = ws.v2.base + NETS_LEN;
    601 	}
    602 	ripv12_buf.rip.rip_vers = vers;
    603 
    604 	ws.v12.n = ws.v12.base;
    605 	set_auth(&ws.v12);
    606 	ws.v2.n = ws.v2.base;
    607 	set_auth(&ws.v2);
    608 
    609 	switch (type) {
    610 	case OUT_BROADCAST:
    611 		ws.v2.type = ((ws.ifp != 0
    612 			       && (ws.ifp->int_if_flags & IFF_MULTICAST))
    613 			      ? OUT_MULTICAST
    614 			      : NO_OUT_MULTICAST);
    615 		ws.v12.type = OUT_BROADCAST;
    616 		break;
    617 	case OUT_MULTICAST:
    618 		ws.v2.type = ((ws.ifp != 0
    619 			       && (ws.ifp->int_if_flags & IFF_MULTICAST))
    620 			      ? OUT_MULTICAST
    621 			      : NO_OUT_MULTICAST);
    622 		ws.v12.type = OUT_BROADCAST;
    623 		break;
    624 	case OUT_UNICAST:
    625 	case OUT_QUERY:
    626 		ws.v2.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
    627 		ws.v12.type = type;
    628 		break;
    629 	default:
    630 		ws.v2.type = type;
    631 		ws.v12.type = type;
    632 		break;
    633 	}
    634 
    635 	if (vers == RIPv2) {
    636 		/* if asked to send RIPv2, send at least that which can
    637 		 * be safely heard by RIPv1 listeners.
    638 		 */
    639 		ws.state |= WS_ST_RIP2_SAFE;
    640 
    641 		/* full RIPv2 only if cannot be heard by RIPv1 listeners */
    642 		if (type != OUT_BROADCAST)
    643 			ws.state |= WS_ST_RIP2_ALL;
    644 		if (!(ws.state & WS_ST_TO_ON_NET)) {
    645 			ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
    646 		} else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
    647 			ws.state |= WS_ST_AG;
    648 			if (type != OUT_BROADCAST
    649 			    && (ws.ifp == 0
    650 				|| !(ws.ifp->int_state & IS_NO_SUPER_AG)))
    651 				ws.state |= WS_ST_SUPER_AG;
    652 		}
    653 
    654 	} else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
    655 		ws.state |= WS_ST_SUB_AG;
    656 	}
    657 
    658 	if (supplier) {
    659 		/*  Fake a default route if asked, and if there is not
    660 		 * a better, real default route.
    661 		 */
    662 		if (ifp->int_d_metric != 0
    663 		    && (0 == (rt = rtget(RIP_DEFAULT, 0))
    664 			|| rt->rt_metric+ws.metric >= ifp->int_d_metric)) {
    665 			ws.state |= WS_ST_DEFAULT;
    666 			ag_check(0, 0, 0, 0,
    667 				 ifp->int_d_metric,ifp->int_d_metric,
    668 				 0, 0, 0, supply_out);
    669 		}
    670 		if ((ws.state & WS_ST_RIP2_ALL)
    671 		    && (ifp->int_state & IS_PM_RDISC)) {
    672 			ws.state |= WS_ST_PM_RDISC;
    673 			ripv12_buf.rip.rip_vers = RIPv1;
    674 		}
    675 	}
    676 
    677 	(void)rn_walktree(rhead, walk_supply, 0);
    678 	ag_flush(0,0,supply_out);
    679 
    680 	/* Flush the packet buffers, provided they are not empty and
    681 	 * do not contain only the password.
    682 	 */
    683 	if (ws.v12.n != ws.v12.base
    684 	    && (ws.v12.n > ws.v12.base+1
    685 		|| ws.v12.n->n_family != RIP_AF_AUTH))
    686 		supply_write(&ws.v12);
    687 	if (ws.v2.n != ws.v2.base
    688 	    && (ws.v2.n > ws.v2.base+1
    689 		|| ws.v2.n->n_family != RIP_AF_AUTH))
    690 		supply_write(&ws.v2);
    691 
    692 	/* If we sent nothing and this is an answer to a query, send
    693 	 * an empty buffer.
    694 	 */
    695 	if (ws.npackets == 0
    696 	    && (ws.state & WS_ST_QUERY))
    697 		supply_write(&ws.v12);
    698 }
    699 
    700 
    701 /* send all of the routing table or just do a flash update
    702  */
    703 void
    704 rip_bcast(int flash)
    705 {
    706 #ifdef _HAVE_SIN_LEN
    707 	static struct sockaddr_in dst = {sizeof(dst), AF_INET};
    708 #else
    709 	static struct sockaddr_in dst = {AF_INET};
    710 #endif
    711 	struct interface *ifp;
    712 	enum output_type type;
    713 	int vers;
    714 	struct timeval rtime;
    715 
    716 
    717 	need_flash = 0;
    718 	intvl_random(&rtime, MIN_WAITTIME, MAX_WAITTIME);
    719 	no_flash = rtime;
    720 	timevaladd(&no_flash, &now);
    721 
    722 	if (rip_sock < 0)
    723 		return;
    724 
    725 	trace_act("send %s and inhibit dynamic updates for %.3f sec\n",
    726 		  flash ? "dynamic update" : "all routes",
    727 		  rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
    728 
    729 	for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
    730 		/* skip interfaces not doing RIP, those already queried,
    731 		 * and aliases.  Do try broken interfaces to see
    732 		 * if they have healed.
    733 		 */
    734 		if (0 != (ifp->int_state & (IS_PASSIVE | IS_ALIAS)))
    735 			continue;
    736 
    737 		/* skip turned off interfaces */
    738 		if (!iff_alive(ifp->int_if_flags))
    739 			continue;
    740 
    741 		/* default to RIPv1 output */
    742 		if (ifp->int_state & IS_NO_RIPV1_OUT) {
    743 			/* Say nothing if this interface is turned off */
    744 			if (ifp->int_state & IS_NO_RIPV2_OUT)
    745 				continue;
    746 			vers = RIPv2;
    747 		} else {
    748 			vers = RIPv1;
    749 		}
    750 
    751 		if (ifp->int_if_flags & IFF_BROADCAST) {
    752 			/* ordinary, hardware interface */
    753 			dst.sin_addr.s_addr = ifp->int_brdaddr;
    754 			/* if RIPv1 is not turned off, then broadcast so
    755 			 * that RIPv1 listeners can hear.
    756 			 */
    757 			if (vers == RIPv2
    758 			    && (ifp->int_state & IS_NO_RIPV1_OUT)) {
    759 				type = OUT_MULTICAST;
    760 			} else {
    761 				type = OUT_BROADCAST;
    762 			}
    763 
    764 		} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
    765 			/* point-to-point hardware interface */
    766 			dst.sin_addr.s_addr = ifp->int_dstaddr;
    767 			type = OUT_UNICAST;
    768 
    769 		} else {
    770 			/* remote interface */
    771 			dst.sin_addr.s_addr = ifp->int_addr;
    772 			type = OUT_UNICAST;
    773 		}
    774 
    775 		supply(&dst, ifp, type, flash, vers);
    776 	}
    777 
    778 	update_seqno++;			/* all routes are up to date */
    779 }
    780 
    781 
    782 /* Ask for routes
    783  * Do it only once to an interface, and not even after the interface
    784  * was broken and recovered.
    785  */
    786 void
    787 rip_query(void)
    788 {
    789 #ifdef _HAVE_SIN_LEN
    790 	static struct sockaddr_in dst = {sizeof(dst), AF_INET};
    791 #else
    792 	static struct sockaddr_in dst = {AF_INET};
    793 #endif
    794 	struct interface *ifp;
    795 	struct rip buf;
    796 	enum output_type type;
    797 
    798 
    799 	if (rip_sock < 0)
    800 		return;
    801 
    802 	bzero(&buf, sizeof(buf));
    803 
    804 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
    805 		/* skip interfaces not doing RIP, those already queried,
    806 		 * and aliases.  Do try broken interfaces to see
    807 		 * if they have healed.
    808 		 */
    809 		if (0 != (ifp->int_state & (IS_RIP_QUERIED
    810 					    | IS_PASSIVE | IS_ALIAS)))
    811 			continue;
    812 
    813 		/* skip turned off interfaces */
    814 		if (!iff_alive(ifp->int_if_flags))
    815 			continue;
    816 
    817 		/* default to RIPv1 output */
    818 		if (ifp->int_state & IS_NO_RIPV2_OUT) {
    819 			/* Say nothing if this interface is turned off */
    820 			if (ifp->int_state & IS_NO_RIPV1_OUT)
    821 				continue;
    822 			buf.rip_vers = RIPv1;
    823 		} else {
    824 			buf.rip_vers = RIPv2;
    825 		}
    826 
    827 		buf.rip_cmd = RIPCMD_REQUEST;
    828 		buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
    829 		buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
    830 
    831 		if (ifp->int_if_flags & IFF_BROADCAST) {
    832 			/* ordinary, hardware interface */
    833 			dst.sin_addr.s_addr = ifp->int_brdaddr;
    834 			/* if RIPv1 is not turned off, then broadcast so
    835 			 * that RIPv1 listeners can hear.
    836 			 */
    837 			if (buf.rip_vers == RIPv2
    838 			    && (ifp->int_state & IS_NO_RIPV1_OUT)) {
    839 				type = OUT_MULTICAST;
    840 			} else {
    841 				type = OUT_BROADCAST;
    842 			}
    843 
    844 		} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
    845 			/* point-to-point hardware interface */
    846 			dst.sin_addr.s_addr = ifp->int_dstaddr;
    847 			type = OUT_UNICAST;
    848 
    849 		} else {
    850 			/* remote interface */
    851 			dst.sin_addr.s_addr = ifp->int_addr;
    852 			type = OUT_UNICAST;
    853 		}
    854 
    855 		ifp->int_state |= IS_RIP_QUERIED;
    856 		if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
    857 			if_sick(ifp);
    858 	}
    859 }
    860