124307Ssklower #ifndef lint 224307Ssklower static char rcsid[] = "$Header$"; 324307Ssklower #endif 424307Ssklower 524307Ssklower /* 624307Ssklower * XNS Routing Table Management Daemon 724307Ssklower */ 824307Ssklower #include "defs.h" 924307Ssklower 1024307Ssklower struct sockaddr * 1124307Ssklower xns_nettosa(net) 1224307Ssklower u_short *net; 1324307Ssklower { 14*24317Ssklower static struct sockaddr_ns sxn; 15*24317Ssklower extern char ether_broadcast_addr[6]; 1624307Ssklower 17*24317Ssklower bzero(&sxn, sizeof (struct sockaddr_ns)); 18*24317Ssklower sxn.sns_family = AF_NS; 19*24317Ssklower xnnet(sxn.sns_addr.x_net) = xnnet(net[0]); 20*24317Ssklower sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr; 2124307Ssklower return( (struct sockaddr *)&sxn); 2224307Ssklower 2324307Ssklower } 2424307Ssklower 2524307Ssklower /* 2624307Ssklower * Process a newly received packet. 2724307Ssklower */ 2824307Ssklower rip_input(from, size) 2924307Ssklower struct sockaddr *from; 3024307Ssklower int size; 3124307Ssklower { 3224307Ssklower struct rt_entry *rt; 3324307Ssklower struct netinfo *n; 3424307Ssklower struct interface *ifp; 3524307Ssklower int newsize; 3624307Ssklower struct afswitch *afp; 3724307Ssklower 3824307Ssklower 39*24317Ssklower ifp = 0; 4024307Ssklower TRACE_INPUT(ifp, from, size); 4124307Ssklower if (from->sa_family >= AF_MAX) 4224307Ssklower return; 4324307Ssklower afp = &afswitch[from->sa_family]; 4424307Ssklower 4524307Ssklower size -= sizeof (u_short) /* command */; 4624307Ssklower n = msg->rip_nets; 4724307Ssklower 4824307Ssklower switch (ntohs(msg->rip_cmd)) { 4924307Ssklower 5024307Ssklower case RIPCMD_REQUEST: 5124307Ssklower /* Be quiet if we don't have anything interesting to talk about */ 5224307Ssklower if (!supplier) return; 5324307Ssklower newsize = 0; 5424307Ssklower while (size > 0) { 5524307Ssklower if (size < sizeof (struct netinfo)) 5624307Ssklower break; 5724307Ssklower size -= sizeof (struct netinfo); 5824307Ssklower 5924307Ssklower /* 6024307Ssklower * A single entry with rip_dst == DSTNETS_ALL and 6124307Ssklower * metric ``infinity'' means ``all routes''. 6224307Ssklower */ 63*24317Ssklower if (ntohl(xnnet(n->rip_dst[0])) == DSTNETS_ALL && 64*24317Ssklower ntohs(n->rip_metric) == HOPCNT_INFINITY && 65*24317Ssklower size == 0) { 66*24317Ssklower ifp = if_ifwithnet(from); 67*24317Ssklower supply(from, 0, ifp); 6824307Ssklower return; 6924307Ssklower } 7024307Ssklower /* 7124307Ssklower * request for specific nets 7224307Ssklower */ 7324307Ssklower rt = rtlookup(xns_nettosa(n->rip_dst)); 7424307Ssklower n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : 7524307Ssklower min(rt->rt_metric+1, HOPCNT_INFINITY)); 7624307Ssklower n++, newsize += sizeof (struct netinfo); 7724307Ssklower } 7824307Ssklower if (newsize > 0) { 7924307Ssklower msg->rip_cmd = htons(RIPCMD_RESPONSE); 8024307Ssklower newsize += sizeof (u_short); 8124307Ssklower /* should check for if with dstaddr(from) first */ 8224307Ssklower if(ifp = if_ifwithnet(from)) 83*24317Ssklower (*afp->af_output)(0, from, newsize); 8424307Ssklower } 8524307Ssklower return; 8624307Ssklower 8724307Ssklower case RIPCMD_RESPONSE: 8824307Ssklower /* verify message came from a router */ 8924307Ssklower if ((*afp->af_portmatch)(from) == 0) 9024307Ssklower return; 91*24317Ssklower (*afp->af_canon)(from); 92*24317Ssklower /* are we talking to ourselves? */ 93*24317Ssklower if (ifp = if_ifwithaddr(from)) { 94*24317Ssklower rt = rtfind(from); 95*24317Ssklower if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 96*24317Ssklower addrouteforif(ifp); 97*24317Ssklower else 98*24317Ssklower rt->rt_timer = 0; 99*24317Ssklower return; 100*24317Ssklower } 10124307Ssklower /* update timer for interface on which the packet arrived */ 10224307Ssklower if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) 10324307Ssklower rt->rt_timer = 0; 10424307Ssklower for (; size > 0; size -= sizeof (struct netinfo), n++) { 10524307Ssklower if (size < sizeof (struct netinfo)) 10624307Ssklower break; 10724307Ssklower if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY) 10824307Ssklower continue; 109*24317Ssklower rt = rtfind(xns_nettosa(n->rip_dst)); 11024307Ssklower if (rt == 0) { 11124307Ssklower rtadd(xns_nettosa(n->rip_dst), from, ntohs(n->rip_metric), 0); 11224307Ssklower continue; 11324307Ssklower } 11424307Ssklower 11524307Ssklower /* 11624307Ssklower * Update if from gateway and different, 11724307Ssklower * from anywhere and shorter, or getting stale and equivalent. 11824307Ssklower */ 11924307Ssklower if ((equal(from, &rt->rt_router) && 12024307Ssklower ntohs(n->rip_metric) != rt->rt_metric ) || 12124307Ssklower (unsigned) ntohs(n->rip_metric) < rt->rt_metric || 12224307Ssklower (rt->rt_timer > (EXPIRE_TIME/2) && 12324307Ssklower rt->rt_metric == ntohs(n->rip_metric))) { 12424307Ssklower rtchange(rt, from, ntohs(n->rip_metric)); 12524307Ssklower rt->rt_timer = 0; 12624307Ssklower } 12724307Ssklower } 12824307Ssklower return; 12924307Ssklower } 13024307Ssklower } 131