IPXrouted(8): Re-indent some code to make the outer for() better visible.
[dragonfly.git] / usr.sbin / IPXrouted / output.c
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 $
39  *
40  * @(#)output.c 8.1 (Berkeley) 6/5/93
41  */
42
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  */
55 void
56 toall(void (*f)(struct sockaddr *, int, struct interface *, int),
57       struct rt_entry *except, int changesonly)
58 {
59         struct interface *ifp;
60         struct sockaddr *dst;
61         int flags;
62         struct rt_entry *trt;
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  */
96 void
97 sndmsg(struct sockaddr *dst, int flags, struct interface *ifp,
98        int changesonly)
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  */
117 void
118 supply(struct sockaddr *dst, int flags, struct interface *ifp,
119        int changesonly)
120 {
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;
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);
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)) +
141                                 sizeof (msg->rip_cmd))) {
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                                 }
150                         }
151
152                         if (changesonly && !(rt->rt_state & RTS_CHANGED))
153                                 continue;
154
155                         /*
156                          * This should do rule one and two of the split horizon
157                          * algorithm.
158                          */
159                         if (rt->rt_ifp == ifp)
160                                 continue;
161
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                         }
176
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                         }
192                         /*
193                          * XXX One day we should cater for slow interfaces
194                          * also.
195                          */
196                         ticks = rt->rt_ticks + 1;
197                         net = sipx->sipx_addr.x_net;
198
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;
217                                 }
218                         }
219                         n->rip_dst = net;
220                         n->rip_metric = htons(metric);
221                         n->rip_ticks = htons(ticks);
222                         n++;
223 next:
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);
230                 }
231         }
232 }