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 * $FreeBSD$ 39 */ 40 41#ifndef lint 42static const 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, changesonly) 59 void (*f)(struct sockaddr *, int, struct interface *, int); 60 struct rt_entry *except; 61 int changesonly; 62{ 63 register struct interface *ifp; 64 register struct sockaddr *dst; 65 register int flags; 66 register struct rt_entry *trt; 67 int onlist; 68 extern struct interface *ifnet; 69 70 for (ifp = ifnet; ifp; ifp = ifp->int_next) { 71 if (ifp->int_flags & IFF_PASSIVE) 72 continue; 73 74 /* 75 * Don't send it on interfaces in the except list. 76 */ 77 onlist = 0; 78 trt = except; 79 while(trt) { 80 if (ifp == trt->rt_ifp) { 81 onlist = 1; 82 break; 83 } 84 trt = trt->rt_clone; 85 } 86 if (onlist) 87 continue; 88 89 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 90 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 91 &ifp->int_addr; 92 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 93 (*f)(dst, flags, ifp, changesonly); 94 } 95} 96 97/* 98 * Output a preformed packet. 99 */ 100void 101sndmsg(dst, flags, ifp, changesonly) 102 struct sockaddr *dst; 103 int flags; 104 struct interface *ifp; 105 int changesonly; 106{ 107 108 (*afswitch[dst->sa_family].af_output) 109 (ripsock, flags, dst, sizeof (struct rip)); 110 TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); 111} 112 113/* 114 * Supply dst with the contents of the routing tables. 115 * If this won't fit in one packet, chop it up into several. 116 * 117 * This must be done using the split horizon algorithm. 118 * 1. Don't send routing info to the interface from where it was received. 119 * 2. Don't publish an interface to itself. 120 * 3. If a route is received from more than one interface and the cost is 121 * the same, don't publish it on either interface. I am calling this 122 * clones. 123 */ 124void 125supply(dst, flags, ifp, changesonly) 126 struct sockaddr *dst; 127 int flags; 128 struct interface *ifp; 129 int changesonly; 130{ 131 register struct rt_entry *rt; 132 register struct rt_entry *crt; /* Clone route */ 133 register struct rthash *rh; 134 register struct netinfo *nn; 135 register struct netinfo *n = msg->rip_nets; 136 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 137 af_output_t *output = afswitch[dst->sa_family].af_output; 138 int size, metric, ticks; 139 union ipx_net net; 140 int delay = 0; 141 142 if (sipx->sipx_port == 0) 143 sipx->sipx_port = htons(IPXPORT_RIP); 144 145 msg->rip_cmd = ntohs(RIPCMD_RESPONSE); 146 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) 147 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 148 size = (char *)n - (char *)msg; 149 if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + 150 sizeof (msg->rip_cmd))) { 151 (*output)(ripsock, flags, dst, size); 152 TRACE_OUTPUT(ifp, dst, size); 153 n = msg->rip_nets; 154 delay++; 155 if(delay == 2) { 156 usleep(50000); 157 delay = 0; 158 } 159 } 160 161 if (changesonly && !(rt->rt_state & RTS_CHANGED)) 162 continue; 163 164 /* 165 * This should do rule one and two of the split horizon 166 * algorithm. 167 */ 168 if (rt->rt_ifp == ifp) 169 continue; 170 171 /* 172 * Rule 3. 173 * Look if we have clones (different routes to the same 174 * place with exactly the same cost). 175 * 176 * We should not publish on any of the clone interfaces. 177 */ 178 crt = rt->rt_clone; 179 while (crt) { 180 if (crt->rt_ifp == ifp) 181 goto next; 182 crt = crt->rt_clone; 183 } 184 185 sipx = (struct sockaddr_ipx *)&rt->rt_dst; 186 if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 187 sipx = (struct sockaddr_ipx *)&rt->rt_router; 188 if (rt->rt_metric == HOPCNT_INFINITY) 189 metric = HOPCNT_INFINITY; 190 else { 191 metric = rt->rt_metric + 1; 192 /* 193 * We don't advertize routes with more than 15 hops. 194 */ 195 if (metric >= HOPCNT_INFINITY) 196 continue; 197 } 198 /* XXX One day we should cater for slow interfaces also. */ 199 ticks = rt->rt_ticks + 1; 200 net = sipx->sipx_addr.x_net; 201 202 /* 203 * Make sure that we don't put out a two net entries 204 * for a pt to pt link (one for the G route, one for the if) 205 * This is a kludge, and won't work if there are lots of nets. 206 */ 207 for (nn = msg->rip_nets; nn < n; nn++) { 208 if (ipx_neteqnn(net, nn->rip_dst)) { 209 if (ticks < ntohs(nn->rip_ticks)) { 210 nn->rip_metric = htons(metric); 211 nn->rip_ticks = htons(ticks); 212 } else if ((ticks == ntohs(nn->rip_ticks)) && 213 (metric < ntohs(nn->rip_metric))) { 214 nn->rip_metric = htons(metric); 215 nn->rip_ticks = htons(ticks); 216 } 217 goto next; 218 } 219 } 220 n->rip_dst = net; 221 n->rip_metric = htons(metric); 222 n->rip_ticks = htons(ticks); 223 n++; 224 next:; 225 } 226 if (n != msg->rip_nets) { 227 size = (char *)n - (char *)msg; 228 (*output)(ripsock, flags, dst, size); 229 TRACE_OUTPUT(ifp, dst, size); 230 } 231} 232