1 /* 2 * Copyright (c) 1985 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This file includes significant work done at Cornell University by 6 * Bill Nesheim. That work included by permission. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)output.c 5.8 (Berkeley) 02/26/91"; 13 #endif /* not lint */ 14 15 /* 16 * Routing Table Management Daemon 17 */ 18 #include "defs.h" 19 20 /* 21 * Apply the function "f" to all non-passive 22 * interfaces. If the interface supports the 23 * use of broadcasting use it, otherwise address 24 * the output to the known router. 25 */ 26 toall(f) 27 int (*f)(); 28 { 29 register struct interface *ifp; 30 register struct sockaddr *dst; 31 register int flags; 32 extern struct interface *ifnet; 33 34 for (ifp = ifnet; ifp; ifp = ifp->int_next) { 35 if (ifp->int_flags & IFF_PASSIVE) 36 continue; 37 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 38 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 39 &ifp->int_addr; 40 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 41 (*f)(dst, flags, ifp); 42 } 43 } 44 45 /* 46 * Output a preformed packet. 47 */ 48 /*ARGSUSED*/ 49 sndmsg(dst, flags, ifp) 50 struct sockaddr *dst; 51 int flags; 52 struct interface *ifp; 53 { 54 55 (*afswitch[dst->sa_family].af_output) 56 (flags, dst, sizeof (struct rip)); 57 TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 58 } 59 60 /* 61 * Supply dst with the contents of the routing tables. 62 * If this won't fit in one packet, chop it up into several. 63 */ 64 supply(dst, flags, ifp) 65 struct sockaddr *dst; 66 int flags; 67 struct interface *ifp; 68 { 69 register struct rt_entry *rt; 70 register struct rthash *rh; 71 register struct netinfo *nn; 72 register struct netinfo *n = msg->rip_nets; 73 struct rthash *base = hosthash; 74 struct sockaddr_ns *sns = (struct sockaddr_ns *) dst; 75 int (*output)() = afswitch[dst->sa_family].af_output; 76 int doinghost = 1, size, metric; 77 union ns_net net; 78 79 msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 80 again: 81 for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) 82 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 83 size = (char *)n - (char *)msg; 84 if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { 85 (*output)(flags, dst, size); 86 TRACE_OUTPUT(ifp, dst, size); 87 n = msg->rip_nets; 88 } 89 sns = (struct sockaddr_ns *)&rt->rt_dst; 90 if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 91 sns = (struct sockaddr_ns *)&rt->rt_router; 92 metric = min(rt->rt_metric + 1, HOPCNT_INFINITY); 93 net = sns->sns_addr.x_net; 94 /* 95 * Make sure that we don't put out a two net entries 96 * for a pt to pt link (one for the G route, one for the if) 97 * This is a kludge, and won't work if there are lots of nets. 98 */ 99 for (nn = msg->rip_nets; nn < n; nn++) { 100 if (ns_neteqnn(net, nn->rip_dst)) { 101 if (metric < ntohs(nn->rip_metric)) 102 nn->rip_metric = htons(metric); 103 goto next; 104 } 105 } 106 n->rip_dst = net; 107 n->rip_metric = htons(metric); 108 n++; 109 next:; 110 } 111 if (doinghost) { 112 doinghost = 0; 113 base = nethash; 114 goto again; 115 } 116 if (n != msg->rip_nets) { 117 size = (char *)n - (char *)msg; 118 (*output)(flags, dst, size); 119 TRACE_OUTPUT(ifp, dst, size); 120 } 121 } 122