input.c revision 11820
111820Sjulian/* 211820Sjulian * Copyright (c) 1985, 1993 311820Sjulian * The Regents of the University of California. All rights reserved. 411820Sjulian * 511820Sjulian * Copyright (c) 1995 John Hay. All rights reserved. 611820Sjulian * 711820Sjulian * This file includes significant work done at Cornell University by 811820Sjulian * Bill Nesheim. That work included by permission. 911820Sjulian * 1011820Sjulian * Redistribution and use in source and binary forms, with or without 1111820Sjulian * modification, are permitted provided that the following conditions 1211820Sjulian * are met: 1311820Sjulian * 1. Redistributions of source code must retain the above copyright 1411820Sjulian * notice, this list of conditions and the following disclaimer. 1511820Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1611820Sjulian * notice, this list of conditions and the following disclaimer in the 1711820Sjulian * documentation and/or other materials provided with the distribution. 1811820Sjulian * 3. All advertising materials mentioning features or use of this software 1911820Sjulian * must display the following acknowledgement: 2011820Sjulian * This product includes software developed by the University of 2111820Sjulian * California, Berkeley and its contributors. 2211820Sjulian * 4. Neither the name of the University nor the names of its contributors 2311820Sjulian * may be used to endorse or promote products derived from this software 2411820Sjulian * without specific prior written permission. 2511820Sjulian * 2611820Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2711820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2811820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2911820Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3011820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3111820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3211820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3311820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3411820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3511820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3611820Sjulian * SUCH DAMAGE. 3711820Sjulian * 3811820Sjulian * $Id: input.c,v 1.9 1995/10/11 18:57:17 jhay Exp $ 3911820Sjulian */ 4011820Sjulian 4111820Sjulian#ifndef lint 4211820Sjulianstatic char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; 4311820Sjulian#endif /* not lint */ 4411820Sjulian 4511820Sjulian/* 4611820Sjulian * IPX Routing Table Management Daemon 4711820Sjulian */ 4811820Sjulian#include "defs.h" 4911820Sjulian 5011820Sjulianstruct sockaddr * 5111820Sjulianipx_nettosa(net) 5211820Sjulianunion ipx_net net; 5311820Sjulian{ 5411820Sjulian static struct sockaddr_ipx sxn; 5511820Sjulian extern char ether_broadcast_addr[6]; 5611820Sjulian 5711820Sjulian bzero(&sxn, sizeof (struct sockaddr_ipx)); 5811820Sjulian sxn.sipx_family = AF_IPX; 5911820Sjulian sxn.sipx_len = sizeof (sxn); 6011820Sjulian sxn.sipx_addr.x_net = net; 6111820Sjulian sxn.sipx_addr.x_host = *(union ipx_host *)ether_broadcast_addr; 6211820Sjulian return( (struct sockaddr *)&sxn); 6311820Sjulian 6411820Sjulian} 6511820Sjulian 6611820Sjulian/* 6711820Sjulian * Process a newly received packet. 6811820Sjulian */ 6911820Sjulianvoid 7011820Sjulianrip_input(from, size) 7111820Sjulian struct sockaddr *from; 7211820Sjulian int size; 7311820Sjulian{ 7411820Sjulian struct rt_entry *rt; 7511820Sjulian struct netinfo *n; 7611820Sjulian struct interface *ifp = 0; 7711820Sjulian int newsize; 7811820Sjulian struct afswitch *afp; 7911820Sjulian struct sockaddr_ipx *ipxp; 8011820Sjulian 8111820Sjulian ifp = if_ifwithnet(from); 8211820Sjulian ipxp = (struct sockaddr_ipx *)from; 8311820Sjulian if (ifp == 0) { 8411820Sjulian if(ftrace) { 8511820Sjulian fprintf(ftrace, "Received bogus packet from %s\n", 8611820Sjulian ipxdp_ntoa(&ipxp->sipx_addr)); 8711820Sjulian } 8811820Sjulian return; 8911820Sjulian } 9011820Sjulian 9111820Sjulian TRACE_INPUT(ifp, from, size); 9211820Sjulian if (from->sa_family >= AF_MAX) 9311820Sjulian return; 9411820Sjulian afp = &afswitch[from->sa_family]; 9511820Sjulian 9611820Sjulian size -= sizeof (u_short) /* command */; 9711820Sjulian n = msg->rip_nets; 9811820Sjulian 9911820Sjulian switch (ntohs(msg->rip_cmd)) { 10011820Sjulian 10111820Sjulian case RIPCMD_REQUEST: 10211820Sjulian if (ipx_hosteq(satoipx_addr(ifp->int_addr), ipxp->sipx_addr)) 10311820Sjulian return; 10411820Sjulian newsize = 0; 10511820Sjulian while (size > 0) { 10611820Sjulian if (size < sizeof (struct netinfo)) 10711820Sjulian break; 10811820Sjulian size -= sizeof (struct netinfo); 10911820Sjulian 11011820Sjulian /* 11111820Sjulian * A single entry with rip_dst == DSTNETS_ALL and 11211820Sjulian * metric ``infinity'' means ``all routes''. 11311820Sjulian * 11411820Sjulian * XXX According to the IPX RIP spec the metric 11511820Sjulian * and tick fields can be anything. So maybe we 11611820Sjulian * should not check the metric??? 11711820Sjulian */ 11811820Sjulian if (ipx_neteqnn(n->rip_dst, ipx_anynet) && 11911820Sjulian ntohs(n->rip_metric) == HOPCNT_INFINITY && 12011820Sjulian size == 0) { 12111820Sjulian supply(from, 0, ifp); 12211820Sjulian return; 12311820Sjulian } 12411820Sjulian /* 12511820Sjulian * request for specific nets 12611820Sjulian */ 12711820Sjulian rt = rtlookup(ipx_nettosa(n->rip_dst)); 12811820Sjulian if (ftrace) { 12911820Sjulian fprintf(ftrace, 13011820Sjulian "specific request for %s", 13111820Sjulian ipxdp_nettoa(n->rip_dst)); 13211820Sjulian fprintf(ftrace, 13311820Sjulian " yields route %x\n", 13411820Sjulian (u_int)rt); 13511820Sjulian } 13611820Sjulian /* 13711820Sjulian * XXX We break out on the first net that isn't 13811820Sjulian * found. The specs is a bit vague here. I'm not 13911820Sjulian * sure what we should do. 14011820Sjulian */ 14111820Sjulian if (rt == 0) 14211820Sjulian return; 14311820Sjulian /* XXX 14411820Sjulian * According to the spec we should not include 14511820Sjulian * information about networks for which the number 14611820Sjulian * of hops is 16. 14711820Sjulian */ 14811820Sjulian if (rt->rt_metric == (HOPCNT_INFINITY-1)) 14911820Sjulian return; 15011820Sjulian n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : 15111820Sjulian min(rt->rt_metric+1, HOPCNT_INFINITY)); 15211820Sjulian n->rip_ticks = htons(rt->rt_ticks+1); 15311820Sjulian 15411820Sjulian /* 15511820Sjulian * We use split horizon with a twist. If the requested 15611820Sjulian * net is the directly connected net we supply an 15711820Sjulian * answer. This is so that the host can learn about 15811820Sjulian * the routers on its net. 15911820Sjulian */ 16011820Sjulian { 16111820Sjulian register struct rt_entry *trt = rt; 16211820Sjulian 16311820Sjulian while (trt) { 16411820Sjulian if ((trt->rt_ifp == ifp) && 16511820Sjulian !ipx_neteqnn(n->rip_dst, 16611820Sjulian satoipx_addr(ifp->int_addr).x_net)) 16711820Sjulian return; 16811820Sjulian trt = trt->rt_clone; 16911820Sjulian } 17011820Sjulian n++; 17111820Sjulian newsize += sizeof (struct netinfo); 17211820Sjulian } 17311820Sjulian } 17411820Sjulian if (newsize > 0) { 17511820Sjulian msg->rip_cmd = htons(RIPCMD_RESPONSE); 17611820Sjulian newsize += sizeof (u_short); 17711820Sjulian /* should check for if with dstaddr(from) first */ 17811820Sjulian (*afp->af_output)(ripsock, 0, from, newsize); 17911820Sjulian TRACE_OUTPUT(ifp, from, newsize); 18011820Sjulian if (ftrace) { 18111820Sjulian /* XXX This should not happen anymore. */ 18211820Sjulian if(ifp == 0) 18311820Sjulian fprintf(ftrace, "--- ifp = 0\n"); 18411820Sjulian else 18511820Sjulian fprintf(ftrace, 18611820Sjulian "request arrived on interface %s\n", 18711820Sjulian ifp->int_name); 18811820Sjulian } 18911820Sjulian } 19011820Sjulian return; 19111820Sjulian 19211820Sjulian case RIPCMD_RESPONSE: 19311820Sjulian /* verify message came from a router */ 19411820Sjulian if ((*afp->af_portmatch)(from) == 0) 19511820Sjulian return; 19611820Sjulian (*afp->af_canon)(from); 19711820Sjulian /* are we talking to ourselves? */ 19811820Sjulian if ((ifp = if_ifwithaddr(from)) != 0) { 19911820Sjulian rt = rtfind(from); 20011820Sjulian if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 20111820Sjulian addrouteforif(ifp); 20211820Sjulian else 20311820Sjulian rt->rt_timer = 0; 20411820Sjulian return; 20511820Sjulian } 20611820Sjulian /* Update timer for interface on which the packet arrived. 20711820Sjulian * If from other end of a point-to-point link that isn't 20811820Sjulian * in the routing tables, (re-)add the route. 20911820Sjulian */ 21011820Sjulian if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) { 21111820Sjulian if(ftrace) fprintf(ftrace, "Got route\n"); 21211820Sjulian rt->rt_timer = 0; 21311820Sjulian } else if ((ifp = if_ifwithdstaddr(from)) != 0) { 21411820Sjulian if(ftrace) fprintf(ftrace, "Got partner\n"); 21511820Sjulian addrouteforif(ifp); 21611820Sjulian } 21711820Sjulian for (; size > 0; size -= sizeof (struct netinfo), n++) { 21811820Sjulian struct sockaddr *sa; 21911820Sjulian if (size < sizeof (struct netinfo)) 22011820Sjulian break; 22111820Sjulian if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY) 22211820Sjulian continue; 22311820Sjulian rt = rtfind(sa = ipx_nettosa(n->rip_dst)); 22411820Sjulian if (rt == 0) { 22511820Sjulian rtadd(sa, from, ntohs(n->rip_metric), 22611820Sjulian ntohs(n->rip_ticks), 0); 22711820Sjulian continue; 22811820Sjulian } 22911820Sjulian 23011820Sjulian /* 23111820Sjulian * A clone is a different route to the same net 23211820Sjulian * with exactly the same cost (ticks and metric). 23311820Sjulian * They must all be recorded because those interfaces 23411820Sjulian * must be handled in the same way as the first route 23511820Sjulian * to that net. ie When using the split horizon 23611820Sjulian * algorithm we must look at these interfaces also. 23711820Sjulian * 23811820Sjulian * Update if from gateway and different, 23911820Sjulian * from anywhere and less ticks or 24011820Sjulian * if same ticks and shorter, 24111820Sjulian * or getting stale and equivalent. 24211820Sjulian * 24311820Sjulian * XXX I don't think this is quite right. 24411820Sjulian */ 24511820Sjulian if (!equal(from, &rt->rt_router) && 24611820Sjulian ntohs(n->rip_ticks == rt->rt_ticks) && 24711820Sjulian ntohs(n->rip_metric == rt->rt_metric)) { 24811820Sjulian register struct rt_entry *trt = rt->rt_clone; 24911820Sjulian 25011820Sjulian while (trt) { 25111820Sjulian if (equal(from, &trt->rt_router)) { 25211820Sjulian trt->rt_timer = 0; 25311820Sjulian break; 25411820Sjulian } 25511820Sjulian } 25611820Sjulian if (trt == NULL) { 25711820Sjulian rtadd_clone(rt, sa, from, 25811820Sjulian ntohs(n->rip_metric), 25911820Sjulian ntohs(n->rip_ticks), 0); 26011820Sjulian } 26111820Sjulian continue; 26211820Sjulian } 26311820Sjulian if ((equal(from, &rt->rt_router) && 26411820Sjulian ((ntohs(n->rip_ticks) != rt->rt_ticks) || 26511820Sjulian (ntohs(n->rip_metric) != rt->rt_metric))) || 26611820Sjulian (ntohs(n->rip_ticks) < rt->rt_ticks) || 26711820Sjulian ((ntohs(n->rip_ticks) == rt->rt_ticks) && 26811820Sjulian (ntohs(n->rip_metric) < rt->rt_metric)) || 26911820Sjulian (rt->rt_timer > (EXPIRE_TIME*2/3) && 27011820Sjulian rt->rt_metric == ntohs(n->rip_metric))) { 27111820Sjulian rtchange(rt, from, ntohs(n->rip_metric), 27211820Sjulian ntohs(n->rip_ticks)); 27311820Sjulian rt->rt_timer = 0; 27411820Sjulian } else if (equal(from, &rt->rt_router) && 27511820Sjulian (ntohs(n->rip_ticks) == rt->rt_ticks) && 27611820Sjulian (ntohs(n->rip_metric) == rt->rt_metric)) { 27711820Sjulian rt->rt_timer = 0; 27811820Sjulian } 27911820Sjulian } 28011820Sjulian return; 28111820Sjulian } 28211820Sjulian} 283