sap_input.c revision 27244
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 *
3127244Sjhay *	$Id: sap_input.c,v 1.4 1997/02/22 16:00:59 peter 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{
4827244Sjhay	int newsize;
4927244Sjhay	int sapchanged = 0;
5011820Sjulian	struct sap_entry *sap;
5111820Sjulian	struct sap_info *n;
5211820Sjulian	struct interface *ifp = 0;
5311820Sjulian	struct afswitch *afp;
5411820Sjulian	struct sockaddr_ipx *ipxp;
5511820Sjulian
5611820Sjulian	ifp = if_ifwithnet(from);
5711820Sjulian	ipxp = (struct sockaddr_ipx *)from;
5811820Sjulian	if (ifp == 0) {
5911820Sjulian		if(ftrace) {
6011820Sjulian			fprintf(ftrace, "Received bogus packet from %s\n",
6111820Sjulian				ipxdp_ntoa(&ipxp->sipx_addr));
6211820Sjulian		}
6311820Sjulian		return;
6411820Sjulian	}
6511820Sjulian
6611820Sjulian	if (ftrace)
6711820Sjulian		dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
6811820Sjulian
6911820Sjulian	if (from->sa_family >= AF_MAX)
7011820Sjulian		return;
7111820Sjulian	afp = &afswitch[from->sa_family];
7211820Sjulian
7311820Sjulian	size -= sizeof (u_short)	/* command */;
7411820Sjulian	n = sap_msg->sap;
7511820Sjulian
7611820Sjulian	switch (ntohs(sap_msg->sap_cmd)) {
7711820Sjulian
7811820Sjulian	case SAP_REQ_NEAR:
7911820Sjulian		if (ftrace)
8011820Sjulian			fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
8111820Sjulian		sap = sap_nearestserver(n->ServType, ifp);
8211820Sjulian		if (sap == NULL)
8311820Sjulian			return;
8411820Sjulian		sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
8511820Sjulian		*n = sap->sap;
8611820Sjulian		n->hops = htons(ntohs(n->hops) + 1);
8711820Sjulian		if (ntohs(n->hops) >= HOPCNT_INFINITY)
8811820Sjulian			return;
8911820Sjulian
9011820Sjulian		newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
9111820Sjulian		(*afp->af_output)(sapsock, 0, from, newsize);
9211820Sjulian		if (ftrace) {
9311820Sjulian			fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
9411820Sjulian				ntohs(n->ServType),
9511820Sjulian				ifp->int_name);
9611820Sjulian			fprintf(ftrace, "  service %04X %-20.20s "
9711820Sjulian					"addr %s.%04X metric %d\n",
9811820Sjulian					ntohs(sap->sap.ServType),
9911820Sjulian					sap->sap.ServName,
10011820Sjulian					ipxdp_ntoa(&sap->sap.ipx),
10111820Sjulian					ntohs(sap->sap.ipx.x_port),
10211820Sjulian					ntohs(sap->sap.hops));
10311820Sjulian		}
10411820Sjulian		return;
10511820Sjulian
10611820Sjulian	case SAP_REQ:
10711820Sjulian		if (ftrace)
10811820Sjulian			fprintf(ftrace, "Received a sap REQ packet.\n");
10911820Sjulian
11027244Sjhay		sap_supply(from, 0, ifp, n->ServType, 0);
11111820Sjulian		return;
11211820Sjulian
11311820Sjulian	case SAP_RESP_NEAR:
11411820Sjulian		/* XXX We do nothing here, for the moment.
11511820Sjulian		 * Maybe we should check if the service is in our table?
11611820Sjulian		 *
11711820Sjulian		 */
11811820Sjulian		if (ftrace)
11911820Sjulian			fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
12011820Sjulian
12111820Sjulian		return;
12211820Sjulian
12311820Sjulian	case SAP_RESP:
12411820Sjulian		if (ftrace)
12511820Sjulian			fprintf(ftrace, "Received a sap RESP packet.\n");
12611820Sjulian
12711820Sjulian		(*afp->af_canon)(from);
12811820Sjulian
12911820Sjulian		for (; size > 0; size -= sizeof (struct sap_info), n++) {
13011820Sjulian			if (size < sizeof (struct netinfo))
13111820Sjulian				break;
13227244Sjhay			/*
13327244Sjhay			 * The idea here is that if the hop count is more
13427244Sjhay			 * than INFINITY it is bogus and should be discarded.
13527244Sjhay			 * If it is equal to INFINITY it is a message to say
13627244Sjhay			 * that a service went down. If we don't allready
13727244Sjhay			 * have it in our tables discard it. Otherwise
13827244Sjhay			 * update our table and set the timer to EXPIRE_TIME
13927244Sjhay			 * so that it is removed next time we go through the
14027244Sjhay			 * tables.
14127244Sjhay			 */
14227244Sjhay			if (ntohs(n->hops) > HOPCNT_INFINITY)
14327244Sjhay				continue;
14411820Sjulian			sap = sap_lookup(n->ServType, n->ServName);
14511820Sjulian			if (sap == 0) {
14627244Sjhay				if (ntohs(n->hops) == HOPCNT_INFINITY)
14727244Sjhay					continue;
14811820Sjulian				sap_add(n, from);
14927244Sjhay				sapchanged = 1;
15011820Sjulian				continue;
15111820Sjulian			}
15211820Sjulian
15311820Sjulian			/*
15411820Sjulian			 * A clone is a different route to the same service
15511820Sjulian			 * with exactly the same cost (metric).
15611820Sjulian			 * They must all be recorded because those interfaces
15711820Sjulian			 * must be handled in the same way as the first route
15811820Sjulian			 * to that service. ie When using the split horizon
15911820Sjulian			 * algorithm we must look at these interfaces also.
16011820Sjulian			 *
16111820Sjulian			 * Update if from gateway and different,
16211820Sjulian			 * from anywhere and less hops or
16311820Sjulian			 * getting stale and equivalent.
16411820Sjulian			 */
16511820Sjulian			if (((ifp != sap->ifp) ||
16611820Sjulian			     !equal(&sap->source, from)) &&
16711820Sjulian			    (n->hops == sap->sap.hops) &&
16811820Sjulian			    (ntohs(n->hops) != HOPCNT_INFINITY)) {
16911820Sjulian				register struct sap_entry *tsap = sap->clone;
17011820Sjulian
17111820Sjulian				while (tsap) {
17211820Sjulian					if ((ifp == tsap->ifp) &&
17311820Sjulian					    equal(&tsap->source, from)) {
17411820Sjulian						tsap->timer = 0;
17511820Sjulian						break;
17611820Sjulian					}
17712620Sjulian					tsap = tsap->clone;
17811820Sjulian				}
17911820Sjulian				if (tsap == NULL) {
18011820Sjulian					sap_add_clone(sap, n, from);
18111820Sjulian				}
18211820Sjulian				continue;
18311820Sjulian			}
18427244Sjhay			if ((ifp == sap->ifp) &&
18527244Sjhay			    equal(&sap->source, from) &&
18627244Sjhay			    (ntohs(n->hops) == ntohs(sap->sap.hops)))
18727244Sjhay				sap->timer = 0;
18827244Sjhay			else if (((ifp == sap->ifp) &&
18927244Sjhay				  equal(&sap->source, from) &&
19027244Sjhay				  (n->hops != sap->sap.hops)) ||
19127244Sjhay				 (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
19227244Sjhay				 (sap->timer > (EXPIRE_TIME*2/3) &&
19327244Sjhay				  ntohs(sap->sap.hops) == ntohs(n->hops) &&
19427244Sjhay				  ntohs(n->hops) != HOPCNT_INFINITY)) {
19511820Sjulian				sap_change(sap, n, from);
19627244Sjhay				sapchanged = 1;
19711820Sjulian			}
19811820Sjulian		}
19927244Sjhay		if (sapchanged) {
20027244Sjhay			register struct sap_entry *sap;
20127244Sjhay			register struct sap_hash *sh;
20227244Sjhay			sap_supply_toall(1);
20327244Sjhay
20427244Sjhay			for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++)
20527244Sjhay				for (sap = sh->forw;
20627244Sjhay				    sap != (struct sap_entry *)sh;
20727244Sjhay				    sap = sap->forw)
20827244Sjhay					sap->state &= ~RTS_CHANGED;
20927244Sjhay		}
21011820Sjulian		return;
21111820Sjulian	}
21211820Sjulian}
213