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 * IPX Routing Table Management Daemon
3611820Sjulian */
3711820Sjulian#include "defs.h"
3811820Sjulian
3945988Sjhayint dognreply = 1;
4011820Sjulian
4111820Sjulian/*
4211820Sjulian * Process a newly received packet.
4311820Sjulian */
4411820Sjulianvoid
4511820Sjuliansap_input(from, size)
4611820Sjulian	struct sockaddr *from;
4711820Sjulian	int size;
4811820Sjulian{
4927244Sjhay	int newsize;
5027244Sjhay	int sapchanged = 0;
5111820Sjulian	struct sap_entry *sap;
5211820Sjulian	struct sap_info *n;
5311820Sjulian	struct interface *ifp = 0;
5411820Sjulian	struct afswitch *afp;
5511820Sjulian	struct sockaddr_ipx *ipxp;
5611820Sjulian
5711820Sjulian	ifp = if_ifwithnet(from);
5811820Sjulian	ipxp = (struct sockaddr_ipx *)from;
5911820Sjulian	if (ifp == 0) {
6011820Sjulian		if(ftrace) {
6111820Sjulian			fprintf(ftrace, "Received bogus packet from %s\n",
6211820Sjulian				ipxdp_ntoa(&ipxp->sipx_addr));
6311820Sjulian		}
6411820Sjulian		return;
6511820Sjulian	}
6611820Sjulian
6711820Sjulian	if (ftrace)
6811820Sjulian		dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
6911820Sjulian
7011820Sjulian	if (from->sa_family >= AF_MAX)
7111820Sjulian		return;
7211820Sjulian	afp = &afswitch[from->sa_family];
7311820Sjulian
7411820Sjulian	size -= sizeof (u_short)	/* command */;
7511820Sjulian	n = sap_msg->sap;
7611820Sjulian
7711820Sjulian	switch (ntohs(sap_msg->sap_cmd)) {
7811820Sjulian
7911820Sjulian	case SAP_REQ_NEAR:
8011820Sjulian		if (ftrace)
8111820Sjulian			fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
8245988Sjhay		if (!dognreply)
8345988Sjhay			return;
8411820Sjulian		sap = sap_nearestserver(n->ServType, ifp);
8511820Sjulian		if (sap == NULL)
8611820Sjulian			return;
8711820Sjulian		sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
8811820Sjulian		*n = sap->sap;
8911820Sjulian		n->hops = htons(ntohs(n->hops) + 1);
9011820Sjulian		if (ntohs(n->hops) >= HOPCNT_INFINITY)
9111820Sjulian			return;
9211820Sjulian
9311820Sjulian		newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
9411820Sjulian		(*afp->af_output)(sapsock, 0, from, newsize);
9511820Sjulian		if (ftrace) {
9611820Sjulian			fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
9711820Sjulian				ntohs(n->ServType),
9811820Sjulian				ifp->int_name);
9911820Sjulian			fprintf(ftrace, "  service %04X %-20.20s "
10011820Sjulian					"addr %s.%04X metric %d\n",
10111820Sjulian					ntohs(sap->sap.ServType),
10211820Sjulian					sap->sap.ServName,
10311820Sjulian					ipxdp_ntoa(&sap->sap.ipx),
10411820Sjulian					ntohs(sap->sap.ipx.x_port),
10511820Sjulian					ntohs(sap->sap.hops));
10611820Sjulian		}
10711820Sjulian		return;
10811820Sjulian
10911820Sjulian	case SAP_REQ:
11011820Sjulian		if (ftrace)
11111820Sjulian			fprintf(ftrace, "Received a sap REQ packet.\n");
11211820Sjulian
11327244Sjhay		sap_supply(from, 0, ifp, n->ServType, 0);
11411820Sjulian		return;
11511820Sjulian
11611820Sjulian	case SAP_RESP_NEAR:
11711820Sjulian		/* XXX We do nothing here, for the moment.
11811820Sjulian		 * Maybe we should check if the service is in our table?
11911820Sjulian		 *
12011820Sjulian		 */
12111820Sjulian		if (ftrace)
12211820Sjulian			fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
12311820Sjulian
12411820Sjulian		return;
12511820Sjulian
12611820Sjulian	case SAP_RESP:
12711820Sjulian		if (ftrace)
12811820Sjulian			fprintf(ftrace, "Received a sap RESP packet.\n");
12911820Sjulian
13011820Sjulian		(*afp->af_canon)(from);
13111820Sjulian
13211820Sjulian		for (; size > 0; size -= sizeof (struct sap_info), n++) {
13311820Sjulian			if (size < sizeof (struct netinfo))
13411820Sjulian				break;
13527244Sjhay			/*
13627244Sjhay			 * The idea here is that if the hop count is more
13727244Sjhay			 * than INFINITY it is bogus and should be discarded.
13827244Sjhay			 * If it is equal to INFINITY it is a message to say
139228990Suqs			 * that a service went down. If we don't already
14027244Sjhay			 * have it in our tables discard it. Otherwise
14127244Sjhay			 * update our table and set the timer to EXPIRE_TIME
14227244Sjhay			 * so that it is removed next time we go through the
14327244Sjhay			 * tables.
14427244Sjhay			 */
14527244Sjhay			if (ntohs(n->hops) > HOPCNT_INFINITY)
14627244Sjhay				continue;
14711820Sjulian			sap = sap_lookup(n->ServType, n->ServName);
14811820Sjulian			if (sap == 0) {
14927244Sjhay				if (ntohs(n->hops) == HOPCNT_INFINITY)
15027244Sjhay					continue;
15111820Sjulian				sap_add(n, from);
15227244Sjhay				sapchanged = 1;
15311820Sjulian				continue;
15411820Sjulian			}
15511820Sjulian
15611820Sjulian			/*
15711820Sjulian			 * A clone is a different route to the same service
15811820Sjulian			 * with exactly the same cost (metric).
15911820Sjulian			 * They must all be recorded because those interfaces
16011820Sjulian			 * must be handled in the same way as the first route
16111820Sjulian			 * to that service. ie When using the split horizon
16211820Sjulian			 * algorithm we must look at these interfaces also.
16311820Sjulian			 *
16411820Sjulian			 * Update if from gateway and different,
16511820Sjulian			 * from anywhere and less hops or
16611820Sjulian			 * getting stale and equivalent.
16711820Sjulian			 */
16811820Sjulian			if (((ifp != sap->ifp) ||
16911820Sjulian			     !equal(&sap->source, from)) &&
17011820Sjulian			    (n->hops == sap->sap.hops) &&
17111820Sjulian			    (ntohs(n->hops) != HOPCNT_INFINITY)) {
17211820Sjulian				register struct sap_entry *tsap = sap->clone;
17311820Sjulian
17411820Sjulian				while (tsap) {
17511820Sjulian					if ((ifp == tsap->ifp) &&
17611820Sjulian					    equal(&tsap->source, from)) {
17711820Sjulian						tsap->timer = 0;
17811820Sjulian						break;
17911820Sjulian					}
18012620Sjulian					tsap = tsap->clone;
18111820Sjulian				}
18211820Sjulian				if (tsap == NULL) {
18311820Sjulian					sap_add_clone(sap, n, from);
18411820Sjulian				}
18511820Sjulian				continue;
18611820Sjulian			}
18727244Sjhay			if ((ifp == sap->ifp) &&
18827244Sjhay			    equal(&sap->source, from) &&
18927244Sjhay			    (ntohs(n->hops) == ntohs(sap->sap.hops)))
19027244Sjhay				sap->timer = 0;
19127244Sjhay			else if (((ifp == sap->ifp) &&
19227244Sjhay				  equal(&sap->source, from) &&
19327244Sjhay				  (n->hops != sap->sap.hops)) ||
19427244Sjhay				 (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
19527244Sjhay				 (sap->timer > (EXPIRE_TIME*2/3) &&
19627244Sjhay				  ntohs(sap->sap.hops) == ntohs(n->hops) &&
19727244Sjhay				  ntohs(n->hops) != HOPCNT_INFINITY)) {
19811820Sjulian				sap_change(sap, n, from);
19927244Sjhay				sapchanged = 1;
20011820Sjulian			}
20111820Sjulian		}
20227244Sjhay		if (sapchanged) {
20327244Sjhay			register struct sap_entry *sap;
20427244Sjhay			register struct sap_hash *sh;
20527244Sjhay			sap_supply_toall(1);
20627244Sjhay
20727244Sjhay			for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++)
20827244Sjhay				for (sap = sh->forw;
20927244Sjhay				    sap != (struct sap_entry *)sh;
21027244Sjhay				    sap = sap->forw)
21127244Sjhay					sap->state &= ~RTS_CHANGED;
21227244Sjhay		}
21311820Sjulian		return;
21411820Sjulian	}
21511820Sjulian}
216