xref: /csrg-svn/sbin/XNSrouted/output.c (revision 61474)
125507Ssklower /*
2*61474Sbostic  * Copyright (c) 1985, 1993
3*61474Sbostic  *	The Regents of the University of California.  All rights reserved.
425507Ssklower  *
535551Sbostic  * This file includes significant work done at Cornell University by
635551Sbostic  * Bill Nesheim.  That work included by permission.
735551Sbostic  *
842698Sbostic  * %sccs.include.redist.c%
925507Ssklower  */
1025507Ssklower 
1124310Ssklower #ifndef lint
12*61474Sbostic static char sccsid[] = "@(#)output.c	8.1 (Berkeley) 06/05/93";
1335551Sbostic #endif /* not lint */
1424310Ssklower 
1524310Ssklower /*
1624310Ssklower  * Routing Table Management Daemon
1724310Ssklower  */
1824310Ssklower #include "defs.h"
1924310Ssklower 
2024310Ssklower /*
2124310Ssklower  * Apply the function "f" to all non-passive
2224310Ssklower  * interfaces.  If the interface supports the
2324310Ssklower  * use of broadcasting use it, otherwise address
2424310Ssklower  * the output to the known router.
2524310Ssklower  */
2624310Ssklower toall(f)
2724310Ssklower 	int (*f)();
2824310Ssklower {
2924310Ssklower 	register struct interface *ifp;
3024310Ssklower 	register struct sockaddr *dst;
3124310Ssklower 	register int flags;
3224310Ssklower 	extern struct interface *ifnet;
3324310Ssklower 
3424310Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
3524310Ssklower 		if (ifp->int_flags & IFF_PASSIVE)
3624310Ssklower 			continue;
3724310Ssklower 		dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
3824310Ssklower 		      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
3924310Ssklower 		      &ifp->int_addr;
4024310Ssklower 		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
4124310Ssklower 		(*f)(dst, flags, ifp);
4224310Ssklower 	}
4324310Ssklower }
4424310Ssklower 
4524310Ssklower /*
4624310Ssklower  * Output a preformed packet.
4724310Ssklower  */
4824310Ssklower /*ARGSUSED*/
4946705Sbostic sndmsg(dst, flags, ifp)
5024310Ssklower 	struct sockaddr *dst;
5124310Ssklower 	int flags;
5224310Ssklower 	struct interface *ifp;
5324310Ssklower {
5424310Ssklower 
5524317Ssklower 	(*afswitch[dst->sa_family].af_output)
5624317Ssklower 		(flags, dst, sizeof (struct rip));
5724310Ssklower 	TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
5824310Ssklower }
5924310Ssklower 
6024310Ssklower /*
6124310Ssklower  * Supply dst with the contents of the routing tables.
6224310Ssklower  * If this won't fit in one packet, chop it up into several.
6324310Ssklower  */
6424310Ssklower supply(dst, flags, ifp)
6524310Ssklower 	struct sockaddr *dst;
6624310Ssklower 	int flags;
6724310Ssklower 	struct interface *ifp;
6824310Ssklower {
6924310Ssklower 	register struct rt_entry *rt;
7024310Ssklower 	register struct rthash *rh;
7124322Ssklower 	register struct netinfo *nn;
7224322Ssklower 	register struct netinfo *n = msg->rip_nets;
7324310Ssklower 	struct rthash *base = hosthash;
7424317Ssklower 	struct sockaddr_ns *sns =  (struct sockaddr_ns *) dst;
7524310Ssklower 	int (*output)() = afswitch[dst->sa_family].af_output;
7624322Ssklower 	int doinghost = 1, size, metric;
7726170Ssklower 	union ns_net net;
7824310Ssklower 
7924310Ssklower 	msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
8024310Ssklower again:
8124310Ssklower 	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
8224310Ssklower 	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
8324310Ssklower 		size = (char *)n - (char *)msg;
8424310Ssklower 		if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
8524317Ssklower 			(*output)(flags, dst, size);
8624310Ssklower 			TRACE_OUTPUT(ifp, dst, size);
8724310Ssklower 			n = msg->rip_nets;
8824310Ssklower 		}
8924317Ssklower 		sns = (struct sockaddr_ns *)&rt->rt_dst;
9025507Ssklower 	        if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
9125507Ssklower 			sns = (struct sockaddr_ns *)&rt->rt_router;
9224322Ssklower 		metric = min(rt->rt_metric + 1, HOPCNT_INFINITY);
9326170Ssklower 		net = sns->sns_addr.x_net;
9424322Ssklower 		/*
9524322Ssklower 		 * Make sure that we don't put out a two net entries
9624322Ssklower 		 * for a pt to pt link (one for the G route, one for the if)
9724322Ssklower 		 * This is a kludge, and won't work if there are lots of nets.
9824322Ssklower 		 */
9924322Ssklower 		for (nn = msg->rip_nets; nn < n; nn++) {
10026170Ssklower 			if (ns_neteqnn(net, nn->rip_dst)) {
10126170Ssklower 				if (metric < ntohs(nn->rip_metric))
10224322Ssklower 					nn->rip_metric = htons(metric);
10324322Ssklower 				goto next;
10424322Ssklower 			}
10524322Ssklower 		}
10626170Ssklower 		n->rip_dst = net;
10724322Ssklower 		n->rip_metric = htons(metric);
10824310Ssklower 		n++;
10924322Ssklower 	next:;
11024310Ssklower 	}
11124310Ssklower 	if (doinghost) {
11224310Ssklower 		doinghost = 0;
11324310Ssklower 		base = nethash;
11424310Ssklower 		goto again;
11524310Ssklower 	}
11624310Ssklower 	if (n != msg->rip_nets) {
11724310Ssklower 		size = (char *)n - (char *)msg;
11824317Ssklower 		(*output)(flags, dst, size);
11924310Ssklower 		TRACE_OUTPUT(ifp, dst, size);
12024310Ssklower 	}
12124310Ssklower }
122