1 #ifndef lint 2 static char sccsid[] = "@(#)input.c 4.11 (Berkeley) 02/25/85"; 3 #endif 4 5 /* 6 * Routing Table Management Daemon 7 */ 8 #include "defs.h" 9 10 /* 11 * Process a newly received packet. 12 */ 13 rip_input(from, size) 14 struct sockaddr *from; 15 int size; 16 { 17 struct rt_entry *rt; 18 struct netinfo *n; 19 struct interface *ifp, *if_ifwithdstaddr(); 20 int newsize; 21 struct afswitch *afp; 22 23 ifp = 0; 24 TRACE_INPUT(ifp, from, size); 25 if (from->sa_family >= AF_MAX) 26 return; 27 afp = &afswitch[from->sa_family]; 28 switch (msg->rip_cmd) { 29 30 case RIPCMD_REQUEST: 31 newsize = 0; 32 size -= 4 * sizeof (char); 33 n = msg->rip_nets; 34 while (size > 0) { 35 if (size < sizeof (struct netinfo)) 36 break; 37 size -= sizeof (struct netinfo); 38 39 if (msg->rip_vers > 0) { 40 n->rip_dst.sa_family = 41 ntohs(n->rip_dst.sa_family); 42 n->rip_metric = ntohl(n->rip_metric); 43 } 44 /* 45 * A single entry with sa_family == AF_UNSPEC and 46 * metric ``infinity'' means ``all routes''. 47 */ 48 if (n->rip_dst.sa_family == AF_UNSPEC && 49 n->rip_metric == HOPCNT_INFINITY && size == 0) { 50 supply(from, 0, ifp); 51 return; 52 } 53 rt = rtlookup(&n->rip_dst); 54 n->rip_metric = rt == 0 ? HOPCNT_INFINITY : 55 min(rt->rt_metric+1, HOPCNT_INFINITY); 56 if (msg->rip_vers > 0) { 57 n->rip_dst.sa_family = 58 htons(n->rip_dst.sa_family); 59 n->rip_metric = htonl(n->rip_metric); 60 } 61 n++, newsize += sizeof (struct netinfo); 62 } 63 if (newsize > 0) { 64 msg->rip_cmd = RIPCMD_RESPONSE; 65 newsize += sizeof (int); 66 (*afp->af_output)(s, 0, from, newsize); 67 } 68 return; 69 70 case RIPCMD_TRACEON: 71 case RIPCMD_TRACEOFF: 72 /* verify message came from a privileged port */ 73 if ((*afp->af_portcheck)(from) == 0) 74 return; 75 packet[size] = '\0'; 76 if (msg->rip_cmd == RIPCMD_TRACEON) 77 traceon(msg->rip_tracefile); 78 else 79 traceoff(); 80 return; 81 82 case RIPCMD_RESPONSE: 83 /* verify message came from a router */ 84 if ((*afp->af_portmatch)(from) == 0) 85 return; 86 (*afp->af_canon)(from); 87 /* are we talking to ourselves? */ 88 ifp = if_ifwithaddr(from); 89 if (ifp) { 90 rt = rtfind(from); 91 if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 92 addrouteforif(ifp); 93 else 94 rt->rt_timer = 0; 95 return; 96 } 97 /* 98 * Update timer for interface on which the packet arrived. 99 * If from other end of a point-to-point link that isn't 100 * in the routing tables, (re-)add the route. 101 */ 102 if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) 103 rt->rt_timer = 0; 104 else if (ifp = if_ifwithdstaddr(from)) 105 addrouteforif(ifp); 106 size -= 4 * sizeof (char); 107 n = msg->rip_nets; 108 for (; size > 0; size -= sizeof (struct netinfo), n++) { 109 if (size < sizeof (struct netinfo)) 110 break; 111 if (msg->rip_vers > 0) { 112 n->rip_dst.sa_family = 113 ntohs(n->rip_dst.sa_family); 114 n->rip_metric = ntohl(n->rip_metric); 115 } 116 if ((unsigned) n->rip_metric >= HOPCNT_INFINITY) 117 continue; 118 if (n->rip_dst.sa_family >= AF_MAX) 119 continue; 120 afp = &afswitch[n->rip_dst.sa_family]; 121 if (((*afp->af_checkhost)(&n->rip_dst)) == 0) 122 continue; 123 rt = rtlookup(&n->rip_dst); 124 if (rt == 0) { 125 rtadd(&n->rip_dst, from, n->rip_metric, 0); 126 continue; 127 } 128 129 /* 130 * Update if from gateway and different, 131 * shorter, or getting stale and equivalent. 132 */ 133 if (equal(from, &rt->rt_router)) { 134 if (n->rip_metric != rt->rt_metric) 135 rtchange(rt, from, n->rip_metric); 136 rt->rt_timer = 0; 137 } else if ((unsigned) (n->rip_metric) < rt->rt_metric || 138 (rt->rt_timer > (EXPIRE_TIME/2) && 139 rt->rt_metric == n->rip_metric)) { 140 rtchange(rt, from, n->rip_metric); 141 rt->rt_timer = 0; 142 } 143 } 144 return; 145 } 146 } 147