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