1*24328Ssklower /* 2*24328Ssklower * Copyright (c) 1985 Regents of the University of California. 3*24328Ssklower * All rights reserved. The Berkeley software License Agreement 4*24328Ssklower * specifies the terms and conditions for redistribution. 5*24328Ssklower * 6*24328Ssklower * Includes material written at Cornell University by Bill Nesheim, 7*24328Ssklower * by permission of the author. 8*24328Ssklower */ 9*24328Ssklower 10*24328Ssklower 1124307Ssklower #ifndef lint 12*24328Ssklower static char sccsid[] = "@(#)input.c 5.3 (Berkeley) 08/16/85"; 13*24328Ssklower #endif not lint 1424307Ssklower 1524307Ssklower /* 1624307Ssklower * XNS Routing Table Management Daemon 1724307Ssklower */ 1824307Ssklower #include "defs.h" 1924307Ssklower 2024307Ssklower struct sockaddr * 2124307Ssklower xns_nettosa(net) 2224307Ssklower u_short *net; 2324307Ssklower { 2424317Ssklower static struct sockaddr_ns sxn; 2524317Ssklower extern char ether_broadcast_addr[6]; 2624307Ssklower 2724317Ssklower bzero(&sxn, sizeof (struct sockaddr_ns)); 2824317Ssklower sxn.sns_family = AF_NS; 2924317Ssklower xnnet(sxn.sns_addr.x_net) = xnnet(net[0]); 3024317Ssklower sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr; 3124307Ssklower return( (struct sockaddr *)&sxn); 3224307Ssklower 3324307Ssklower } 3424307Ssklower 3524307Ssklower /* 3624307Ssklower * Process a newly received packet. 3724307Ssklower */ 3824307Ssklower rip_input(from, size) 3924307Ssklower struct sockaddr *from; 4024307Ssklower int size; 4124307Ssklower { 4224307Ssklower struct rt_entry *rt; 4324307Ssklower struct netinfo *n; 4424307Ssklower struct interface *ifp; 4524307Ssklower int newsize; 4624307Ssklower struct afswitch *afp; 4724307Ssklower 4824307Ssklower 4924317Ssklower ifp = 0; 5024307Ssklower TRACE_INPUT(ifp, from, size); 5124307Ssklower if (from->sa_family >= AF_MAX) 5224307Ssklower return; 5324307Ssklower afp = &afswitch[from->sa_family]; 5424307Ssklower 5524307Ssklower size -= sizeof (u_short) /* command */; 5624307Ssklower n = msg->rip_nets; 5724307Ssklower 5824307Ssklower switch (ntohs(msg->rip_cmd)) { 5924307Ssklower 6024307Ssklower case RIPCMD_REQUEST: 6124307Ssklower newsize = 0; 6224307Ssklower while (size > 0) { 6324307Ssklower if (size < sizeof (struct netinfo)) 6424307Ssklower break; 6524307Ssklower size -= sizeof (struct netinfo); 6624307Ssklower 6724307Ssklower /* 6824307Ssklower * A single entry with rip_dst == DSTNETS_ALL and 6924307Ssklower * metric ``infinity'' means ``all routes''. 7024307Ssklower */ 7124317Ssklower if (ntohl(xnnet(n->rip_dst[0])) == DSTNETS_ALL && 7224317Ssklower ntohs(n->rip_metric) == HOPCNT_INFINITY && 7324317Ssklower size == 0) { 7424317Ssklower ifp = if_ifwithnet(from); 7524317Ssklower supply(from, 0, ifp); 7624307Ssklower return; 7724307Ssklower } 7824307Ssklower /* 7924307Ssklower * request for specific nets 8024307Ssklower */ 8124307Ssklower rt = rtlookup(xns_nettosa(n->rip_dst)); 82*24328Ssklower if (tracepackets > 1) { 83*24328Ssklower fprintf(ftrace, 84*24328Ssklower "specific request for %d", 85*24328Ssklower ntohl(xnnet(n->rip_dst[0]))); 86*24328Ssklower fprintf(ftrace, 87*24328Ssklower "yields route %x", 88*24328Ssklower rt); 89*24328Ssklower } 9024307Ssklower n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : 9124307Ssklower min(rt->rt_metric+1, HOPCNT_INFINITY)); 9224307Ssklower n++, newsize += sizeof (struct netinfo); 9324307Ssklower } 9424307Ssklower if (newsize > 0) { 9524307Ssklower msg->rip_cmd = htons(RIPCMD_RESPONSE); 9624307Ssklower newsize += sizeof (u_short); 9724307Ssklower /* should check for if with dstaddr(from) first */ 98*24328Ssklower (ifp = if_ifwithnet(from)); 99*24328Ssklower (*afp->af_output)(0, from, newsize); 100*24328Ssklower if (tracepackets > 1) { 101*24328Ssklower fprintf(ftrace, 102*24328Ssklower ", request arriving on interface %x\n", 103*24328Ssklower ifp); 104*24328Ssklower } 10524307Ssklower } 10624307Ssklower return; 10724307Ssklower 10824307Ssklower case RIPCMD_RESPONSE: 10924307Ssklower /* verify message came from a router */ 11024307Ssklower if ((*afp->af_portmatch)(from) == 0) 11124307Ssklower return; 11224317Ssklower (*afp->af_canon)(from); 11324317Ssklower /* are we talking to ourselves? */ 11424317Ssklower if (ifp = if_ifwithaddr(from)) { 11524317Ssklower rt = rtfind(from); 11624317Ssklower if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 11724317Ssklower addrouteforif(ifp); 11824317Ssklower else 11924317Ssklower rt->rt_timer = 0; 12024317Ssklower return; 12124317Ssklower } 122*24328Ssklower /* Update timer for interface on which the packet arrived. 123*24328Ssklower * If from other end of a point-to-point link that isn't 124*24328Ssklower * in the routing tables, (re-)add the route. 125*24328Ssklower */ 126*24328Ssklower if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) { 127*24328Ssklower if(tracepackets > 1) fprintf(ftrace, "Got route\n"); 12824307Ssklower rt->rt_timer = 0; 129*24328Ssklower } else if (ifp = if_ifwithdstaddr(from)) { 130*24328Ssklower if(tracepackets > 1) fprintf(ftrace, "Got partner\n"); 131*24328Ssklower addrouteforif(ifp); 132*24328Ssklower } 13324307Ssklower for (; size > 0; size -= sizeof (struct netinfo), n++) { 134*24328Ssklower struct sockaddr *sa; 13524307Ssklower if (size < sizeof (struct netinfo)) 13624307Ssklower break; 13724307Ssklower if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY) 13824307Ssklower continue; 139*24328Ssklower rt = rtfind(sa = xns_nettosa(n->rip_dst)); 14024307Ssklower if (rt == 0) { 141*24328Ssklower rtadd(sa, from, ntohs(n->rip_metric), 0); 14224307Ssklower continue; 14324307Ssklower } 14424307Ssklower 14524307Ssklower /* 14624307Ssklower * Update if from gateway and different, 14724307Ssklower * from anywhere and shorter, or getting stale and equivalent. 14824307Ssklower */ 14924307Ssklower if ((equal(from, &rt->rt_router) && 15024307Ssklower ntohs(n->rip_metric) != rt->rt_metric ) || 15124307Ssklower (unsigned) ntohs(n->rip_metric) < rt->rt_metric || 15224307Ssklower (rt->rt_timer > (EXPIRE_TIME/2) && 15324307Ssklower rt->rt_metric == ntohs(n->rip_metric))) { 15424307Ssklower rtchange(rt, from, ntohs(n->rip_metric)); 15524307Ssklower rt->rt_timer = 0; 15624307Ssklower } 15724307Ssklower } 15824307Ssklower return; 15924307Ssklower } 16024307Ssklower } 161