sap_input.c revision 22997
1/*
2 * Copyright (c) 1995 John Hay.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 *    must display the following acknowledgement:
14 *	This product includes software developed by John Hay.
15 * 4. Neither the name of the author nor the names of any co-contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	$Id$
32 */
33
34/*
35 * IPX Routing Table Management Daemon
36 */
37#include "defs.h"
38
39
40/*
41 * Process a newly received packet.
42 */
43void
44sap_input(from, size)
45	struct sockaddr *from;
46	int size;
47{
48	struct sap_entry *sap;
49	struct sap_info *n;
50	struct interface *ifp = 0;
51	int newsize;
52	struct afswitch *afp;
53	struct sockaddr_ipx *ipxp;
54
55	ifp = if_ifwithnet(from);
56	ipxp = (struct sockaddr_ipx *)from;
57	if (ifp == 0) {
58		if(ftrace) {
59			fprintf(ftrace, "Received bogus packet from %s\n",
60				ipxdp_ntoa(&ipxp->sipx_addr));
61		}
62		return;
63	}
64
65	if (ftrace)
66		dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
67
68	if (from->sa_family >= AF_MAX)
69		return;
70	afp = &afswitch[from->sa_family];
71
72	size -= sizeof (u_short)	/* command */;
73	n = sap_msg->sap;
74
75	switch (ntohs(sap_msg->sap_cmd)) {
76
77	case SAP_REQ_NEAR:
78		if (ftrace)
79			fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
80		sap = sap_nearestserver(n->ServType, ifp);
81		if (sap == NULL)
82			return;
83		sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
84		*n = sap->sap;
85		n->hops = htons(ntohs(n->hops) + 1);
86		if (ntohs(n->hops) >= HOPCNT_INFINITY)
87			return;
88
89		newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
90		(*afp->af_output)(sapsock, 0, from, newsize);
91		if (ftrace) {
92			fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
93				ntohs(n->ServType),
94				ifp->int_name);
95			fprintf(ftrace, "  service %04X %-20.20s "
96					"addr %s.%04X metric %d\n",
97					ntohs(sap->sap.ServType),
98					sap->sap.ServName,
99					ipxdp_ntoa(&sap->sap.ipx),
100					ntohs(sap->sap.ipx.x_port),
101					ntohs(sap->sap.hops));
102		}
103		return;
104
105	case SAP_REQ:
106		if (ftrace)
107			fprintf(ftrace, "Received a sap REQ packet.\n");
108
109		sap_supply(from, 0, ifp, n->ServType);
110		return;
111
112	case SAP_RESP_NEAR:
113		/* XXX We do nothing here, for the moment.
114		 * Maybe we should check if the service is in our table?
115		 *
116		 */
117		if (ftrace)
118			fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
119
120		return;
121
122	case SAP_RESP:
123		if (ftrace)
124			fprintf(ftrace, "Received a sap RESP packet.\n");
125
126		(*afp->af_canon)(from);
127
128		for (; size > 0; size -= sizeof (struct sap_info), n++) {
129			if (size < sizeof (struct netinfo))
130				break;
131			sap = sap_lookup(n->ServType, n->ServName);
132			if (sap == 0) {
133				sap_add(n, from);
134				continue;
135			}
136
137			/*
138			 * A clone is a different route to the same service
139			 * with exactly the same cost (metric).
140			 * They must all be recorded because those interfaces
141			 * must be handled in the same way as the first route
142			 * to that service. ie When using the split horizon
143			 * algorithm we must look at these interfaces also.
144			 *
145			 * Update if from gateway and different,
146			 * from anywhere and less hops or
147			 * getting stale and equivalent.
148			 *
149			 * XXX I don't think this is quite right yet.
150			 */
151			if (((ifp != sap->ifp) ||
152			     !equal(&sap->source, from)) &&
153			    (n->hops == sap->sap.hops) &&
154			    (ntohs(n->hops) != HOPCNT_INFINITY)) {
155				register struct sap_entry *tsap = sap->clone;
156
157				while (tsap) {
158					if ((ifp == tsap->ifp) &&
159					    equal(&tsap->source, from)) {
160						tsap->timer = 0;
161						break;
162					}
163					tsap = tsap->clone;
164				}
165				if (tsap == NULL) {
166					sap_add_clone(sap, n, from);
167				}
168				continue;
169			}
170			if (((ifp == sap->ifp) &&
171			     equal(&sap->source, from) &&
172			    (n->hops != sap->sap.hops)) ||
173			    (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
174			    (sap->timer > (EXPIRE_TIME*2/3) &&
175			    ntohs(sap->sap.hops) == ntohs(n->hops))) {
176				sap_change(sap, n, from);
177			}
178		}
179		return;
180	}
181}
182