111820Sjulian/*
211820Sjulian * Copyright (c) 1995 John Hay.  All rights reserved.
311820Sjulian *
411820Sjulian * Redistribution and use in source and binary forms, with or without
511820Sjulian * modification, are permitted provided that the following conditions
611820Sjulian * are met:
711820Sjulian * 1. Redistributions of source code must retain the above copyright
811820Sjulian *    notice, this list of conditions and the following disclaimer.
911820Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1011820Sjulian *    notice, this list of conditions and the following disclaimer in the
1111820Sjulian *    documentation and/or other materials provided with the distribution.
1211820Sjulian * 3. All advertising materials mentioning features or use of this software
1311820Sjulian *    must display the following acknowledgement:
1411820Sjulian *	This product includes software developed by John Hay.
1511820Sjulian * 4. Neither the name of the author nor the names of any co-contributors
1611820Sjulian *    may be used to endorse or promote products derived from this software
1711820Sjulian *    without specific prior written permission.
1811820Sjulian *
1911820Sjulian * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
2011820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2111820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2211820Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
2311820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2411820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2511820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2611820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2711820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2811820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2911820Sjulian * SUCH DAMAGE.
3011820Sjulian *
3150479Speter * $FreeBSD$
3211820Sjulian */
3311820Sjulian
3411820Sjulian/*
3511820Sjulian * Routing Table Management Daemon
3611820Sjulian */
3719948Sjhay#include <unistd.h>
3811820Sjulian#include "defs.h"
3911820Sjulian
4011820Sjulian/*
4111820Sjulian * Apply the function "f" to all non-passive
4211820Sjulian * interfaces.  If the interface supports the
4311820Sjulian * use of broadcasting use it, otherwise address
4411820Sjulian * the output to the known router.
4511820Sjulian */
4611820Sjulianvoid
4727244Sjhaysap_supply_toall(changesonly)
4827244Sjhay	int changesonly;
4911820Sjulian{
5011820Sjulian	register struct interface *ifp;
5111820Sjulian	struct sockaddr dst;
5211820Sjulian	register struct sockaddr_ipx *ipx_dst;
5311820Sjulian	register int flags;
5411820Sjulian	extern struct interface *ifnet;
5511820Sjulian
5611820Sjulian	ipx_dst = (struct sockaddr_ipx *)&dst;
5711820Sjulian
5811820Sjulian	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
5911820Sjulian		if (ifp->int_flags & IFF_PASSIVE)
6011820Sjulian			continue;
6111820Sjulian
6211820Sjulian		dst = ifp->int_flags & IFF_BROADCAST ? ifp->int_broadaddr :
6311820Sjulian		      ifp->int_flags & IFF_POINTOPOINT ? ifp->int_dstaddr :
6411820Sjulian		      ifp->int_addr;
6511820Sjulian
6612268Sjulian		ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
6712268Sjulian
6811820Sjulian		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
6927244Sjhay		sap_supply(&dst, flags, ifp, SAP_WILDCARD, changesonly);
7011820Sjulian	}
7111820Sjulian}
7211820Sjulian
7311820Sjulianvoid
7427244Sjhaysapsndmsg(dst, flags, ifp, changesonly)
7511820Sjulian	struct sockaddr *dst;
7611820Sjulian	int flags;
7711820Sjulian	struct interface *ifp;
7827244Sjhay	int changesonly;
7911820Sjulian{
8011820Sjulian	struct sockaddr t_dst;
8111820Sjulian	struct sockaddr_ipx *ipx_dst;
8211820Sjulian
8311820Sjulian	t_dst = *dst;
8411820Sjulian	ipx_dst = (struct sockaddr_ipx *)&t_dst;
8511820Sjulian
8611820Sjulian	if (ipx_dst->sipx_addr.x_port == 0)
8711820Sjulian		ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
8811820Sjulian
8911820Sjulian        (*afswitch[dst->sa_family].af_output)
9011820Sjulian		(sapsock, flags, &t_dst,
9111820Sjulian		sizeof (struct sap_packet) + sizeof(u_short));
9211820Sjulian	TRACE_SAP_OUTPUT(ifp, &t_dst,
9311820Sjulian			 sizeof (struct sap_packet) + sizeof(u_short));
9411820Sjulian}
9511820Sjulian
9611820Sjulian/*
9711820Sjulian * Supply dst with the contents of the SAP tables. If the ServType ==
9811820Sjulian * SAP_WILDCARD (0xFFFF) supply the whole table, otherwise only the
9911820Sjulian * services that are of ServType. If this won't fit in one packet, chop
10011820Sjulian * it up into several.
10111820Sjulian *
10211820Sjulian * This must be done using the split horizon algorithm.
10311820Sjulian * 1. Don't send SAP info to the interface from where it was received.
10411820Sjulian * 2. If a service is received from more than one interface and the cost is
10511820Sjulian *    the same, don't publish it on either interface. I am calling this
10611820Sjulian *    clones.
10711820Sjulian */
10811820Sjulianvoid
10927244Sjhaysap_supply(dst, flags, ifp, ServType, changesonly)
11011820Sjulian	struct sockaddr *dst;
11111820Sjulian	int flags;
11211820Sjulian	struct interface *ifp;
11311820Sjulian	int ServType;
11427244Sjhay	int changesonly;
11511820Sjulian{
11611820Sjulian	register struct sap_entry *sap;
11711820Sjulian	register struct sap_entry *csap; /* Clone route */
11811820Sjulian	register struct sap_hash *sh;
11911820Sjulian	register struct sap_info *n = sap_msg->sap;
12011820Sjulian	struct sap_hash *base = sap_head;
12111820Sjulian	struct sockaddr_ipx *sipx =  (struct sockaddr_ipx *) dst;
12211820Sjulian	af_output_t *output = afswitch[dst->sa_family].af_output;
12311820Sjulian	int size, metric;
12419948Sjhay	int delay = 0;
12511820Sjulian
12611820Sjulian	if (sipx->sipx_port == 0)
12711820Sjulian		sipx->sipx_port = htons(IPXPORT_SAP);
12811820Sjulian
12911820Sjulian	sap_msg->sap_cmd = ntohs(SAP_RESP);
13011820Sjulian
13111820Sjulian	for (sh = base; sh < &base[SAPHASHSIZ]; sh++)
13211820Sjulian	for (sap = sh->forw; sap != (struct sap_entry *)sh; sap = sap->forw) {
13311820Sjulian		size = (char *)n - (char *)sap_msg;
13415248Sjhay		if (size >= ((MAXSAPENTRIES * sizeof (struct sap_info)) +
13515248Sjhay				sizeof (sap_msg->sap_cmd))) {
13611820Sjulian			(*output)(sapsock, flags, dst, size);
13711820Sjulian			TRACE_SAP_OUTPUT(ifp, dst, size);
13811820Sjulian			n = sap_msg->sap;
13919948Sjhay			delay++;
14019948Sjhay			if(delay == 2) {
14127244Sjhay				usleep(50000);
14219948Sjhay				delay = 0;
14319948Sjhay			}
14411820Sjulian		}
14511820Sjulian
14627244Sjhay		if (changesonly && !(sap->state & RTS_CHANGED))
14727244Sjhay			continue;
14827244Sjhay
14911820Sjulian		/*
15011820Sjulian		 * Check for the servicetype except if the ServType is
15111820Sjulian		 * a wildcard (0xFFFF).
15211820Sjulian		 */
15311820Sjulian		if ((ServType != SAP_WILDCARD) &&
15411820Sjulian		    (ServType != sap->sap.ServType))
15511820Sjulian			continue;
15611820Sjulian
15711820Sjulian		/*
15811820Sjulian		 * This should do rule one and two of the split horizon
15911820Sjulian		 * algorithm.
16011820Sjulian		 */
16111820Sjulian		if (sap->ifp == ifp)
16211820Sjulian			continue;
16311820Sjulian
16411820Sjulian		/*
16511820Sjulian		 * Rule 2.
16611820Sjulian		 * Look if we have clones (different routes to the same
16711820Sjulian		 * place with exactly the same cost).
16811820Sjulian		 *
16911820Sjulian		 * We should not publish on any of the clone interfaces.
17011820Sjulian		 */
17111820Sjulian		csap = sap->clone;
17211820Sjulian		while (csap) {
17311820Sjulian			if (csap->ifp == ifp)
17412630Sjulian				goto next;
17511820Sjulian			csap = csap->clone;
17611820Sjulian		}
17711820Sjulian
17811820Sjulian		/*
17911820Sjulian		 * Don't advertise services with more than 15 hops. It
18011820Sjulian		 * will be confused with a service that has gone down.
18111820Sjulian		 */
18211820Sjulian		if (ntohs(sap->sap.hops) == (HOPCNT_INFINITY - 1))
18311820Sjulian			continue;
18411820Sjulian		metric = min(ntohs(sap->sap.hops) + 1, HOPCNT_INFINITY);
18511820Sjulian
18611820Sjulian		*n = sap->sap;
18711820Sjulian		n->hops = htons(metric);
18811820Sjulian		n++;
18912630Sjuliannext:
19097638Swollman		;
19111820Sjulian	}
19211820Sjulian	if (n != sap_msg->sap) {
19311820Sjulian		size = (char *)n - (char *)sap_msg;
19411820Sjulian		(*output)(sapsock, flags, dst, size);
19511820Sjulian		TRACE_SAP_OUTPUT(ifp, dst, size);
19611820Sjulian	}
19711820Sjulian}
19811820Sjulian
199