sap_input.c revision 45988
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 * 3145988Sjhay * $Id: sap_input.c,v 1.5 1997/07/06 07:38:31 jhay Exp $ 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 13927244Sjhay * that a service went down. If we don't allready 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