sap_input.c revision 11820
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 *
3111820Sjulian *	$Id: sap_input.c,v 1.6 1995/10/11 18:57:27 jhay Exp $
3211820Sjulian */
3311820Sjulian
3411820Sjulian/*
3511820Sjulian * IPX Routing Table Management Daemon
3611820Sjulian */
3711820Sjulian#include "defs.h"
3811820Sjulian
3911820Sjulian
4011820Sjulian/*
4111820Sjulian * Process a newly received packet.
4211820Sjulian */
4311820Sjulianvoid
4411820Sjuliansap_input(from, size)
4511820Sjulian	struct sockaddr *from;
4611820Sjulian	int size;
4711820Sjulian{
4811820Sjulian	struct sap_entry *sap;
4911820Sjulian	struct sap_info *n;
5011820Sjulian	struct interface *ifp = 0;
5111820Sjulian	int newsize;
5211820Sjulian	struct afswitch *afp;
5311820Sjulian	struct sockaddr_ipx *ipxp;
5411820Sjulian
5511820Sjulian	ifp = if_ifwithnet(from);
5611820Sjulian	ipxp = (struct sockaddr_ipx *)from;
5711820Sjulian	if (ifp == 0) {
5811820Sjulian		if(ftrace) {
5911820Sjulian			fprintf(ftrace, "Received bogus packet from %s\n",
6011820Sjulian				ipxdp_ntoa(&ipxp->sipx_addr));
6111820Sjulian		}
6211820Sjulian		return;
6311820Sjulian	}
6411820Sjulian
6511820Sjulian	if (ftrace)
6611820Sjulian		dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
6711820Sjulian
6811820Sjulian	if (from->sa_family >= AF_MAX)
6911820Sjulian		return;
7011820Sjulian	afp = &afswitch[from->sa_family];
7111820Sjulian
7211820Sjulian	size -= sizeof (u_short)	/* command */;
7311820Sjulian	n = sap_msg->sap;
7411820Sjulian
7511820Sjulian	switch (ntohs(sap_msg->sap_cmd)) {
7611820Sjulian
7711820Sjulian	case SAP_REQ_NEAR:
7811820Sjulian		if (ftrace)
7911820Sjulian			fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
8011820Sjulian		sap = sap_nearestserver(n->ServType, ifp);
8111820Sjulian		if (sap == NULL)
8211820Sjulian			return;
8311820Sjulian		sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
8411820Sjulian		*n = sap->sap;
8511820Sjulian		n->hops = htons(ntohs(n->hops) + 1);
8611820Sjulian		if (ntohs(n->hops) >= HOPCNT_INFINITY)
8711820Sjulian			return;
8811820Sjulian
8911820Sjulian		newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
9011820Sjulian		(*afp->af_output)(sapsock, 0, from, newsize);
9111820Sjulian		if (ftrace) {
9211820Sjulian			fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
9311820Sjulian				ntohs(n->ServType),
9411820Sjulian				ifp->int_name);
9511820Sjulian			fprintf(ftrace, "  service %04X %-20.20s "
9611820Sjulian					"addr %s.%04X metric %d\n",
9711820Sjulian					ntohs(sap->sap.ServType),
9811820Sjulian					sap->sap.ServName,
9911820Sjulian					ipxdp_ntoa(&sap->sap.ipx),
10011820Sjulian					ntohs(sap->sap.ipx.x_port),
10111820Sjulian					ntohs(sap->sap.hops));
10211820Sjulian		}
10311820Sjulian		return;
10411820Sjulian
10511820Sjulian	case SAP_REQ:
10611820Sjulian		if (ftrace)
10711820Sjulian			fprintf(ftrace, "Received a sap REQ packet.\n");
10811820Sjulian
10911820Sjulian		sap_supply(from, 0, ifp, n->ServType);
11011820Sjulian		return;
11111820Sjulian
11211820Sjulian	case SAP_RESP_NEAR:
11311820Sjulian		/* XXX We do nothing here, for the moment.
11411820Sjulian		 * Maybe we should check if the service is in our table?
11511820Sjulian		 *
11611820Sjulian		 */
11711820Sjulian		if (ftrace)
11811820Sjulian			fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
11911820Sjulian
12011820Sjulian		return;
12111820Sjulian
12211820Sjulian	case SAP_RESP:
12311820Sjulian		if (ftrace)
12411820Sjulian			fprintf(ftrace, "Received a sap RESP packet.\n");
12511820Sjulian
12611820Sjulian		(*afp->af_canon)(from);
12711820Sjulian
12811820Sjulian		for (; size > 0; size -= sizeof (struct sap_info), n++) {
12911820Sjulian			if (size < sizeof (struct netinfo))
13011820Sjulian				break;
13111820Sjulian			sap = sap_lookup(n->ServType, n->ServName);
13211820Sjulian			if (sap == 0) {
13311820Sjulian				sap_add(n, from);
13411820Sjulian				continue;
13511820Sjulian			}
13611820Sjulian
13711820Sjulian			/*
13811820Sjulian			 * A clone is a different route to the same service
13911820Sjulian			 * with exactly the same cost (metric).
14011820Sjulian			 * They must all be recorded because those interfaces
14111820Sjulian			 * must be handled in the same way as the first route
14211820Sjulian			 * to that service. ie When using the split horizon
14311820Sjulian			 * algorithm we must look at these interfaces also.
14411820Sjulian			 *
14511820Sjulian			 * Update if from gateway and different,
14611820Sjulian			 * from anywhere and less hops or
14711820Sjulian			 * getting stale and equivalent.
14811820Sjulian			 *
14911820Sjulian			 * XXX I don't think this is quite right yet.
15011820Sjulian			 */
15111820Sjulian			if (((ifp != sap->ifp) ||
15211820Sjulian			     !equal(&sap->source, from)) &&
15311820Sjulian			    (n->hops == sap->sap.hops) &&
15411820Sjulian			    (ntohs(n->hops) != HOPCNT_INFINITY)) {
15511820Sjulian				register struct sap_entry *tsap = sap->clone;
15611820Sjulian
15711820Sjulian				while (tsap) {
15811820Sjulian					if ((ifp == tsap->ifp) &&
15911820Sjulian					    equal(&tsap->source, from)) {
16011820Sjulian						tsap->timer = 0;
16111820Sjulian						break;
16211820Sjulian					}
16311820Sjulian				}
16411820Sjulian				if (tsap == NULL) {
16511820Sjulian					sap_add_clone(sap, n, from);
16611820Sjulian				}
16711820Sjulian				continue;
16811820Sjulian			}
16911820Sjulian			if (((ifp == sap->ifp) &&
17011820Sjulian			     equal(&sap->source, from) &&
17111820Sjulian			    (n->hops != sap->sap.hops)) ||
17211820Sjulian			    (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
17311820Sjulian			    (sap->timer > (EXPIRE_TIME*2/3) &&
17411820Sjulian			    ntohs(sap->sap.hops) == ntohs(n->hops))) {
17511820Sjulian				sap_change(sap, n, from);
17611820Sjulian			}
17711820Sjulian		}
17811820Sjulian		return;
17911820Sjulian	}
18011820Sjulian}
181