1 /* 2 * Copyright (c) 1983, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 06/05/93"; 10 #endif /* not lint */ 11 12 /* 13 * Routing Table Management Daemon 14 */ 15 #include "defs.h" 16 17 /* 18 * Apply the function "f" to all non-passive 19 * interfaces. If the interface supports the 20 * use of broadcasting use it, otherwise address 21 * the output to the known router. 22 */ 23 toall(f, rtstate, skipif) 24 int (*f)(); 25 int rtstate; 26 struct interface *skipif; 27 { 28 register struct interface *ifp; 29 register struct sockaddr *dst; 30 register int flags; 31 extern struct interface *ifnet; 32 33 for (ifp = ifnet; ifp; ifp = ifp->int_next) { 34 if (ifp->int_flags & IFF_PASSIVE || ifp == skipif) 35 continue; 36 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 37 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 38 &ifp->int_addr; 39 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 40 (*f)(dst, flags, ifp, rtstate); 41 } 42 } 43 44 /* 45 * Output a preformed packet. 46 */ 47 /*ARGSUSED*/ 48 sndmsg(dst, flags, ifp, rtstate) 49 struct sockaddr *dst; 50 int flags; 51 struct interface *ifp; 52 int rtstate; 53 { 54 55 (*afswitch[dst->sa_family].af_output)(s, flags, 56 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, rtstate) 65 struct sockaddr *dst; 66 int flags; 67 register struct interface *ifp; 68 int rtstate; 69 { 70 register struct rt_entry *rt; 71 register struct netinfo *n = msg->rip_nets; 72 register struct rthash *rh; 73 struct rthash *base = hosthash; 74 int doinghost = 1, size; 75 int (*output)() = afswitch[dst->sa_family].af_output; 76 int (*sendroute)() = afswitch[dst->sa_family].af_sendroute; 77 int npackets = 0; 78 79 msg->rip_cmd = RIPCMD_RESPONSE; 80 msg->rip_vers = RIPVERSION; 81 bzero(msg->rip_res1, sizeof(msg->rip_res1)); 82 again: 83 for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) 84 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 85 /* 86 * Don't resend the information on the network 87 * from which it was received (unless sending 88 * in response to a query). 89 */ 90 if (ifp && rt->rt_ifp == ifp && 91 (rt->rt_state & RTS_INTERFACE) == 0) 92 continue; 93 if (rt->rt_state & RTS_EXTERNAL) 94 continue; 95 /* 96 * For dynamic updates, limit update to routes 97 * with the specified state. 98 */ 99 if (rtstate && (rt->rt_state & rtstate) == 0) 100 continue; 101 /* 102 * Limit the spread of subnet information 103 * to those who are interested. 104 */ 105 if (doinghost == 0 && rt->rt_state & RTS_SUBNET) { 106 if (rt->rt_dst.sa_family != dst->sa_family) 107 continue; 108 if ((*sendroute)(rt, dst) == 0) 109 continue; 110 } 111 size = (char *)n - packet; 112 if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { 113 TRACE_OUTPUT(ifp, dst, size); 114 (*output)(s, flags, dst, size); 115 /* 116 * If only sending to ourselves, 117 * one packet is enough to monitor interface. 118 */ 119 if (ifp && (ifp->int_flags & 120 (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0) 121 return; 122 n = msg->rip_nets; 123 npackets++; 124 } 125 n->rip_dst = rt->rt_dst; 126 #if BSD < 198810 127 if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 128 n->rip_dst.sa_family = htons(n->rip_dst.sa_family); 129 #else 130 #define osa(x) ((struct osockaddr *)(&(x))) 131 osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family); 132 #endif 133 n->rip_metric = htonl(rt->rt_metric); 134 n++; 135 } 136 if (doinghost) { 137 doinghost = 0; 138 base = nethash; 139 goto again; 140 } 141 if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) { 142 size = (char *)n - packet; 143 TRACE_OUTPUT(ifp, dst, size); 144 (*output)(s, flags, dst, size); 145 } 146 } 147