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