output.c revision 19948
1122940Speter/* 240003Skato * Copyright (c) 1985, 1993 324113Skato * The Regents of the University of California. All rights reserved. 424113Skato * 524113Skato * Copyright (c) 1995 John Hay. All rights reserved. 624113Skato * 724113Skato * This file includes significant work done at Cornell University by 824113Skato * Bill Nesheim. That work included by permission. 924113Skato * 1024113Skato * Redistribution and use in source and binary forms, with or without 1124113Skato * modification, are permitted provided that the following conditions 1224113Skato * are met: 1324113Skato * 1. Redistributions of source code must retain the above copyright 1424113Skato * notice, this list of conditions and the following disclaimer. 1524113Skato * 2. Redistributions in binary form must reproduce the above copyright 1624113Skato * notice, this list of conditions and the following disclaimer in the 1724113Skato * documentation and/or other materials provided with the distribution. 1824113Skato * 3. All advertising materials mentioning features or use of this software 1924113Skato * must display the following acknowledgement: 2024113Skato * This product includes software developed by the University of 2124113Skato * California, Berkeley and its contributors. 2224113Skato * 4. Neither the name of the University nor the names of its contributors 2324113Skato * may be used to endorse or promote products derived from this software 2424113Skato * without specific prior written permission. 2524113Skato * 2624113Skato * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2724113Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2824113Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2924113Skato * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30118031Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31118031Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32118031Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3324113Skato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3424113Skato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3524113Skato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3624113Skato * SUCH DAMAGE. 37243848Skib * 3824113Skato * $Id: output.c,v 1.3 1996/04/13 15:13:20 jhay Exp $ 3979609Speter */ 4024113Skato 4124113Skato#ifndef lint 4224113Skatostatic char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; 4324113Skato#endif /* not lint */ 4424113Skato 45130224Speter/* 46130224Speter * Routing Table Management Daemon 4740003Skato */ 48109700Sjhb#include <unistd.h> 4979609Speter#include "defs.h" 50109700Sjhb 51199067Skuriyama/* 52199067Skuriyama * Apply the function "f" to all non-passive 53199067Skuriyama * interfaces. If the interface supports the 54199067Skuriyama * use of broadcasting use it, otherwise address 55199067Skuriyama * the output to the known router. 56199067Skuriyama */ 5779609Spetervoid 58114349Spetertoall(f, except) 59114349Speter void (*f)(struct sockaddr *, int, struct interface *); 60130224Speter struct rt_entry *except; 61151348Sjkim{ 62151348Sjkim register struct interface *ifp; 63184101Sjkim register struct sockaddr *dst; 64187109Sjkim register int flags; 65187109Sjkim register struct rt_entry *trt; 66114349Speter int onlist; 67130224Speter extern struct interface *ifnet; 68114349Speter 69114349Speter for (ifp = ifnet; ifp; ifp = ifp->int_next) { 70151348Sjkim if (ifp->int_flags & IFF_PASSIVE) 71114349Speter continue; 72185341Sjkim 73109700Sjhb /* 74159783Sdavidxu * Don't send it on interfaces in the except list. 75195820Skib */ 76243139Skib onlist = 0; 77231979Skib trt = except; 7882261Speter while(trt) { 79187109Sjkim if (ifp == trt->rt_ifp) { 80220018Sjkim onlist = 1; 81187109Sjkim break; 82220018Sjkim } 83187109Sjkim trt = trt->rt_clone; 84233798Sjkim } 85233798Sjkim if (onlist) 86233798Sjkim continue; 87233798Sjkim 88233798Sjkim dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 89233798Sjkim ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 90233798Sjkim &ifp->int_addr; 91233798Sjkim flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 92233798Sjkim (*f)(dst, flags, ifp); 93233798Sjkim } 94233798Sjkim} 95233798Sjkim 96239560Skib/* 97239560Skib * Output a preformed packet. 98239560Skib */ 99239560Skibvoid 100239560Skibsndmsg(dst, flags, ifp) 101233798Sjkim struct sockaddr *dst; 102233798Sjkim int flags; 103233798Sjkim struct interface *ifp; 104233798Sjkim{ 105239560Skib 106239560Skib (*afswitch[dst->sa_family].af_output) 107233798Sjkim (ripsock, flags, dst, sizeof (struct rip)); 108233798Sjkim TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 109233798Sjkim} 110233798Sjkim 11124113Skato/* 112220018Sjkim * Supply dst with the contents of the routing tables. 113187109Sjkim * If this won't fit in one packet, chop it up into several. 114187109Sjkim * 115187109Sjkim * This must be done using the split horizon algorithm. 116187109Sjkim * 1. Don't send routing info to the interface from where it was received. 117187109Sjkim * 2. Don't publish an interface to itself. 118187109Sjkim * 3. If a route is received from more than one interface and the cost is 119220018Sjkim * the same, don't publish it on either interface. I am calling this 120220018Sjkim * clones. 121220018Sjkim */ 122220018Sjkimvoid 123220018Sjkimsupply(dst, flags, ifp) 124187109Sjkim struct sockaddr *dst; 125220018Sjkim int flags; 126187109Sjkim struct interface *ifp; 127187109Sjkim{ 128187109Sjkim register struct rt_entry *rt; 129220018Sjkim register struct rt_entry *crt; /* Clone route */ 130187109Sjkim register struct rthash *rh; 131220018Sjkim register struct netinfo *nn; 132220018Sjkim register struct netinfo *n = msg->rip_nets; 133187109Sjkim struct rthash *base = hosthash; 134220018Sjkim struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 135187109Sjkim af_output_t *output = afswitch[dst->sa_family].af_output; 136220018Sjkim int doinghost = 1, size, metric, ticks; 137220018Sjkim union ipx_net net; 138220018Sjkim int delay = 0; 139187109Sjkim 140220018Sjkim if (sipx->sipx_port == 0) 141187109Sjkim sipx->sipx_port = htons(IPXPORT_RIP); 142220018Sjkim 143187109Sjkim msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 144220018Sjkimagain: 145187109Sjkim for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) 146220018Sjkim for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 147220018Sjkim size = (char *)n - (char *)msg; 148187109Sjkim if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + 149187109Sjkim sizeof (msg->rip_cmd))) { 150187109Sjkim (*output)(ripsock, flags, dst, size); 151130224Speter TRACE_OUTPUT(ifp, dst, size); 15279609Speter n = msg->rip_nets; 15379609Speter delay++; 154130224Speter if(delay == 2) { 15579609Speter usleep(20000); 156130224Speter delay = 0; 157243848Skib } 158130224Speter } 159243848Skib 16079609Speter /* 161243848Skib * This should do rule one and two of the split horizon 16279609Speter * algorithm. 16379609Speter */ 164243848Skib if (rt->rt_ifp == ifp) 165243848Skib continue; 166243848Skib 167243848Skib /* 168243848Skib * Rule 3. 169243848Skib * Look if we have clones (different routes to the same 170243848Skib * place with exactly the same cost). 171243848Skib * 172243848Skib * We should not publish on any of the clone interfaces. 173243848Skib */ 174243848Skib crt = rt->rt_clone; 175243848Skib while (crt) { 176130224Speter if (crt->rt_ifp == ifp) 177130224Speter goto next; 178130224Speter crt = crt->rt_clone; 179130224Speter } 18024113Skato 181233798Sjkim sipx = (struct sockaddr_ipx *)&rt->rt_dst; 182233798Sjkim if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 183233798Sjkim sipx = (struct sockaddr_ipx *)&rt->rt_router; 184233798Sjkim if (rt->rt_metric == HOPCNT_INFINITY) 185233798Sjkim metric = HOPCNT_INFINITY; 186187109Sjkim else { 187233798Sjkim metric = rt->rt_metric + 1; 188233798Sjkim /* 189199253Skib * We don't advertize routes with more than 15 hops. 190195820Skib */ 191199253Skib if (metric >= HOPCNT_INFINITY) 192199253Skib continue; 193199253Skib } 194199253Skib /* XXX One day we should cater for slow interfaces also. */ 195195820Skib ticks = rt->rt_ticks + 1; 196195820Skib net = sipx->sipx_addr.x_net; 197195820Skib 198195820Skib /* 199195820Skib * Make sure that we don't put out a two net entries 200195820Skib * for a pt to pt link (one for the G route, one for the if) 201195820Skib * This is a kludge, and won't work if there are lots of nets. 202197663Skib */ 203210774Sjhb for (nn = msg->rip_nets; nn < n; nn++) { 204210774Sjhb if (ipx_neteqnn(net, nn->rip_dst)) { 205210774Sjhb if (ticks < ntohs(nn->rip_ticks)) { 206210774Sjhb nn->rip_metric = htons(metric); 207197663Skib nn->rip_ticks = htons(ticks); 208199067Skuriyama } else if ((ticks == ntohs(nn->rip_ticks)) && 209210774Sjhb (metric < ntohs(nn->rip_metric))) { 210197663Skib nn->rip_metric = htons(metric); 211199067Skuriyama nn->rip_ticks = htons(ticks); 212199067Skuriyama } 213210774Sjhb goto next; 214199067Skuriyama } 215199215Skuriyama } 216199067Skuriyama n->rip_dst = net; 21724113Skato 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