output.c revision 15248
1194701Srpaulo/* 2194701Srpaulo * Copyright (c) 1985, 1993 3194701Srpaulo * The Regents of the University of California. All rights reserved. 4194701Srpaulo * 5194701Srpaulo * Copyright (c) 1995 John Hay. All rights reserved. 6194701Srpaulo * 7194701Srpaulo * This file includes significant work done at Cornell University by 8194701Srpaulo * Bill Nesheim. That work included by permission. 9194701Srpaulo * 10194701Srpaulo * Redistribution and use in source and binary forms, with or without 11194701Srpaulo * modification, are permitted provided that the following conditions 12194701Srpaulo * are met: 13194701Srpaulo * 1. Redistributions of source code must retain the above copyright 14194701Srpaulo * notice, this list of conditions and the following disclaimer. 15194701Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 16194701Srpaulo * notice, this list of conditions and the following disclaimer in the 17194701Srpaulo * documentation and/or other materials provided with the distribution. 18194701Srpaulo * 3. All advertising materials mentioning features or use of this software 19194701Srpaulo * must display the following acknowledgement: 20194701Srpaulo * This product includes software developed by the University of 21194701Srpaulo * California, Berkeley and its contributors. 22194701Srpaulo * 4. Neither the name of the University nor the names of its contributors 23194701Srpaulo * may be used to endorse or promote products derived from this software 24194701Srpaulo * without specific prior written permission. 25194701Srpaulo * 26194701Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27229858Sjh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28203687Sgavin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29194701Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30194701Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31194701Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32194701Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33194701Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34194701Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35194701Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36194701Srpaulo * SUCH DAMAGE. 37194701Srpaulo * 38194701Srpaulo * $Id: output.c,v 1.2 1995/12/05 04:59:54 julian Exp $ 39194701Srpaulo */ 40194701Srpaulo 41194701Srpaulo#ifndef lint 42194701Srpaulostatic char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; 43194701Srpaulo#endif /* not lint */ 44194701Srpaulo 45194701Srpaulo/* 46194701Srpaulo * Routing Table Management Daemon 47194701Srpaulo */ 48194701Srpaulo#include "defs.h" 49194701Srpaulo 50237216Seadler/* 51195325Srpaulo * Apply the function "f" to all non-passive 52229858Sjh * interfaces. If the interface supports the 53194701Srpaulo * use of broadcasting use it, otherwise address 54194701Srpaulo * the output to the known router. 55229858Sjh */ 56229858Sjhvoid 57194701Srpaulotoall(f, except) 58194701Srpaulo void (*f)(struct sockaddr *, int, struct interface *); 59194701Srpaulo struct rt_entry *except; 60205076Suqs{ 61229858Sjh register struct interface *ifp; 62194701Srpaulo register struct sockaddr *dst; 63194701Srpaulo register int flags; 64194701Srpaulo register struct rt_entry *trt; 65194701Srpaulo int onlist; 66194701Srpaulo extern struct interface *ifnet; 67194701Srpaulo 68194701Srpaulo for (ifp = ifnet; ifp; ifp = ifp->int_next) { 69194701Srpaulo if (ifp->int_flags & IFF_PASSIVE) 70194701Srpaulo continue; 71194701Srpaulo 72194701Srpaulo /* 73194701Srpaulo * Don't send it on interfaces in the except list. 74194701Srpaulo */ 75194701Srpaulo onlist = 0; 76194701Srpaulo trt = except; 77194701Srpaulo while(trt) { 78194701Srpaulo if (ifp == trt->rt_ifp) { 79194701Srpaulo onlist = 1; 80194701Srpaulo break; 81194701Srpaulo } 82198441Srpaulo trt = trt->rt_clone; 83194701Srpaulo } 84194701Srpaulo if (onlist) 85194701Srpaulo continue; 86194701Srpaulo 87194701Srpaulo dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : 88235578Sgjb ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : 89194701Srpaulo &ifp->int_addr; 90235578Sgjb flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 91194701Srpaulo (*f)(dst, flags, ifp); 92194701Srpaulo } 93194701Srpaulo} 94194701Srpaulo 95194701Srpaulo/* 96235578Sgjb * 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