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