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