sap_output.c revision 97638
1251652Sgjb/* 2251652Sgjb * Copyright (c) 1995 John Hay. All rights reserved. 3251652Sgjb * 4251652Sgjb * Redistribution and use in source and binary forms, with or without 5251652Sgjb * modification, are permitted provided that the following conditions 6251652Sgjb * are met: 7251652Sgjb * 1. Redistributions of source code must retain the above copyright 8251652Sgjb * notice, this list of conditions and the following disclaimer. 9251652Sgjb * 2. Redistributions in binary form must reproduce the above copyright 10251652Sgjb * notice, this list of conditions and the following disclaimer in the 11251652Sgjb * documentation and/or other materials provided with the distribution. 12251652Sgjb * 3. All advertising materials mentioning features or use of this software 13251652Sgjb * must display the following acknowledgement: 14251652Sgjb * This product includes software developed by John Hay. 15251652Sgjb * 4. Neither the name of the author nor the names of any co-contributors 16251652Sgjb * may be used to endorse or promote products derived from this software 17251652Sgjb * without specific prior written permission. 18251652Sgjb * 19251652Sgjb * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND 20251652Sgjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21251652Sgjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22251652Sgjb * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE 23251652Sgjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24251652Sgjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25251652Sgjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26251652Sgjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27251652Sgjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28251652Sgjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29251652Sgjb * SUCH DAMAGE. 30251652Sgjb * 31251652Sgjb * $FreeBSD: head/usr.sbin/IPXrouted/sap_output.c 97638 2002-05-30 21:49:15Z wollman $ 32251652Sgjb */ 33251652Sgjb 34251652Sgjb/* 35251652Sgjb * Routing Table Management Daemon 36251652Sgjb */ 37251652Sgjb#include <unistd.h> 38251652Sgjb#include "defs.h" 39251652Sgjb 40251652Sgjb/* 41251652Sgjb * Apply the function "f" to all non-passive 42251652Sgjb * interfaces. If the interface supports the 43251652Sgjb * use of broadcasting use it, otherwise address 44251652Sgjb * the output to the known router. 45251652Sgjb */ 46251652Sgjbvoid 47251652Sgjbsap_supply_toall(changesonly) 48251652Sgjb int changesonly; 49251652Sgjb{ 50251652Sgjb register struct interface *ifp; 51251652Sgjb struct sockaddr dst; 52251652Sgjb register struct sockaddr_ipx *ipx_dst; 53251652Sgjb register int flags; 54251652Sgjb extern struct interface *ifnet; 55251652Sgjb 56251652Sgjb ipx_dst = (struct sockaddr_ipx *)&dst; 57251652Sgjb 58251652Sgjb for (ifp = ifnet; ifp; ifp = ifp->int_next) { 59251652Sgjb if (ifp->int_flags & IFF_PASSIVE) 60251652Sgjb continue; 61251652Sgjb 62251652Sgjb dst = ifp->int_flags & IFF_BROADCAST ? ifp->int_broadaddr : 63251652Sgjb ifp->int_flags & IFF_POINTOPOINT ? ifp->int_dstaddr : 64251652Sgjb ifp->int_addr; 65251652Sgjb 66251652Sgjb ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP); 67251652Sgjb 68251652Sgjb flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; 69251652Sgjb sap_supply(&dst, flags, ifp, SAP_WILDCARD, changesonly); 70251652Sgjb } 71251652Sgjb} 72251652Sgjb 73251652Sgjbvoid 74251652Sgjbsapsndmsg(dst, flags, ifp, changesonly) 75251652Sgjb struct sockaddr *dst; 76251652Sgjb int flags; 77251652Sgjb struct interface *ifp; 78251652Sgjb int changesonly; 79251652Sgjb{ 80251652Sgjb struct sockaddr t_dst; 81251652Sgjb struct sockaddr_ipx *ipx_dst; 82251652Sgjb 83251652Sgjb t_dst = *dst; 84251652Sgjb ipx_dst = (struct sockaddr_ipx *)&t_dst; 85251652Sgjb 86251652Sgjb if (ipx_dst->sipx_addr.x_port == 0) 87251652Sgjb ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP); 88251652Sgjb 89251652Sgjb (*afswitch[dst->sa_family].af_output) 90251652Sgjb (sapsock, flags, &t_dst, 91251652Sgjb sizeof (struct sap_packet) + sizeof(u_short)); 92251652Sgjb TRACE_SAP_OUTPUT(ifp, &t_dst, 93251652Sgjb sizeof (struct sap_packet) + sizeof(u_short)); 94251652Sgjb} 95251652Sgjb 96251652Sgjb/* 97251652Sgjb * Supply dst with the contents of the SAP tables. If the ServType == 98251652Sgjb * SAP_WILDCARD (0xFFFF) supply the whole table, otherwise only the 99251652Sgjb * services that are of ServType. If this won't fit in one packet, chop 100251652Sgjb * it up into several. 101251652Sgjb * 102251652Sgjb * This must be done using the split horizon algorithm. 103251652Sgjb * 1. Don't send SAP info to the interface from where it was received. 104251652Sgjb * 2. If a service is received from more than one interface and the cost is 105251652Sgjb * the same, don't publish it on either interface. I am calling this 106251652Sgjb * clones. 107251652Sgjb */ 108251652Sgjbvoid 109251652Sgjbsap_supply(dst, flags, ifp, ServType, changesonly) 110251652Sgjb struct sockaddr *dst; 111251652Sgjb int flags; 112251652Sgjb struct interface *ifp; 113251652Sgjb int ServType; 114251652Sgjb int changesonly; 115251652Sgjb{ 116251652Sgjb register struct sap_entry *sap; 117251652Sgjb register struct sap_entry *csap; /* Clone route */ 118251652Sgjb register struct sap_hash *sh; 119251652Sgjb register struct sap_info *n = sap_msg->sap; 120251652Sgjb struct sap_hash *base = sap_head; 121251652Sgjb struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; 122251652Sgjb af_output_t *output = afswitch[dst->sa_family].af_output; 123251652Sgjb int size, metric; 124251652Sgjb int delay = 0; 125251652Sgjb 126251652Sgjb if (sipx->sipx_port == 0) 127251652Sgjb sipx->sipx_port = htons(IPXPORT_SAP); 128251652Sgjb 129251652Sgjb sap_msg->sap_cmd = ntohs(SAP_RESP); 130251652Sgjb 131251652Sgjb for (sh = base; sh < &base[SAPHASHSIZ]; sh++) 132251652Sgjb for (sap = sh->forw; sap != (struct sap_entry *)sh; sap = sap->forw) { 133251652Sgjb size = (char *)n - (char *)sap_msg; 134251652Sgjb if (size >= ((MAXSAPENTRIES * sizeof (struct sap_info)) + 135251652Sgjb sizeof (sap_msg->sap_cmd))) { 136251652Sgjb (*output)(sapsock, flags, dst, size); 137251652Sgjb TRACE_SAP_OUTPUT(ifp, dst, size); 138251652Sgjb n = sap_msg->sap; 139251652Sgjb delay++; 140251652Sgjb if(delay == 2) { 141251652Sgjb usleep(50000); 142251652Sgjb delay = 0; 143251652Sgjb } 144251652Sgjb } 145251652Sgjb 146251652Sgjb if (changesonly && !(sap->state & RTS_CHANGED)) 147251652Sgjb continue; 148251652Sgjb 149251652Sgjb /* 150251652Sgjb * Check for the servicetype except if the ServType is 151251652Sgjb * a wildcard (0xFFFF). 152251652Sgjb */ 153251652Sgjb if ((ServType != SAP_WILDCARD) && 154251652Sgjb (ServType != sap->sap.ServType)) 155251652Sgjb continue; 156251652Sgjb 157251652Sgjb /* 158251652Sgjb * This should do rule one and two of the split horizon 159251652Sgjb * algorithm. 160251652Sgjb */ 161251652Sgjb if (sap->ifp == ifp) 162251652Sgjb continue; 163251652Sgjb 164251652Sgjb /* 165251652Sgjb * Rule 2. 166251652Sgjb * Look if we have clones (different routes to the same 167251652Sgjb * place with exactly the same cost). 168251652Sgjb * 169251652Sgjb * We should not publish on any of the clone interfaces. 170251652Sgjb */ 171251652Sgjb csap = sap->clone; 172251652Sgjb while (csap) { 173251652Sgjb if (csap->ifp == ifp) 174251652Sgjb goto next; 175251652Sgjb csap = csap->clone; 176251652Sgjb } 177251652Sgjb 178251652Sgjb /* 179251652Sgjb * Don't advertise services with more than 15 hops. It 180251652Sgjb * will be confused with a service that has gone down. 181251652Sgjb */ 182251652Sgjb if (ntohs(sap->sap.hops) == (HOPCNT_INFINITY - 1)) 183251652Sgjb continue; 184251652Sgjb metric = min(ntohs(sap->sap.hops) + 1, HOPCNT_INFINITY); 185251652Sgjb 186251652Sgjb *n = sap->sap; 187251652Sgjb n->hops = htons(metric); 188251652Sgjb n++; 189251652Sgjbnext: 190251652Sgjb ; 191251652Sgjb } 192251652Sgjb if (n != sap_msg->sap) { 193251652Sgjb size = (char *)n - (char *)sap_msg; 194 (*output)(sapsock, flags, dst, size); 195 TRACE_SAP_OUTPUT(ifp, dst, size); 196 } 197} 198 199