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