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