xref: /csrg-svn/sbin/XNSrouted/output.c (revision 25507)
1*25507Ssklower /*
2*25507Ssklower  * Copyright (c) 1985 Regents of the University of California.
3*25507Ssklower  * All rights reserved.  The Berkeley software License Agreement
4*25507Ssklower  * specifies the terms and conditions for redistribution.
5*25507Ssklower  *
6*25507Ssklower  * Includes material written at Cornell University by Bill Nesheim,
7*25507Ssklower  * by permission of the author.
8*25507Ssklower  */
9*25507Ssklower 
1024310Ssklower #ifndef lint
11*25507Ssklower static char sccsid[] = "@(#)output.c	5.4 (Berkeley) 11/20/85";
1224310Ssklower #endif
1324310Ssklower 
1424310Ssklower /*
1524310Ssklower  * Routing Table Management Daemon
1624310Ssklower  */
1724310Ssklower #include "defs.h"
1824310Ssklower 
1924310Ssklower /*
2024310Ssklower  * Apply the function "f" to all non-passive
2124310Ssklower  * interfaces.  If the interface supports the
2224310Ssklower  * use of broadcasting use it, otherwise address
2324310Ssklower  * the output to the known router.
2424310Ssklower  */
2524310Ssklower toall(f)
2624310Ssklower 	int (*f)();
2724310Ssklower {
2824310Ssklower 	register struct interface *ifp;
2924310Ssklower 	register struct sockaddr *dst;
3024310Ssklower 	register int flags;
3124310Ssklower 	extern struct interface *ifnet;
3224310Ssklower 
3324310Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
3424310Ssklower 		if (ifp->int_flags & IFF_PASSIVE)
3524310Ssklower 			continue;
3624310Ssklower 		dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
3724310Ssklower 		      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
3824310Ssklower 		      &ifp->int_addr;
3924310Ssklower 		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
4024310Ssklower 		(*f)(dst, flags, ifp);
4124310Ssklower 	}
4224310Ssklower }
4324310Ssklower 
4424310Ssklower /*
4524310Ssklower  * Output a preformed packet.
4624310Ssklower  */
4724310Ssklower /*ARGSUSED*/
4824310Ssklower sendmsg(dst, flags, ifp)
4924310Ssklower 	struct sockaddr *dst;
5024310Ssklower 	int flags;
5124310Ssklower 	struct interface *ifp;
5224310Ssklower {
5324310Ssklower 
5424317Ssklower 	(*afswitch[dst->sa_family].af_output)
5524317Ssklower 		(flags, dst, sizeof (struct rip));
5624310Ssklower 	TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
5724310Ssklower }
5824310Ssklower 
5924310Ssklower /*
6024310Ssklower  * Supply dst with the contents of the routing tables.
6124310Ssklower  * If this won't fit in one packet, chop it up into several.
6224310Ssklower  */
6324310Ssklower supply(dst, flags, ifp)
6424310Ssklower 	struct sockaddr *dst;
6524310Ssklower 	int flags;
6624310Ssklower 	struct interface *ifp;
6724310Ssklower {
6824310Ssklower 	register struct rt_entry *rt;
6924310Ssklower 	register struct rthash *rh;
7024322Ssklower 	register struct netinfo *nn;
7124322Ssklower 	register struct netinfo *n = msg->rip_nets;
7224310Ssklower 	struct rthash *base = hosthash;
7324317Ssklower 	struct sockaddr_ns *sns =  (struct sockaddr_ns *) dst;
7424310Ssklower 	int (*output)() = afswitch[dst->sa_family].af_output;
7524322Ssklower 	int doinghost = 1, size, metric;
7624322Ssklower 	long net;
7724310Ssklower 
7824310Ssklower 	msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
7924310Ssklower again:
8024310Ssklower 	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
8124310Ssklower 	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
8224310Ssklower 		size = (char *)n - (char *)msg;
8324310Ssklower 		if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
8424317Ssklower 			(*output)(flags, dst, size);
8524310Ssklower 			TRACE_OUTPUT(ifp, dst, size);
8624310Ssklower 			n = msg->rip_nets;
8724310Ssklower 		}
8824317Ssklower 		sns = (struct sockaddr_ns *)&rt->rt_dst;
89*25507Ssklower 	        if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
90*25507Ssklower 			sns = (struct sockaddr_ns *)&rt->rt_router;
9124322Ssklower 		metric = min(rt->rt_metric + 1, HOPCNT_INFINITY);
9224322Ssklower 		net = ns_netof(sns->sns_addr);
9324322Ssklower 		/*
9424322Ssklower 		 * Make sure that we don't put out a two net entries
9524322Ssklower 		 * for a pt to pt link (one for the G route, one for the if)
9624322Ssklower 		 * This is a kludge, and won't work if there are lots of nets.
9724322Ssklower 		 */
9824322Ssklower 		for (nn = msg->rip_nets; nn < n; nn++) {
9924322Ssklower 			if(net == xnnet(nn->rip_dst[0])) {
10024322Ssklower 				if(metric < ntohs(nn->rip_metric))
10124322Ssklower 					nn->rip_metric = htons(metric);
10224322Ssklower 				goto next;
10324322Ssklower 			}
10424322Ssklower 		}
10524322Ssklower 		xnnet(n->rip_dst[0]) = net;
10624322Ssklower 		n->rip_metric = htons(metric);
10724310Ssklower 		n++;
10824322Ssklower 	next:;
10924310Ssklower 	}
11024310Ssklower 	if (doinghost) {
11124310Ssklower 		doinghost = 0;
11224310Ssklower 		base = nethash;
11324310Ssklower 		goto again;
11424310Ssklower 	}
11524310Ssklower 	if (n != msg->rip_nets) {
11624310Ssklower 		size = (char *)n - (char *)msg;
11724317Ssklower 		(*output)(flags, dst, size);
11824310Ssklower 		TRACE_OUTPUT(ifp, dst, size);
11924310Ssklower 	}
12024310Ssklower }
121