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