xref: /csrg-svn/sbin/XNSrouted/output.c (revision 35551)
125507Ssklower /*
2*35551Sbostic  * Copyright (c) 1985 The Regents of the University of California.
3*35551Sbostic  * All rights reserved.
425507Ssklower  *
5*35551Sbostic  * This file includes significant work done at Cornell University by
6*35551Sbostic  * Bill Nesheim.  That work included by permission.
7*35551Sbostic  *
8*35551Sbostic  * Redistribution and use in source and binary forms are permitted
9*35551Sbostic  * provided that the above copyright notice and this paragraph are
10*35551Sbostic  * duplicated in all such forms and that any documentation,
11*35551Sbostic  * advertising materials, and other materials related to such
12*35551Sbostic  * distribution and use acknowledge that the software was developed
13*35551Sbostic  * by the University of California, Berkeley.  The name of the
14*35551Sbostic  * University may not be used to endorse or promote products derived
15*35551Sbostic  * from this software without specific prior written permission.
16*35551Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*35551Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*35551Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1925507Ssklower  */
2025507Ssklower 
2124310Ssklower #ifndef lint
22*35551Sbostic static char sccsid[] = "@(#)output.c	5.6 (Berkeley) 09/19/88";
23*35551Sbostic #endif /* not lint */
2424310Ssklower 
2524310Ssklower /*
2624310Ssklower  * Routing Table Management Daemon
2724310Ssklower  */
2824310Ssklower #include "defs.h"
2924310Ssklower 
3024310Ssklower /*
3124310Ssklower  * Apply the function "f" to all non-passive
3224310Ssklower  * interfaces.  If the interface supports the
3324310Ssklower  * use of broadcasting use it, otherwise address
3424310Ssklower  * the output to the known router.
3524310Ssklower  */
3624310Ssklower toall(f)
3724310Ssklower 	int (*f)();
3824310Ssklower {
3924310Ssklower 	register struct interface *ifp;
4024310Ssklower 	register struct sockaddr *dst;
4124310Ssklower 	register int flags;
4224310Ssklower 	extern struct interface *ifnet;
4324310Ssklower 
4424310Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
4524310Ssklower 		if (ifp->int_flags & IFF_PASSIVE)
4624310Ssklower 			continue;
4724310Ssklower 		dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
4824310Ssklower 		      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
4924310Ssklower 		      &ifp->int_addr;
5024310Ssklower 		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
5124310Ssklower 		(*f)(dst, flags, ifp);
5224310Ssklower 	}
5324310Ssklower }
5424310Ssklower 
5524310Ssklower /*
5624310Ssklower  * Output a preformed packet.
5724310Ssklower  */
5824310Ssklower /*ARGSUSED*/
5924310Ssklower sendmsg(dst, flags, ifp)
6024310Ssklower 	struct sockaddr *dst;
6124310Ssklower 	int flags;
6224310Ssklower 	struct interface *ifp;
6324310Ssklower {
6424310Ssklower 
6524317Ssklower 	(*afswitch[dst->sa_family].af_output)
6624317Ssklower 		(flags, dst, sizeof (struct rip));
6724310Ssklower 	TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
6824310Ssklower }
6924310Ssklower 
7024310Ssklower /*
7124310Ssklower  * Supply dst with the contents of the routing tables.
7224310Ssklower  * If this won't fit in one packet, chop it up into several.
7324310Ssklower  */
7424310Ssklower supply(dst, flags, ifp)
7524310Ssklower 	struct sockaddr *dst;
7624310Ssklower 	int flags;
7724310Ssklower 	struct interface *ifp;
7824310Ssklower {
7924310Ssklower 	register struct rt_entry *rt;
8024310Ssklower 	register struct rthash *rh;
8124322Ssklower 	register struct netinfo *nn;
8224322Ssklower 	register struct netinfo *n = msg->rip_nets;
8324310Ssklower 	struct rthash *base = hosthash;
8424317Ssklower 	struct sockaddr_ns *sns =  (struct sockaddr_ns *) dst;
8524310Ssklower 	int (*output)() = afswitch[dst->sa_family].af_output;
8624322Ssklower 	int doinghost = 1, size, metric;
8726170Ssklower 	union ns_net net;
8824310Ssklower 
8924310Ssklower 	msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
9024310Ssklower again:
9124310Ssklower 	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
9224310Ssklower 	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
9324310Ssklower 		size = (char *)n - (char *)msg;
9424310Ssklower 		if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
9524317Ssklower 			(*output)(flags, dst, size);
9624310Ssklower 			TRACE_OUTPUT(ifp, dst, size);
9724310Ssklower 			n = msg->rip_nets;
9824310Ssklower 		}
9924317Ssklower 		sns = (struct sockaddr_ns *)&rt->rt_dst;
10025507Ssklower 	        if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
10125507Ssklower 			sns = (struct sockaddr_ns *)&rt->rt_router;
10224322Ssklower 		metric = min(rt->rt_metric + 1, HOPCNT_INFINITY);
10326170Ssklower 		net = sns->sns_addr.x_net;
10424322Ssklower 		/*
10524322Ssklower 		 * Make sure that we don't put out a two net entries
10624322Ssklower 		 * for a pt to pt link (one for the G route, one for the if)
10724322Ssklower 		 * This is a kludge, and won't work if there are lots of nets.
10824322Ssklower 		 */
10924322Ssklower 		for (nn = msg->rip_nets; nn < n; nn++) {
11026170Ssklower 			if (ns_neteqnn(net, nn->rip_dst)) {
11126170Ssklower 				if (metric < ntohs(nn->rip_metric))
11224322Ssklower 					nn->rip_metric = htons(metric);
11324322Ssklower 				goto next;
11424322Ssklower 			}
11524322Ssklower 		}
11626170Ssklower 		n->rip_dst = net;
11724322Ssklower 		n->rip_metric = htons(metric);
11824310Ssklower 		n++;
11924322Ssklower 	next:;
12024310Ssklower 	}
12124310Ssklower 	if (doinghost) {
12224310Ssklower 		doinghost = 0;
12324310Ssklower 		base = nethash;
12424310Ssklower 		goto again;
12524310Ssklower 	}
12624310Ssklower 	if (n != msg->rip_nets) {
12724310Ssklower 		size = (char *)n - (char *)msg;
12824317Ssklower 		(*output)(flags, dst, size);
12924310Ssklower 		TRACE_OUTPUT(ifp, dst, size);
13024310Ssklower 	}
13124310Ssklower }
132