2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1995 John Hay. All rights reserved.
7 * This file includes significant work done at Cornell University by
8 * Bill Nesheim. That work included by permission.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $FreeBSD: src/usr.sbin/IPXrouted/output.c,v 1.8 1999/08/28 01:15:03 peter Exp $
36 * @(#)output.c 8.1 (Berkeley) 6/5/93
40 * Routing Table Management Daemon
46 * Apply the function "f" to all non-passive
47 * interfaces. If the interface supports the
48 * use of broadcasting use it, otherwise address
49 * the output to the known router.
52 toall(void (*f)(struct sockaddr *, int, struct interface *, int),
53 struct rt_entry *except, int changesonly)
55 struct interface *ifp;
60 extern struct interface *ifnet;
62 for (ifp = ifnet; ifp; ifp = ifp->int_next) {
63 if (ifp->int_flags & IFF_PASSIVE)
67 * Don't send it on interfaces in the except list.
72 if (ifp == trt->rt_ifp) {
81 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
82 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
84 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
85 (*f)(dst, flags, ifp, changesonly);
90 * Output a preformed packet.
93 sndmsg(struct sockaddr *dst, int flags, struct interface *ifp,
97 (*afswitch[dst->sa_family].af_output)
98 (ripsock, flags, dst, sizeof (struct rip));
99 TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
103 * Supply dst with the contents of the routing tables.
104 * If this won't fit in one packet, chop it up into several.
106 * This must be done using the split horizon algorithm.
107 * 1. Don't send routing info to the interface from where it was received.
108 * 2. Don't publish an interface to itself.
109 * 3. If a route is received from more than one interface and the cost is
110 * the same, don't publish it on either interface. I am calling this
114 supply(struct sockaddr *dst, int flags, struct interface *ifp,
118 struct rt_entry *crt; /* Clone route */
121 struct netinfo *n = msg->rip_nets;
122 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst;
123 af_output_t *output = afswitch[dst->sa_family].af_output;
124 int size, metric, ticks;
128 if (sipx->sipx_port == 0)
129 sipx->sipx_port = htons(IPXPORT_RIP);
131 msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
132 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
133 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh;
135 size = (char *)n - (char *)msg;
136 if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) +
137 sizeof (msg->rip_cmd))) {
138 (*output)(ripsock, flags, dst, size);
139 TRACE_OUTPUT(ifp, dst, size);
148 if (changesonly && !(rt->rt_state & RTS_CHANGED))
152 * This should do rule one and two of the split horizon
155 if (rt->rt_ifp == ifp)
160 * Look if we have clones (different routes to the same
161 * place with exactly the same cost).
163 * We should not publish on any of the clone
168 if (crt->rt_ifp == ifp)
173 sipx = (struct sockaddr_ipx *)&rt->rt_dst;
174 if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) ==
176 sipx = (struct sockaddr_ipx *)&rt->rt_router;
177 if (rt->rt_metric == HOPCNT_INFINITY)
178 metric = HOPCNT_INFINITY;
180 metric = rt->rt_metric + 1;
182 * We don't advertize routes with more than
185 if (metric >= HOPCNT_INFINITY)
189 * XXX One day we should cater for slow interfaces
192 ticks = rt->rt_ticks + 1;
193 net = sipx->sipx_addr.x_net;
196 * Make sure that we don't put out a two net entries
197 * for a pt to pt link (one for the G route, one for
199 * This is a kludge, and won't work if there are lots
202 for (nn = msg->rip_nets; nn < n; nn++) {
203 if (ipx_neteqnn(net, nn->rip_dst)) {
204 if (ticks < ntohs(nn->rip_ticks)) {
205 nn->rip_metric = htons(metric);
206 nn->rip_ticks = htons(ticks);
207 } else if ((ticks == ntohs(nn->rip_ticks)) &&
208 (metric < ntohs(nn->rip_metric))) {
209 nn->rip_metric = htons(metric);
210 nn->rip_ticks = htons(ticks);
216 n->rip_metric = htons(metric);
217 n->rip_ticks = htons(ticks);
222 if (n != msg->rip_nets) {
223 size = (char *)n - (char *)msg;
224 (*output)(ripsock, flags, dst, size);
225 TRACE_OUTPUT(ifp, dst, size);