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