output.c revision 22997
1/* 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (c) 1995 John Hay. All rights reserved. 6 * 7 * This file includes significant work done at Cornell University by 8 * Bill Nesheim. That work included by permission. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id$ 39 */ 40 41#ifndef lint 42static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; 43#endif /* not lint */ 44 45/* 46 * Routing Table Management Daemon 47 */ 48#include <unistd.h> 49#include "defs.h" 50 51/* 52 * Apply the function "f" to all non-passive 53 * interfaces. If the interface supports the 54 * use of broadcasting use it, otherwise address 55 * the output to the known router. 56 */ 57void 58toall(f, except) 59 void (*f)(struct sockaddr *, int, struct interface *); 60 struct rt_entry *except; 61{ 62 register struct interface *ifp; 63 register struct sockaddr *dst; 64 register int flags; 65 register struct rt_entry *trt; 66 int onlist; 67 extern struct interface *ifnet; 68 69 for (ifp = ifnet; ifp; ifp = ifp->int_next) { 70 if (ifp->int_flags & IFF_PASSIVE) 71 continue; 72 73 /* 74 * Don't send it on interfaces in the except list. 75 */ 76 onlist = 0; 77 trt = except; 78 while(trt) { 79 if (ifp == trt->rt_ifp) { 80 onlist = 1; 81 break; 82 } 83 trt = trt->rt_clone; 84 } 85 if (onlist) 86 continue; 87 88 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 89 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 90 &ifp->int_addr; 91 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 92 (*f)(dst, flags, ifp); 93 } 94} 95 96/* 97 * Output a preformed packet. 98 */ 99void 100sndmsg(dst, flags, ifp) 101 struct sockaddr *dst; 102 int flags; 103 struct interface *ifp; 104{ 105 106 (*afswitch[dst->sa_family].af_output) 107 (ripsock, flags, dst, sizeof (struct rip)); 108 TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 109} 110 111/* 112 * Supply dst with the contents of the routing tables. 113 * If this won't fit in one packet, chop it up into several. 114 * 115 * This must be done using the split horizon algorithm. 116 * 1. Don't send routing info to the interface from where it was received. 117 * 2. Don't publish an interface to itself. 118 * 3. If a route is received from more than one interface and the cost is 119 * the same, don't publish it on either interface. I am calling this 120 * clones. 121 */ 122void 123supply(dst, flags, ifp) 124 struct sockaddr *dst; 125 int flags; 126 struct interface *ifp; 127{ 128 register struct rt_entry *rt; 129 register struct rt_entry *crt; /* Clone route */ 130 register struct rthash *rh; 131 register struct netinfo *nn; 132 register struct netinfo *n = msg->rip_nets; 133 struct rthash *base = hosthash; 134 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 135 af_output_t *output = afswitch[dst->sa_family].af_output; 136 int doinghost = 1, size, metric, ticks; 137 union ipx_net net; 138 int delay = 0; 139 140 if (sipx->sipx_port == 0) 141 sipx->sipx_port = htons(IPXPORT_RIP); 142 143 msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 144again: 145 for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) 146 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 147 size = (char *)n - (char *)msg; 148 if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + 149 sizeof (msg->rip_cmd))) { 150 (*output)(ripsock, flags, dst, size); 151 TRACE_OUTPUT(ifp, dst, size); 152 n = msg->rip_nets; 153 delay++; 154 if(delay == 2) { 155 usleep(20000); 156 delay = 0; 157 } 158 } 159 160 /* 161 * This should do rule one and two of the split horizon 162 * algorithm. 163 */ 164 if (rt->rt_ifp == ifp) 165 continue; 166 167 /* 168 * Rule 3. 169 * Look if we have clones (different routes to the same 170 * place with exactly the same cost). 171 * 172 * We should not publish on any of the clone interfaces. 173 */ 174 crt = rt->rt_clone; 175 while (crt) { 176 if (crt->rt_ifp == ifp) 177 goto next; 178 crt = crt->rt_clone; 179 } 180 181 sipx = (struct sockaddr_ipx *)&rt->rt_dst; 182 if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 183 sipx = (struct sockaddr_ipx *)&rt->rt_router; 184 if (rt->rt_metric == HOPCNT_INFINITY) 185 metric = HOPCNT_INFINITY; 186 else { 187 metric = rt->rt_metric + 1; 188 /* 189 * We don't advertize routes with more than 15 hops. 190 */ 191 if (metric >= HOPCNT_INFINITY) 192 continue; 193 } 194 /* XXX One day we should cater for slow interfaces also. */ 195 ticks = rt->rt_ticks + 1; 196 net = sipx->sipx_addr.x_net; 197 198 /* 199 * Make sure that we don't put out a two net entries 200 * for a pt to pt link (one for the G route, one for the if) 201 * This is a kludge, and won't work if there are lots of nets. 202 */ 203 for (nn = msg->rip_nets; nn < n; nn++) { 204 if (ipx_neteqnn(net, nn->rip_dst)) { 205 if (ticks < ntohs(nn->rip_ticks)) { 206 nn->rip_metric = htons(metric); 207 nn->rip_ticks = htons(ticks); 208 } else if ((ticks == ntohs(nn->rip_ticks)) && 209 (metric < ntohs(nn->rip_metric))) { 210 nn->rip_metric = htons(metric); 211 nn->rip_ticks = htons(ticks); 212 } 213 goto next; 214 } 215 } 216 n->rip_dst = net; 217 n->rip_metric = htons(metric); 218 n->rip_ticks = htons(ticks); 219 n++; 220 next:; 221 } 222 if (doinghost) { 223 doinghost = 0; 224 base = nethash; 225 goto again; 226 } 227 if (n != msg->rip_nets) { 228 size = (char *)n - (char *)msg; 229 (*output)(ripsock, flags, dst, size); 230 TRACE_OUTPUT(ifp, dst, size); 231 } 232} 233