19016Ssam #ifndef lint 2*12156Ssam static char sccsid[] = "@(#)input.c 4.3 05/01/83"; 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 { 179016Ssam struct rt_entry *rt; 189016Ssam struct netinfo *n; 199016Ssam struct interface *ifp; 209016Ssam int newsize; 219016Ssam struct afswitch *afp; 229016Ssam 239016Ssam ifp = 0; 249016Ssam TRACE_INPUT(ifp, from, size); 259016Ssam if (from->sa_family >= AF_MAX) 269016Ssam return; 279016Ssam afp = &afswitch[from->sa_family]; 289016Ssam switch (msg->rip_cmd) { 299016Ssam 309016Ssam case RIPCMD_REQUEST: 319016Ssam newsize = 0; 329016Ssam size -= 4 * sizeof (char); 339016Ssam n = msg->rip_nets; 349016Ssam while (size > 0) { 359016Ssam if (size < sizeof (struct netinfo)) 369016Ssam break; 379016Ssam size -= sizeof (struct netinfo); 389016Ssam 399016Ssam /* 409016Ssam * A single entry with sa_family == AF_UNSPEC and 419016Ssam * metric ``infinity'' means ``all routes''. 429016Ssam */ 439016Ssam if (n->rip_dst.sa_family == AF_UNSPEC && 449016Ssam n->rip_metric == HOPCNT_INFINITY && size == 0) { 459016Ssam supply(from, 0, ifp); 469016Ssam return; 479016Ssam } 489016Ssam rt = rtlookup(&n->rip_dst); 499016Ssam n->rip_metric = rt == 0 ? HOPCNT_INFINITY : 509016Ssam min(rt->rt_metric+1, HOPCNT_INFINITY); 519016Ssam n++, newsize += sizeof (struct netinfo); 529016Ssam } 539016Ssam if (newsize > 0) { 549016Ssam msg->rip_cmd = RIPCMD_RESPONSE; 559016Ssam newsize += sizeof (int); 56*12156Ssam (*afp->af_output)(s, 0, from, newsize); 579016Ssam } 589016Ssam return; 599016Ssam 609016Ssam case RIPCMD_TRACEON: 619016Ssam case RIPCMD_TRACEOFF: 629016Ssam /* verify message came from a priviledged port */ 639016Ssam if ((*afp->af_portcheck)(from) == 0) 649016Ssam return; 659016Ssam packet[size] = '\0'; 669016Ssam if (msg->rip_cmd == RIPCMD_TRACEON) 679016Ssam traceon(msg->rip_tracefile); 689016Ssam else 699016Ssam traceoff(); 709016Ssam return; 719016Ssam 729016Ssam case RIPCMD_RESPONSE: 739016Ssam /* verify message came from a router */ 749016Ssam if ((*afp->af_portmatch)(from) == 0) 759016Ssam return; 769016Ssam (*afp->af_canon)(from); 779016Ssam /* are we talking to ourselves? */ 789016Ssam ifp = if_ifwithaddr(from); 799016Ssam if (ifp) { 809016Ssam rt = rtfind(from); 819016Ssam if (rt == 0) 829016Ssam addrouteforif(ifp); 839016Ssam else 849016Ssam rt->rt_timer = 0; 859016Ssam return; 869016Ssam } 879016Ssam size -= 4 * sizeof (char); 889016Ssam n = msg->rip_nets; 899016Ssam for (; size > 0; size -= sizeof (struct netinfo), n++) { 909016Ssam if (size < sizeof (struct netinfo)) 919016Ssam break; 929016Ssam if (n->rip_metric >= HOPCNT_INFINITY) 939016Ssam continue; 949016Ssam rt = rtlookup(&n->rip_dst); 959016Ssam if (rt == 0) { 969016Ssam rtadd(&n->rip_dst, from, n->rip_metric, 0); 979016Ssam continue; 989016Ssam } 999016Ssam 1009016Ssam /* 1019016Ssam * Update if from gateway, shorter, or getting 1029016Ssam * stale and equivalent. 1039016Ssam */ 1049016Ssam if (equal(from, &rt->rt_router) || 1059016Ssam n->rip_metric < rt->rt_metric || 1069016Ssam (rt->rt_timer > (EXPIRE_TIME/2) && 1079016Ssam rt->rt_metric == n->rip_metric)) { 1089016Ssam rtchange(rt, from, n->rip_metric); 1099016Ssam rt->rt_timer = 0; 1109016Ssam } 1119016Ssam } 1129016Ssam return; 1139016Ssam } 1149016Ssam } 115