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