sap_input.c revision 228990
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 * $FreeBSD: head/usr.sbin/IPXrouted/sap_input.c 228990 2011-12-30 10:58:14Z uqs $ 32 */ 33 34/* 35 * IPX Routing Table Management Daemon 36 */ 37#include "defs.h" 38 39int dognreply = 1; 40 41/* 42 * Process a newly received packet. 43 */ 44void 45sap_input(from, size) 46 struct sockaddr *from; 47 int size; 48{ 49 int newsize; 50 int sapchanged = 0; 51 struct sap_entry *sap; 52 struct sap_info *n; 53 struct interface *ifp = 0; 54 struct afswitch *afp; 55 struct sockaddr_ipx *ipxp; 56 57 ifp = if_ifwithnet(from); 58 ipxp = (struct sockaddr_ipx *)from; 59 if (ifp == 0) { 60 if(ftrace) { 61 fprintf(ftrace, "Received bogus packet from %s\n", 62 ipxdp_ntoa(&ipxp->sipx_addr)); 63 } 64 return; 65 } 66 67 if (ftrace) 68 dumpsappacket(ftrace, "received", from, (char *)sap_msg , size); 69 70 if (from->sa_family >= AF_MAX) 71 return; 72 afp = &afswitch[from->sa_family]; 73 74 size -= sizeof (u_short) /* command */; 75 n = sap_msg->sap; 76 77 switch (ntohs(sap_msg->sap_cmd)) { 78 79 case SAP_REQ_NEAR: 80 if (ftrace) 81 fprintf(ftrace, "Received a sap REQ_NEAR packet.\n"); 82 if (!dognreply) 83 return; 84 sap = sap_nearestserver(n->ServType, ifp); 85 if (sap == NULL) 86 return; 87 sap_msg->sap_cmd = htons(SAP_RESP_NEAR); 88 *n = sap->sap; 89 n->hops = htons(ntohs(n->hops) + 1); 90 if (ntohs(n->hops) >= HOPCNT_INFINITY) 91 return; 92 93 newsize = sizeof(struct sap_info) + sizeof(struct sap_packet); 94 (*afp->af_output)(sapsock, 0, from, newsize); 95 if (ftrace) { 96 fprintf(ftrace, "sap_nearestserver %X %s returned:\n", 97 ntohs(n->ServType), 98 ifp->int_name); 99 fprintf(ftrace, " service %04X %-20.20s " 100 "addr %s.%04X metric %d\n", 101 ntohs(sap->sap.ServType), 102 sap->sap.ServName, 103 ipxdp_ntoa(&sap->sap.ipx), 104 ntohs(sap->sap.ipx.x_port), 105 ntohs(sap->sap.hops)); 106 } 107 return; 108 109 case SAP_REQ: 110 if (ftrace) 111 fprintf(ftrace, "Received a sap REQ packet.\n"); 112 113 sap_supply(from, 0, ifp, n->ServType, 0); 114 return; 115 116 case SAP_RESP_NEAR: 117 /* XXX We do nothing here, for the moment. 118 * Maybe we should check if the service is in our table? 119 * 120 */ 121 if (ftrace) 122 fprintf(ftrace, "Received a sap RESP_NEAR packet.\n"); 123 124 return; 125 126 case SAP_RESP: 127 if (ftrace) 128 fprintf(ftrace, "Received a sap RESP packet.\n"); 129 130 (*afp->af_canon)(from); 131 132 for (; size > 0; size -= sizeof (struct sap_info), n++) { 133 if (size < sizeof (struct netinfo)) 134 break; 135 /* 136 * The idea here is that if the hop count is more 137 * than INFINITY it is bogus and should be discarded. 138 * If it is equal to INFINITY it is a message to say 139 * that a service went down. If we don't already 140 * have it in our tables discard it. Otherwise 141 * update our table and set the timer to EXPIRE_TIME 142 * so that it is removed next time we go through the 143 * tables. 144 */ 145 if (ntohs(n->hops) > HOPCNT_INFINITY) 146 continue; 147 sap = sap_lookup(n->ServType, n->ServName); 148 if (sap == 0) { 149 if (ntohs(n->hops) == HOPCNT_INFINITY) 150 continue; 151 sap_add(n, from); 152 sapchanged = 1; 153 continue; 154 } 155 156 /* 157 * A clone is a different route to the same service 158 * with exactly the same cost (metric). 159 * They must all be recorded because those interfaces 160 * must be handled in the same way as the first route 161 * to that service. ie When using the split horizon 162 * algorithm we must look at these interfaces also. 163 * 164 * Update if from gateway and different, 165 * from anywhere and less hops or 166 * getting stale and equivalent. 167 */ 168 if (((ifp != sap->ifp) || 169 !equal(&sap->source, from)) && 170 (n->hops == sap->sap.hops) && 171 (ntohs(n->hops) != HOPCNT_INFINITY)) { 172 register struct sap_entry *tsap = sap->clone; 173 174 while (tsap) { 175 if ((ifp == tsap->ifp) && 176 equal(&tsap->source, from)) { 177 tsap->timer = 0; 178 break; 179 } 180 tsap = tsap->clone; 181 } 182 if (tsap == NULL) { 183 sap_add_clone(sap, n, from); 184 } 185 continue; 186 } 187 if ((ifp == sap->ifp) && 188 equal(&sap->source, from) && 189 (ntohs(n->hops) == ntohs(sap->sap.hops))) 190 sap->timer = 0; 191 else if (((ifp == sap->ifp) && 192 equal(&sap->source, from) && 193 (n->hops != sap->sap.hops)) || 194 (ntohs(n->hops) < ntohs(sap->sap.hops)) || 195 (sap->timer > (EXPIRE_TIME*2/3) && 196 ntohs(sap->sap.hops) == ntohs(n->hops) && 197 ntohs(n->hops) != HOPCNT_INFINITY)) { 198 sap_change(sap, n, from); 199 sapchanged = 1; 200 } 201 } 202 if (sapchanged) { 203 register struct sap_entry *sap; 204 register struct sap_hash *sh; 205 sap_supply_toall(1); 206 207 for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) 208 for (sap = sh->forw; 209 sap != (struct sap_entry *)sh; 210 sap = sap->forw) 211 sap->state &= ~RTS_CHANGED; 212 } 213 return; 214 } 215} 216