output.c revision 122760
1155192Srwatson/* 2155192Srwatson * Copyright (c) 1985, 1993 3155192Srwatson * The Regents of the University of California. All rights reserved. 4155192Srwatson * 5155192Srwatson * Copyright (c) 1995 John Hay. All rights reserved. 6155192Srwatson * 7155192Srwatson * This file includes significant work done at Cornell University by 8155192Srwatson * Bill Nesheim. That work included by permission. 9155192Srwatson * 10155192Srwatson * Redistribution and use in source and binary forms, with or without 11155192Srwatson * modification, are permitted provided that the following conditions 12155192Srwatson * are met: 13155192Srwatson * 1. Redistributions of source code must retain the above copyright 14155192Srwatson * notice, this list of conditions and the following disclaimer. 15155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright 16155192Srwatson * notice, this list of conditions and the following disclaimer in the 17155192Srwatson * documentation and/or other materials provided with the distribution. 18155192Srwatson * 3. All advertising materials mentioning features or use of this software 19155192Srwatson * must display the following acknowledgement: 20155192Srwatson * This product includes software developed by the University of 21155192Srwatson * California, Berkeley and its contributors. 22155192Srwatson * 4. Neither the name of the University nor the names of its contributors 23155192Srwatson * may be used to endorse or promote products derived from this software 24155192Srwatson * without specific prior written permission. 25155192Srwatson * 26155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28155192Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29155192Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30155192Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31155192Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32155192Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33155192Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34155192Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35155192Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36155192Srwatson * SUCH DAMAGE. 37155192Srwatson * 38159259Srwatson * $FreeBSD: head/usr.sbin/IPXrouted/output.c 122760 2003-11-15 17:10:56Z trhodes $ 39155192Srwatson */ 40155192Srwatson 41155192Srwatson#ifndef lint 42155192Srwatsonstatic const char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; 43155192Srwatson#endif /* not lint */ 44155192Srwatson 45155192Srwatson/* 46155192Srwatson * Routing Table Management Daemon 47155192Srwatson */ 48155192Srwatson#include <unistd.h> 49155192Srwatson#include "defs.h" 50155192Srwatson 51155192Srwatson/* 52155192Srwatson * Apply the function "f" to all non-passive 53155192Srwatson * interfaces. If the interface supports the 54155192Srwatson * use of broadcasting use it, otherwise address 55155192Srwatson * the output to the known router. 56155192Srwatson */ 57155192Srwatsonvoid 58155192Srwatsontoall(f, except, changesonly) 59155192Srwatson void (*f)(struct sockaddr *, int, struct interface *, int); 60155192Srwatson struct rt_entry *except; 61155192Srwatson int changesonly; 62155192Srwatson{ 63155192Srwatson register struct interface *ifp; 64155192Srwatson register struct sockaddr *dst; 65155192Srwatson register int flags; 66155192Srwatson register struct rt_entry *trt; 67155192Srwatson int onlist; 68155192Srwatson extern struct interface *ifnet; 69155192Srwatson 70155192Srwatson for (ifp = ifnet; ifp; ifp = ifp->int_next) { 71155192Srwatson if (ifp->int_flags & IFF_PASSIVE) 72155192Srwatson continue; 73155192Srwatson 74155192Srwatson /* 75155192Srwatson * Don't send it on interfaces in the except list. 76155192Srwatson */ 77155192Srwatson onlist = 0; 78155192Srwatson trt = except; 79155192Srwatson while(trt) { 80155192Srwatson if (ifp == trt->rt_ifp) { 81155192Srwatson onlist = 1; 82155192Srwatson break; 83155192Srwatson } 84155192Srwatson trt = trt->rt_clone; 85155192Srwatson } 86155192Srwatson if (onlist) 87155192Srwatson continue; 88155192Srwatson 89155192Srwatson dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 90155192Srwatson ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 91155192Srwatson &ifp->int_addr; 92155192Srwatson flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 93155192Srwatson (*f)(dst, flags, ifp, changesonly); 94155192Srwatson } 95155192Srwatson} 96155192Srwatson 97155192Srwatson/* 98155192Srwatson * Output a preformed packet. 99155192Srwatson */ 100155192Srwatsonvoid 101155192Srwatsonsndmsg(dst, flags, ifp, changesonly) 102155192Srwatson struct sockaddr *dst; 103155192Srwatson int flags; 104155192Srwatson struct interface *ifp; 105155192Srwatson int changesonly; 106155192Srwatson{ 107155192Srwatson 108155192Srwatson (*afswitch[dst->sa_family].af_output) 109155192Srwatson (ripsock, flags, dst, sizeof (struct rip)); 110155192Srwatson TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 111155192Srwatson} 112155192Srwatson 113155192Srwatson/* 114155192Srwatson * Supply dst with the contents of the routing tables. 115155192Srwatson * If this won't fit in one packet, chop it up into several. 116155192Srwatson * 117155192Srwatson * This must be done using the split horizon algorithm. 118155192Srwatson * 1. Don't send routing info to the interface from where it was received. 119155192Srwatson * 2. Don't publish an interface to itself. 120155192Srwatson * 3. If a route is received from more than one interface and the cost is 121155192Srwatson * the same, don't publish it on either interface. I am calling this 122155192Srwatson * clones. 123155192Srwatson */ 124155192Srwatsonvoid 125155192Srwatsonsupply(dst, flags, ifp, changesonly) 126155192Srwatson struct sockaddr *dst; 127155192Srwatson int flags; 128155192Srwatson struct interface *ifp; 129155192Srwatson int changesonly; 130155192Srwatson{ 131155192Srwatson register struct rt_entry *rt; 132155192Srwatson register struct rt_entry *crt; /* Clone route */ 133155192Srwatson register struct rthash *rh; 134155192Srwatson register struct netinfo *nn; 135155192Srwatson register struct netinfo *n = msg->rip_nets; 136155192Srwatson struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 137155192Srwatson af_output_t *output = afswitch[dst->sa_family].af_output; 138155192Srwatson int size, metric, ticks; 139155192Srwatson union ipx_net net; 140155192Srwatson int delay = 0; 141155192Srwatson 142155192Srwatson if (sipx->sipx_port == 0) 143155192Srwatson sipx->sipx_port = htons(IPXPORT_RIP); 144155192Srwatson 145155192Srwatson msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 146155192Srwatson for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) 147155192Srwatson for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 148155192Srwatson size = (char *)n - (char *)msg; 149155192Srwatson if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + 150155192Srwatson sizeof (msg->rip_cmd))) { 151155192Srwatson (*output)(ripsock, flags, dst, size); 152155192Srwatson TRACE_OUTPUT(ifp, dst, size); 153155192Srwatson n = msg->rip_nets; 154155192Srwatson delay++; 155155192Srwatson if(delay == 2) { 156155192Srwatson usleep(50000); 157155192Srwatson delay = 0; 158155192Srwatson } 159155192Srwatson } 160155192Srwatson 161155192Srwatson if (changesonly && !(rt->rt_state & RTS_CHANGED)) 162155192Srwatson continue; 163155192Srwatson 164155192Srwatson /* 165155192Srwatson * This should do rule one and two of the split horizon 166155192Srwatson * algorithm. 167155192Srwatson */ 168155192Srwatson if (rt->rt_ifp == ifp) 169155192Srwatson continue; 170155192Srwatson 171155192Srwatson /* 172155192Srwatson * Rule 3. 173155192Srwatson * Look if we have clones (different routes to the same 174155192Srwatson * place with exactly the same cost). 175155192Srwatson * 176155192Srwatson * We should not publish on any of the clone interfaces. 177155192Srwatson */ 178155192Srwatson crt = rt->rt_clone; 179155192Srwatson while (crt) { 180155192Srwatson if (crt->rt_ifp == ifp) 181168783Srwatson goto next; 182168783Srwatson crt = crt->rt_clone; 183168783Srwatson } 184168783Srwatson 185155192Srwatson sipx = (struct sockaddr_ipx *)&rt->rt_dst; 186168783Srwatson if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 187168783Srwatson sipx = (struct sockaddr_ipx *)&rt->rt_router; 188168783Srwatson if (rt->rt_metric == HOPCNT_INFINITY) 189168783Srwatson metric = HOPCNT_INFINITY; 190168783Srwatson else { 191168783Srwatson metric = rt->rt_metric + 1; 192168783Srwatson /* 193168783Srwatson * We don't advertize routes with more than 15 hops. 194168783Srwatson */ 195168783Srwatson if (metric >= HOPCNT_INFINITY) 196168783Srwatson continue; 197168783Srwatson } 198168783Srwatson /* XXX One day we should cater for slow interfaces also. */ 199168783Srwatson ticks = rt->rt_ticks + 1; 200168783Srwatson net = sipx->sipx_addr.x_net; 201168783Srwatson 202168783Srwatson /* 203168783Srwatson * Make sure that we don't put out a two net entries 204168783Srwatson * for a pt to pt link (one for the G route, one for the if) 205168783Srwatson * This is a kludge, and won't work if there are lots of nets. 206168783Srwatson */ 207168783Srwatson for (nn = msg->rip_nets; nn < n; nn++) { 208168783Srwatson if (ipx_neteqnn(net, nn->rip_dst)) { 209168783Srwatson if (ticks < ntohs(nn->rip_ticks)) { 210168783Srwatson nn->rip_metric = htons(metric); 211168783Srwatson nn->rip_ticks = htons(ticks); 212168783Srwatson } else if ((ticks == ntohs(nn->rip_ticks)) && 213168783Srwatson (metric < ntohs(nn->rip_metric))) { 214168783Srwatson nn->rip_metric = htons(metric); 215168783Srwatson nn->rip_ticks = htons(ticks); 216168783Srwatson } 217168783Srwatson goto next; 218168783Srwatson } 219155192Srwatson } 220155192Srwatson n->rip_dst = net; 221155192Srwatson n->rip_metric = htons(metric); 222155192Srwatson n->rip_ticks = htons(ticks); 223155192Srwatson n++; 224155192Srwatson next:; 225155192Srwatson } 226155192Srwatson if (n != msg->rip_nets) { 227155192Srwatson size = (char *)n - (char *)msg; 228155192Srwatson (*output)(ripsock, flags, dst, size); 229155192Srwatson TRACE_OUTPUT(ifp, dst, size); 230155192Srwatson } 231155192Srwatson} 232155192Srwatson