output.c revision 15248
1132216Snjl/* 2131767Simp * Copyright (c) 1985, 1993 3131767Simp * The Regents of the University of California. All rights reserved. 4131767Simp * 5131767Simp * Copyright (c) 1995 John Hay. All rights reserved. 6131767Simp * 7131767Simp * This file includes significant work done at Cornell University by 8131767Simp * Bill Nesheim. That work included by permission. 9140040Simp * 10131767Simp * Redistribution and use in source and binary forms, with or without 11140040Simp * modification, are permitted provided that the following conditions 12140040Simp * are met: 13131767Simp * 1. Redistributions of source code must retain the above copyright 14131767Simp * notice, this list of conditions and the following disclaimer. 15131767Simp * 2. Redistributions in binary form must reproduce the above copyright 16131767Simp * notice, this list of conditions and the following disclaimer in the 17140040Simp * documentation and/or other materials provided with the distribution. 18140040Simp * 3. All advertising materials mentioning features or use of this software 19131767Simp * must display the following acknowledgement: 20131767Simp * This product includes software developed by the University of 21131767Simp * California, Berkeley and its contributors. 22131767Simp * 4. Neither the name of the University nor the names of its contributors 23131767Simp * may be used to endorse or promote products derived from this software 24131767Simp * without specific prior written permission. 25131767Simp * 26131767Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27131767Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28131767Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29131767Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30131767Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31131767Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32131767Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33131767Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34134081Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35131767Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36134081Sphk * SUCH DAMAGE. 37131767Simp * 38131767Simp * $Id: output.c,v 1.2 1995/12/05 04:59:54 julian Exp $ 39131767Simp */ 40132080Simp 41132080Simp#ifndef lint 42131767Simpstatic char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; 43131767Simp#endif /* not lint */ 44131767Simp 45131767Simp/* 46131767Simp * Routing Table Management Daemon 47131767Simp */ 48131767Simp#include "defs.h" 49131767Simp 50131767Simp/* 51131767Simp * Apply the function "f" to all non-passive 52131767Simp * interfaces. If the interface supports the 53131767Simp * use of broadcasting use it, otherwise address 54131767Simp * the output to the known router. 55132216Snjl */ 56132137Simpvoid 57132137Simptoall(f, except) 58135212Simp void (*f)(struct sockaddr *, int, struct interface *); 59132137Simp struct rt_entry *except; 60132139Simp{ 61132137Simp register struct interface *ifp; 62132137Simp register struct sockaddr *dst; 63132137Simp register int flags; 64132137Simp register struct rt_entry *trt; 65132137Simp int onlist; 66132137Simp extern struct interface *ifnet; 67132137Simp 68132137Simp for (ifp = ifnet; ifp; ifp = ifp->int_next) { 69135212Simp if (ifp->int_flags & IFF_PASSIVE) 70135212Simp continue; 71135212Simp 72135212Simp /* 73135212Simp * Don't send it on interfaces in the except list. 74132137Simp */ 75135212Simp onlist = 0; 76135212Simp trt = except; 77135212Simp while(trt) { 78135212Simp if (ifp == trt->rt_ifp) { 79135212Simp onlist = 1; 80135212Simp break; 81135212Simp } 82135504Simp trt = trt->rt_clone; 83136138Simp } 84135212Simp if (onlist) 85135212Simp continue; 86132137Simp 87132137Simp dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 88132137Simp ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 89135212Simp &ifp->int_addr; 90135212Simp flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 91135212Simp (*f)(dst, flags, ifp); 92132137Simp } 93135504Simp} 94132137Simp 95132137Simp/* 96132137Simp * Output a preformed packet. 97135212Simp */ 98135212Simpvoid 99135212Simpsndmsg(dst, flags, ifp) 100132137Simp struct sockaddr *dst; 101136138Simp int flags; 102135504Simp struct interface *ifp; 103135504Simp{ 104135504Simp 105135504Simp (*afswitch[dst->sa_family].af_output) 106135504Simp (ripsock, flags, dst, sizeof (struct rip)); 107135504Simp TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 108132137Simp} 109132137Simp 110132137Simp/* 111132137Simp * Supply dst with the contents of the routing tables. 112135504Simp * If this won't fit in one packet, chop it up into several. 113132137Simp * 114135212Simp * This must be done using the split horizon algorithm. 115132137Simp * 1. Don't send routing info to the interface from where it was received. 116132137Simp * 2. Don't publish an interface to itself. 117136138Simp * 3. If a route is received from more than one interface and the cost is 118132137Simp * the same, don't publish it on either interface. I am calling this 119136138Simp * clones. 120135504Simp */ 121135212Simpvoid 122135212Simpsupply(dst, flags, ifp) 123135212Simp struct sockaddr *dst; 124135212Simp int flags; 125135212Simp struct interface *ifp; 126135212Simp{ 127135212Simp register struct rt_entry *rt; 128135212Simp register struct rt_entry *crt; /* Clone route */ 129135212Simp register struct rthash *rh; 130135212Simp register struct netinfo *nn; 131135212Simp register struct netinfo *n = msg->rip_nets; 132135212Simp struct rthash *base = hosthash; 133135212Simp struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 134135212Simp af_output_t *output = afswitch[dst->sa_family].af_output; 135135212Simp int doinghost = 1, size, metric, ticks; 136132137Simp union ipx_net net; 137132137Simp 138132137Simp if (sipx->sipx_port == 0) 139135212Simp sipx->sipx_port = htons(IPXPORT_RIP); 140135212Simp 141135212Simp msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 142132137Simpagain: 143135504Simp for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) 144132137Simp for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 145132137Simp size = (char *)n - (char *)msg; 146135212Simp if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + 147135212Simp sizeof (msg->rip_cmd))) { 148135212Simp (*output)(ripsock, flags, dst, size); 149135212Simp TRACE_OUTPUT(ifp, dst, size); 150135212Simp n = msg->rip_nets; 151135212Simp } 152135212Simp 153135212Simp /* 154135212Simp * This should do rule one and two of the split horizon 155132137Simp * algorithm. 156132137Simp */ 157132137Simp if (rt->rt_ifp == ifp) 158135212Simp continue; 159132137Simp 160132137Simp /* 161135212Simp * Rule 3. 162132137Simp * Look if we have clones (different routes to the same 163132137Simp * place with exactly the same cost). 164132137Simp * 165132137Simp * We should not publish on any of the clone interfaces. 166132137Simp */ 167132137Simp crt = rt->rt_clone; 168132137Simp while (crt) { 169135212Simp if (crt->rt_ifp == ifp) 170132137Simp goto next; 171132137Simp crt = crt->rt_clone; 172132137Simp } 173132137Simp 174132137Simp sipx = (struct sockaddr_ipx *)&rt->rt_dst; 175135212Simp if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 176132137Simp sipx = (struct sockaddr_ipx *)&rt->rt_router; 177132137Simp if (rt->rt_metric == HOPCNT_INFINITY) 178132137Simp metric = HOPCNT_INFINITY; 179131767Simp else { 180131767Simp metric = rt->rt_metric + 1; 181134081Sphk /* 182131767Simp * We don't advertize routes with more than 15 hops. 183131767Simp */ 184131767Simp if (metric >= HOPCNT_INFINITY) 185131767Simp continue; 186131767Simp } 187131767Simp /* XXX One day we should cater for slow interfaces also. */ 188131767Simp ticks = rt->rt_ticks + 1; 189131767Simp net = sipx->sipx_addr.x_net; 190132137Simp 191131767Simp /* 192131767Simp * Make sure that we don't put out a two net entries 193132137Simp * for a pt to pt link (one for the G route, one for the if) 194134081Sphk * This is a kludge, and won't work if there are lots of nets. 195134081Sphk */ 196131767Simp for (nn = msg->rip_nets; nn < n; nn++) { 197131767Simp if (ipx_neteqnn(net, nn->rip_dst)) { 198131767Simp if (ticks < ntohs(nn->rip_ticks)) { 199131767Simp nn->rip_metric = htons(metric); 200131767Simp nn->rip_ticks = htons(ticks); 201132137Simp } else if ((ticks == ntohs(nn->rip_ticks)) && 202132137Simp (metric < ntohs(nn->rip_metric))) { 203132137Simp nn->rip_metric = htons(metric); 204132137Simp nn->rip_ticks = htons(ticks); 205132137Simp } 206132137Simp goto next; 207132137Simp } 208134580Simp } 209134081Sphk n->rip_dst = net; 210134081Sphk n->rip_metric = htons(metric); 211134081Sphk n->rip_ticks = htons(ticks); 212134081Sphk n++; 213132216Snjl next:; 214132216Snjl } 215132216Snjl if (doinghost) { 216132137Simp doinghost = 0; 217132137Simp base = nethash; 218131767Simp goto again; 219131767Simp } 220131767Simp if (n != msg->rip_nets) { 221132137Simp size = (char *)n - (char *)msg; 222131767Simp (*output)(ripsock, flags, dst, size); 223131767Simp TRACE_OUTPUT(ifp, dst, size); 224131767Simp } 225131767Simp} 226131767Simp