19016Ssam #ifndef lint 2*21836Skarels static char sccsid[] = "@(#)input.c 4.12 (Berkeley) 06/03/85"; 39016Ssam #endif 49016Ssam 59016Ssam /* 69016Ssam * Routing Table Management Daemon 79016Ssam */ 810245Ssam #include "defs.h" 99016Ssam 109016Ssam /* 119016Ssam * Process a newly received packet. 129016Ssam */ 139016Ssam rip_input(from, size) 149016Ssam struct sockaddr *from; 159016Ssam int size; 169016Ssam { 17*21836Skarels register struct rt_entry *rt; 18*21836Skarels register struct netinfo *n; 19*21836Skarels register struct interface *ifp; 20*21836Skarels struct interface *if_ifwithdstaddr(); 219016Ssam int newsize; 22*21836Skarels register struct afswitch *afp; 239016Ssam 249016Ssam ifp = 0; 259016Ssam TRACE_INPUT(ifp, from, size); 269016Ssam if (from->sa_family >= AF_MAX) 279016Ssam return; 289016Ssam afp = &afswitch[from->sa_family]; 299016Ssam switch (msg->rip_cmd) { 309016Ssam 319016Ssam case RIPCMD_REQUEST: 329016Ssam newsize = 0; 339016Ssam size -= 4 * sizeof (char); 349016Ssam n = msg->rip_nets; 359016Ssam while (size > 0) { 369016Ssam if (size < sizeof (struct netinfo)) 379016Ssam break; 389016Ssam size -= sizeof (struct netinfo); 399016Ssam 4012726Ssam if (msg->rip_vers > 0) { 4112726Ssam n->rip_dst.sa_family = 4212726Ssam ntohs(n->rip_dst.sa_family); 4312726Ssam n->rip_metric = ntohl(n->rip_metric); 4412726Ssam } 459016Ssam /* 469016Ssam * A single entry with sa_family == AF_UNSPEC and 479016Ssam * metric ``infinity'' means ``all routes''. 489016Ssam */ 499016Ssam if (n->rip_dst.sa_family == AF_UNSPEC && 509016Ssam n->rip_metric == HOPCNT_INFINITY && size == 0) { 519016Ssam supply(from, 0, ifp); 529016Ssam return; 539016Ssam } 549016Ssam rt = rtlookup(&n->rip_dst); 559016Ssam n->rip_metric = rt == 0 ? HOPCNT_INFINITY : 569016Ssam min(rt->rt_metric+1, HOPCNT_INFINITY); 5712726Ssam if (msg->rip_vers > 0) { 5812726Ssam n->rip_dst.sa_family = 5912726Ssam htons(n->rip_dst.sa_family); 6012726Ssam n->rip_metric = htonl(n->rip_metric); 6112726Ssam } 629016Ssam n++, newsize += sizeof (struct netinfo); 639016Ssam } 649016Ssam if (newsize > 0) { 659016Ssam msg->rip_cmd = RIPCMD_RESPONSE; 669016Ssam newsize += sizeof (int); 6712156Ssam (*afp->af_output)(s, 0, from, newsize); 689016Ssam } 699016Ssam return; 709016Ssam 719016Ssam case RIPCMD_TRACEON: 729016Ssam case RIPCMD_TRACEOFF: 7316314Skarels /* verify message came from a privileged port */ 749016Ssam if ((*afp->af_portcheck)(from) == 0) 759016Ssam return; 769016Ssam packet[size] = '\0'; 779016Ssam if (msg->rip_cmd == RIPCMD_TRACEON) 789016Ssam traceon(msg->rip_tracefile); 799016Ssam else 809016Ssam traceoff(); 819016Ssam return; 829016Ssam 839016Ssam case RIPCMD_RESPONSE: 849016Ssam /* verify message came from a router */ 859016Ssam if ((*afp->af_portmatch)(from) == 0) 869016Ssam return; 879016Ssam (*afp->af_canon)(from); 889016Ssam /* are we talking to ourselves? */ 899016Ssam ifp = if_ifwithaddr(from); 909016Ssam if (ifp) { 919016Ssam rt = rtfind(from); 9216314Skarels if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 939016Ssam addrouteforif(ifp); 949016Ssam else 959016Ssam rt->rt_timer = 0; 969016Ssam return; 979016Ssam } 9817573Skarels /* 9917573Skarels * Update timer for interface on which the packet arrived. 10017573Skarels * If from other end of a point-to-point link that isn't 10117573Skarels * in the routing tables, (re-)add the route. 10217573Skarels */ 10316314Skarels if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) 10416314Skarels rt->rt_timer = 0; 10517573Skarels else if (ifp = if_ifwithdstaddr(from)) 10617573Skarels addrouteforif(ifp); 1079016Ssam size -= 4 * sizeof (char); 1089016Ssam n = msg->rip_nets; 1099016Ssam for (; size > 0; size -= sizeof (struct netinfo), n++) { 1109016Ssam if (size < sizeof (struct netinfo)) 1119016Ssam break; 11212726Ssam if (msg->rip_vers > 0) { 11312726Ssam n->rip_dst.sa_family = 11412726Ssam ntohs(n->rip_dst.sa_family); 11512726Ssam n->rip_metric = ntohl(n->rip_metric); 11612726Ssam } 117*21836Skarels if ((unsigned) n->rip_metric > HOPCNT_INFINITY) 1189016Ssam continue; 11916753Skarels if (n->rip_dst.sa_family >= AF_MAX) 12016753Skarels continue; 12116753Skarels afp = &afswitch[n->rip_dst.sa_family]; 12216128Skarels if (((*afp->af_checkhost)(&n->rip_dst)) == 0) 12316128Skarels continue; 1249016Ssam rt = rtlookup(&n->rip_dst); 1259016Ssam if (rt == 0) { 126*21836Skarels if (n->rip_metric < HOPCNT_INFINITY) 127*21836Skarels rtadd(&n->rip_dst, from, n->rip_metric, 0); 1289016Ssam continue; 1299016Ssam } 1309016Ssam 1319016Ssam /* 13216323Skarels * Update if from gateway and different, 13316323Skarels * shorter, or getting stale and equivalent. 1349016Ssam */ 13518112Skarels if (equal(from, &rt->rt_router)) { 136*21836Skarels if (n->rip_metric == HOPCNT_INFINITY) { 137*21836Skarels rtdelete(rt); 138*21836Skarels continue; 139*21836Skarels } 14018112Skarels if (n->rip_metric != rt->rt_metric) 14118112Skarels rtchange(rt, from, n->rip_metric); 14218112Skarels rt->rt_timer = 0; 14318112Skarels } else if ((unsigned) (n->rip_metric) < rt->rt_metric || 1449016Ssam (rt->rt_timer > (EXPIRE_TIME/2) && 1459016Ssam rt->rt_metric == n->rip_metric)) { 1469016Ssam rtchange(rt, from, n->rip_metric); 1479016Ssam rt->rt_timer = 0; 1489016Ssam } 1499016Ssam } 1509016Ssam return; 1519016Ssam } 1529016Ssam } 153