output.c revision 11820
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.6 1995/10/11 18:57:22 jhay 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 > MAXPACKETSIZE - sizeof (struct netinfo)) { 147 (*output)(ripsock, flags, dst, size); 148 TRACE_OUTPUT(ifp, dst, size); 149 n = msg->rip_nets; 150 } 151 152 /* 153 * This should do rule one and two of the split horizon 154 * algorithm. 155 */ 156 if (rt->rt_ifp == ifp) 157 continue; 158 159 /* 160 * Rule 3. 161 * Look if we have clones (different routes to the same 162 * place with exactly the same cost). 163 * 164 * We should not publish on any of the clone interfaces. 165 */ 166 crt = rt->rt_clone; 167 while (crt) { 168 if (crt->rt_ifp == ifp) 169 continue; 170 crt = crt->rt_clone; 171 } 172 173 sipx = (struct sockaddr_ipx *)&rt->rt_dst; 174 if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 175 sipx = (struct sockaddr_ipx *)&rt->rt_router; 176 if (rt->rt_metric == HOPCNT_INFINITY) 177 metric = HOPCNT_INFINITY; 178 else { 179 metric = rt->rt_metric + 1; 180 /* 181 * We don't advertize routes with more than 15 hops. 182 */ 183 if (metric >= HOPCNT_INFINITY) 184 continue; 185 } 186 /* XXX One day we should cater for slow interfaces also. */ 187 ticks = rt->rt_ticks + 1; 188 net = sipx->sipx_addr.x_net; 189 190 /* 191 * Make sure that we don't put out a two net entries 192 * for a pt to pt link (one for the G route, one for the if) 193 * This is a kludge, and won't work if there are lots of nets. 194 */ 195 for (nn = msg->rip_nets; nn < n; nn++) { 196 if (ipx_neteqnn(net, nn->rip_dst)) { 197 if (ticks < ntohs(nn->rip_ticks)) { 198 nn->rip_metric = htons(metric); 199 nn->rip_ticks = htons(ticks); 200 } else if ((ticks == ntohs(nn->rip_ticks)) && 201 (metric < ntohs(nn->rip_metric))) { 202 nn->rip_metric = htons(metric); 203 nn->rip_ticks = htons(ticks); 204 } 205 goto next; 206 } 207 } 208 n->rip_dst = net; 209 n->rip_metric = htons(metric); 210 n->rip_ticks = htons(ticks); 211 n++; 212 next:; 213 } 214 if (doinghost) { 215 doinghost = 0; 216 base = nethash; 217 goto again; 218 } 219 if (n != msg->rip_nets) { 220 size = (char *)n - (char *)msg; 221 (*output)(ripsock, flags, dst, size); 222 TRACE_OUTPUT(ifp, dst, size); 223 } 224} 225