124328Ssklower /* 2*35551Sbostic * Copyright (c) 1985 The Regents of the University of California. 3*35551Sbostic * All rights reserved. 424328Ssklower * 5*35551Sbostic * This file includes significant work done at Cornell University by 6*35551Sbostic * Bill Nesheim. That work included by permission. 7*35551Sbostic * 8*35551Sbostic * Redistribution and use in source and binary forms are permitted 9*35551Sbostic * provided that the above copyright notice and this paragraph are 10*35551Sbostic * duplicated in all such forms and that any documentation, 11*35551Sbostic * advertising materials, and other materials related to such 12*35551Sbostic * distribution and use acknowledge that the software was developed 13*35551Sbostic * by the University of California, Berkeley. The name of the 14*35551Sbostic * University may not be used to endorse or promote products derived 15*35551Sbostic * from this software without specific prior written permission. 16*35551Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*35551Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*35551Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1924328Ssklower */ 2024328Ssklower 2124307Ssklower #ifndef lint 22*35551Sbostic static char sccsid[] = "@(#)input.c 5.7 (Berkeley) 09/19/88"; 23*35551Sbostic #endif /* not lint */ 2424307Ssklower 2524307Ssklower /* 2624307Ssklower * XNS Routing Table Management Daemon 2724307Ssklower */ 2824307Ssklower #include "defs.h" 2924307Ssklower 3024307Ssklower struct sockaddr * 3124307Ssklower xns_nettosa(net) 3226170Ssklower union ns_net net; 3324307Ssklower { 3424317Ssklower static struct sockaddr_ns sxn; 3524317Ssklower extern char ether_broadcast_addr[6]; 3624307Ssklower 3724317Ssklower bzero(&sxn, sizeof (struct sockaddr_ns)); 3824317Ssklower sxn.sns_family = AF_NS; 3926170Ssklower sxn.sns_addr.x_net = net; 4024317Ssklower sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr; 4124307Ssklower return( (struct sockaddr *)&sxn); 4224307Ssklower 4324307Ssklower } 4424307Ssklower 4524307Ssklower /* 4624307Ssklower * Process a newly received packet. 4724307Ssklower */ 4824307Ssklower rip_input(from, size) 4924307Ssklower struct sockaddr *from; 5024307Ssklower int size; 5124307Ssklower { 5224307Ssklower struct rt_entry *rt; 5324307Ssklower struct netinfo *n; 5424307Ssklower struct interface *ifp; 5524307Ssklower int newsize; 5624307Ssklower struct afswitch *afp; 5724307Ssklower 5824307Ssklower 5924317Ssklower ifp = 0; 6024307Ssklower TRACE_INPUT(ifp, from, size); 6124307Ssklower if (from->sa_family >= AF_MAX) 6224307Ssklower return; 6324307Ssklower afp = &afswitch[from->sa_family]; 6424307Ssklower 6524307Ssklower size -= sizeof (u_short) /* command */; 6624307Ssklower n = msg->rip_nets; 6724307Ssklower 6824307Ssklower switch (ntohs(msg->rip_cmd)) { 6924307Ssklower 7024307Ssklower case RIPCMD_REQUEST: 7124307Ssklower newsize = 0; 7224307Ssklower while (size > 0) { 7324307Ssklower if (size < sizeof (struct netinfo)) 7424307Ssklower break; 7524307Ssklower size -= sizeof (struct netinfo); 7624307Ssklower 7724307Ssklower /* 7824307Ssklower * A single entry with rip_dst == DSTNETS_ALL and 7924307Ssklower * metric ``infinity'' means ``all routes''. 8024307Ssklower */ 8126170Ssklower if (ns_neteqnn(n->rip_dst, ns_anynet) && 8224317Ssklower ntohs(n->rip_metric) == HOPCNT_INFINITY && 8324317Ssklower size == 0) { 8424317Ssklower ifp = if_ifwithnet(from); 8524317Ssklower supply(from, 0, ifp); 8624307Ssklower return; 8724307Ssklower } 8824307Ssklower /* 8924307Ssklower * request for specific nets 9024307Ssklower */ 9124307Ssklower rt = rtlookup(xns_nettosa(n->rip_dst)); 9224875Ssklower if (ftrace) { 9324328Ssklower fprintf(ftrace, 9426170Ssklower "specific request for %s", 9526170Ssklower xns_nettoa(n->rip_dst)); 9624328Ssklower fprintf(ftrace, 9726170Ssklower " yields route %x\n", 9824328Ssklower rt); 9924328Ssklower } 10024307Ssklower n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : 10124307Ssklower min(rt->rt_metric+1, HOPCNT_INFINITY)); 10226170Ssklower n++; 10326170Ssklower newsize += sizeof (struct netinfo); 10424307Ssklower } 10524307Ssklower if (newsize > 0) { 10624307Ssklower msg->rip_cmd = htons(RIPCMD_RESPONSE); 10724307Ssklower newsize += sizeof (u_short); 10824307Ssklower /* should check for if with dstaddr(from) first */ 10924875Ssklower (*afp->af_output)(0, from, newsize); 11026170Ssklower ifp = if_ifwithnet(from); 11126170Ssklower TRACE_OUTPUT(ifp, from, newsize); 11224875Ssklower if (ftrace) { 11324328Ssklower fprintf(ftrace, 11426170Ssklower "request arrived on interface %s\n", 11526170Ssklower ifp->int_name); 11624328Ssklower } 11724307Ssklower } 11824307Ssklower return; 11924307Ssklower 12024307Ssklower case RIPCMD_RESPONSE: 12124307Ssklower /* verify message came from a router */ 12224307Ssklower if ((*afp->af_portmatch)(from) == 0) 12324307Ssklower return; 12424317Ssklower (*afp->af_canon)(from); 12524317Ssklower /* are we talking to ourselves? */ 12624317Ssklower if (ifp = if_ifwithaddr(from)) { 12724317Ssklower rt = rtfind(from); 12824317Ssklower if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 12924317Ssklower addrouteforif(ifp); 13024317Ssklower else 13124317Ssklower rt->rt_timer = 0; 13224317Ssklower return; 13324317Ssklower } 13424328Ssklower /* Update timer for interface on which the packet arrived. 13524328Ssklower * If from other end of a point-to-point link that isn't 13624328Ssklower * in the routing tables, (re-)add the route. 13724328Ssklower */ 13824328Ssklower if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) { 13924875Ssklower if(ftrace) fprintf(ftrace, "Got route\n"); 14024307Ssklower rt->rt_timer = 0; 14124328Ssklower } else if (ifp = if_ifwithdstaddr(from)) { 14224875Ssklower if(ftrace) fprintf(ftrace, "Got partner\n"); 14324328Ssklower addrouteforif(ifp); 14424328Ssklower } 14524307Ssklower for (; size > 0; size -= sizeof (struct netinfo), n++) { 14624328Ssklower struct sockaddr *sa; 14724307Ssklower if (size < sizeof (struct netinfo)) 14824307Ssklower break; 14925507Ssklower if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY) 15024307Ssklower continue; 15124328Ssklower rt = rtfind(sa = xns_nettosa(n->rip_dst)); 15224307Ssklower if (rt == 0) { 15324328Ssklower rtadd(sa, from, ntohs(n->rip_metric), 0); 15424307Ssklower continue; 15524307Ssklower } 15624307Ssklower 15724307Ssklower /* 15824307Ssklower * Update if from gateway and different, 15924307Ssklower * from anywhere and shorter, or getting stale and equivalent. 16024307Ssklower */ 16124307Ssklower if ((equal(from, &rt->rt_router) && 16224307Ssklower ntohs(n->rip_metric) != rt->rt_metric ) || 16324307Ssklower (unsigned) ntohs(n->rip_metric) < rt->rt_metric || 16424307Ssklower (rt->rt_timer > (EXPIRE_TIME/2) && 16524307Ssklower rt->rt_metric == ntohs(n->rip_metric))) { 16624307Ssklower rtchange(rt, from, ntohs(n->rip_metric)); 16724307Ssklower rt->rt_timer = 0; 16824307Ssklower } 16924307Ssklower } 17024307Ssklower return; 17124307Ssklower } 17224307Ssklower } 173