sap_output.c revision 97638
1251652Sgjb/*
2251652Sgjb * Copyright (c) 1995 John Hay.  All rights reserved.
3251652Sgjb *
4251652Sgjb * Redistribution and use in source and binary forms, with or without
5251652Sgjb * modification, are permitted provided that the following conditions
6251652Sgjb * are met:
7251652Sgjb * 1. Redistributions of source code must retain the above copyright
8251652Sgjb *    notice, this list of conditions and the following disclaimer.
9251652Sgjb * 2. Redistributions in binary form must reproduce the above copyright
10251652Sgjb *    notice, this list of conditions and the following disclaimer in the
11251652Sgjb *    documentation and/or other materials provided with the distribution.
12251652Sgjb * 3. All advertising materials mentioning features or use of this software
13251652Sgjb *    must display the following acknowledgement:
14251652Sgjb *	This product includes software developed by John Hay.
15251652Sgjb * 4. Neither the name of the author nor the names of any co-contributors
16251652Sgjb *    may be used to endorse or promote products derived from this software
17251652Sgjb *    without specific prior written permission.
18251652Sgjb *
19251652Sgjb * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
20251652Sgjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21251652Sgjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22251652Sgjb * ARE DISCLAIMED.  IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
23251652Sgjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24251652Sgjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25251652Sgjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26251652Sgjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27251652Sgjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28251652Sgjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29251652Sgjb * SUCH DAMAGE.
30251652Sgjb *
31251652Sgjb * $FreeBSD: head/usr.sbin/IPXrouted/sap_output.c 97638 2002-05-30 21:49:15Z wollman $
32251652Sgjb */
33251652Sgjb
34251652Sgjb/*
35251652Sgjb * Routing Table Management Daemon
36251652Sgjb */
37251652Sgjb#include <unistd.h>
38251652Sgjb#include "defs.h"
39251652Sgjb
40251652Sgjb/*
41251652Sgjb * Apply the function "f" to all non-passive
42251652Sgjb * interfaces.  If the interface supports the
43251652Sgjb * use of broadcasting use it, otherwise address
44251652Sgjb * the output to the known router.
45251652Sgjb */
46251652Sgjbvoid
47251652Sgjbsap_supply_toall(changesonly)
48251652Sgjb	int changesonly;
49251652Sgjb{
50251652Sgjb	register struct interface *ifp;
51251652Sgjb	struct sockaddr dst;
52251652Sgjb	register struct sockaddr_ipx *ipx_dst;
53251652Sgjb	register int flags;
54251652Sgjb	extern struct interface *ifnet;
55251652Sgjb
56251652Sgjb	ipx_dst = (struct sockaddr_ipx *)&dst;
57251652Sgjb
58251652Sgjb	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
59251652Sgjb		if (ifp->int_flags & IFF_PASSIVE)
60251652Sgjb			continue;
61251652Sgjb
62251652Sgjb		dst = ifp->int_flags & IFF_BROADCAST ? ifp->int_broadaddr :
63251652Sgjb		      ifp->int_flags & IFF_POINTOPOINT ? ifp->int_dstaddr :
64251652Sgjb		      ifp->int_addr;
65251652Sgjb
66251652Sgjb		ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
67251652Sgjb
68251652Sgjb		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
69251652Sgjb		sap_supply(&dst, flags, ifp, SAP_WILDCARD, changesonly);
70251652Sgjb	}
71251652Sgjb}
72251652Sgjb
73251652Sgjbvoid
74251652Sgjbsapsndmsg(dst, flags, ifp, changesonly)
75251652Sgjb	struct sockaddr *dst;
76251652Sgjb	int flags;
77251652Sgjb	struct interface *ifp;
78251652Sgjb	int changesonly;
79251652Sgjb{
80251652Sgjb	struct sockaddr t_dst;
81251652Sgjb	struct sockaddr_ipx *ipx_dst;
82251652Sgjb
83251652Sgjb	t_dst = *dst;
84251652Sgjb	ipx_dst = (struct sockaddr_ipx *)&t_dst;
85251652Sgjb
86251652Sgjb	if (ipx_dst->sipx_addr.x_port == 0)
87251652Sgjb		ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
88251652Sgjb
89251652Sgjb        (*afswitch[dst->sa_family].af_output)
90251652Sgjb		(sapsock, flags, &t_dst,
91251652Sgjb		sizeof (struct sap_packet) + sizeof(u_short));
92251652Sgjb	TRACE_SAP_OUTPUT(ifp, &t_dst,
93251652Sgjb			 sizeof (struct sap_packet) + sizeof(u_short));
94251652Sgjb}
95251652Sgjb
96251652Sgjb/*
97251652Sgjb * Supply dst with the contents of the SAP tables. If the ServType ==
98251652Sgjb * SAP_WILDCARD (0xFFFF) supply the whole table, otherwise only the
99251652Sgjb * services that are of ServType. If this won't fit in one packet, chop
100251652Sgjb * it up into several.
101251652Sgjb *
102251652Sgjb * This must be done using the split horizon algorithm.
103251652Sgjb * 1. Don't send SAP info to the interface from where it was received.
104251652Sgjb * 2. If a service is received from more than one interface and the cost is
105251652Sgjb *    the same, don't publish it on either interface. I am calling this
106251652Sgjb *    clones.
107251652Sgjb */
108251652Sgjbvoid
109251652Sgjbsap_supply(dst, flags, ifp, ServType, changesonly)
110251652Sgjb	struct sockaddr *dst;
111251652Sgjb	int flags;
112251652Sgjb	struct interface *ifp;
113251652Sgjb	int ServType;
114251652Sgjb	int changesonly;
115251652Sgjb{
116251652Sgjb	register struct sap_entry *sap;
117251652Sgjb	register struct sap_entry *csap; /* Clone route */
118251652Sgjb	register struct sap_hash *sh;
119251652Sgjb	register struct sap_info *n = sap_msg->sap;
120251652Sgjb	struct sap_hash *base = sap_head;
121251652Sgjb	struct sockaddr_ipx *sipx =  (struct sockaddr_ipx *) dst;
122251652Sgjb	af_output_t *output = afswitch[dst->sa_family].af_output;
123251652Sgjb	int size, metric;
124251652Sgjb	int delay = 0;
125251652Sgjb
126251652Sgjb	if (sipx->sipx_port == 0)
127251652Sgjb		sipx->sipx_port = htons(IPXPORT_SAP);
128251652Sgjb
129251652Sgjb	sap_msg->sap_cmd = ntohs(SAP_RESP);
130251652Sgjb
131251652Sgjb	for (sh = base; sh < &base[SAPHASHSIZ]; sh++)
132251652Sgjb	for (sap = sh->forw; sap != (struct sap_entry *)sh; sap = sap->forw) {
133251652Sgjb		size = (char *)n - (char *)sap_msg;
134251652Sgjb		if (size >= ((MAXSAPENTRIES * sizeof (struct sap_info)) +
135251652Sgjb				sizeof (sap_msg->sap_cmd))) {
136251652Sgjb			(*output)(sapsock, flags, dst, size);
137251652Sgjb			TRACE_SAP_OUTPUT(ifp, dst, size);
138251652Sgjb			n = sap_msg->sap;
139251652Sgjb			delay++;
140251652Sgjb			if(delay == 2) {
141251652Sgjb				usleep(50000);
142251652Sgjb				delay = 0;
143251652Sgjb			}
144251652Sgjb		}
145251652Sgjb
146251652Sgjb		if (changesonly && !(sap->state & RTS_CHANGED))
147251652Sgjb			continue;
148251652Sgjb
149251652Sgjb		/*
150251652Sgjb		 * Check for the servicetype except if the ServType is
151251652Sgjb		 * a wildcard (0xFFFF).
152251652Sgjb		 */
153251652Sgjb		if ((ServType != SAP_WILDCARD) &&
154251652Sgjb		    (ServType != sap->sap.ServType))
155251652Sgjb			continue;
156251652Sgjb
157251652Sgjb		/*
158251652Sgjb		 * This should do rule one and two of the split horizon
159251652Sgjb		 * algorithm.
160251652Sgjb		 */
161251652Sgjb		if (sap->ifp == ifp)
162251652Sgjb			continue;
163251652Sgjb
164251652Sgjb		/*
165251652Sgjb		 * Rule 2.
166251652Sgjb		 * Look if we have clones (different routes to the same
167251652Sgjb		 * place with exactly the same cost).
168251652Sgjb		 *
169251652Sgjb		 * We should not publish on any of the clone interfaces.
170251652Sgjb		 */
171251652Sgjb		csap = sap->clone;
172251652Sgjb		while (csap) {
173251652Sgjb			if (csap->ifp == ifp)
174251652Sgjb				goto next;
175251652Sgjb			csap = csap->clone;
176251652Sgjb		}
177251652Sgjb
178251652Sgjb		/*
179251652Sgjb		 * Don't advertise services with more than 15 hops. It
180251652Sgjb		 * will be confused with a service that has gone down.
181251652Sgjb		 */
182251652Sgjb		if (ntohs(sap->sap.hops) == (HOPCNT_INFINITY - 1))
183251652Sgjb			continue;
184251652Sgjb		metric = min(ntohs(sap->sap.hops) + 1, HOPCNT_INFINITY);
185251652Sgjb
186251652Sgjb		*n = sap->sap;
187251652Sgjb		n->hops = htons(metric);
188251652Sgjb		n++;
189251652Sgjbnext:
190251652Sgjb		;
191251652Sgjb	}
192251652Sgjb	if (n != sap_msg->sap) {
193251652Sgjb		size = (char *)n - (char *)sap_msg;
194		(*output)(sapsock, flags, dst, size);
195		TRACE_SAP_OUTPUT(ifp, dst, size);
196	}
197}
198
199