1 /* 2 * Copyright (c) 1983, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 06/05/93"; 10 #endif /* not lint */ 11 12 /* 13 * Routing Table Management Daemon 14 */ 15 #include "defs.h" 16 #include <sys/syslog.h> 17 18 /* 19 * Process a newly received packet. 20 */ 21 rip_input(from, rip, size) 22 struct sockaddr *from; 23 register struct rip *rip; 24 int size; 25 { 26 register struct rt_entry *rt; 27 register struct netinfo *n; 28 register struct interface *ifp; 29 struct interface *if_ifwithdstaddr(); 30 int count, changes = 0; 31 register struct afswitch *afp; 32 static struct sockaddr badfrom, badfrom2; 33 34 ifp = 0; 35 TRACE_INPUT(ifp, from, (char *)rip, size); 36 if (from->sa_family >= af_max || 37 (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { 38 syslog(LOG_INFO, 39 "\"from\" address in unsupported address family (%d), cmd %d\n", 40 from->sa_family, rip->rip_cmd); 41 return; 42 } 43 if (rip->rip_vers == 0) { 44 syslog(LOG_ERR, 45 "RIP version 0 packet received from %s! (cmd %d)", 46 (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd); 47 return; 48 } 49 switch (rip->rip_cmd) { 50 51 case RIPCMD_REQUEST: 52 n = rip->rip_nets; 53 count = size - ((char *)n - (char *)rip); 54 if (count < sizeof (struct netinfo)) 55 return; 56 for (; count > 0; n++) { 57 if (count < sizeof (struct netinfo)) 58 break; 59 count -= sizeof (struct netinfo); 60 61 #if BSD < 198810 62 if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 63 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 64 #else 65 #define osa(x) ((struct osockaddr *)(&(x))) 66 n->rip_dst.sa_family = 67 ntohs(osa(n->rip_dst)->sa_family); 68 n->rip_dst.sa_len = sizeof(n->rip_dst); 69 #endif 70 n->rip_metric = ntohl(n->rip_metric); 71 /* 72 * A single entry with sa_family == AF_UNSPEC and 73 * metric ``infinity'' means ``all routes''. 74 * We respond to routers only if we are acting 75 * as a supplier, or to anyone other than a router 76 * (eg, query). 77 */ 78 if (n->rip_dst.sa_family == AF_UNSPEC && 79 n->rip_metric == HOPCNT_INFINITY && count == 0) { 80 if (supplier || (*afp->af_portmatch)(from) == 0) 81 supply(from, 0, 0, 0); 82 return; 83 } 84 if (n->rip_dst.sa_family < af_max && 85 afswitch[n->rip_dst.sa_family].af_hash) 86 rt = rtlookup(&n->rip_dst); 87 else 88 rt = 0; 89 #define min(a, b) (a < b ? a : b) 90 n->rip_metric = rt == 0 ? HOPCNT_INFINITY : 91 min(rt->rt_metric + 1, HOPCNT_INFINITY); 92 #if BSD < 198810 93 if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 94 n->rip_dst.sa_family = htons(n->rip_dst.sa_family); 95 #else 96 osa(n->rip_dst)->sa_family = 97 htons(n->rip_dst.sa_family); 98 #endif 99 n->rip_metric = htonl(n->rip_metric); 100 } 101 rip->rip_cmd = RIPCMD_RESPONSE; 102 bcopy((char *)rip, packet, size); 103 (*afp->af_output)(s, 0, from, size); 104 return; 105 106 case RIPCMD_TRACEON: 107 case RIPCMD_TRACEOFF: 108 /* verify message came from a privileged port */ 109 if ((*afp->af_portcheck)(from) == 0) 110 return; 111 if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & 112 (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || 113 ifp->int_flags & IFF_PASSIVE) { 114 syslog(LOG_ERR, "trace command from unknown router, %s", 115 (*afswitch[from->sa_family].af_format)(from)); 116 return; 117 } 118 ((char *)rip)[size] = '\0'; 119 if (rip->rip_cmd == RIPCMD_TRACEON) 120 traceon(rip->rip_tracefile); 121 else 122 traceoff(); 123 return; 124 125 case RIPCMD_RESPONSE: 126 /* verify message came from a router */ 127 if ((*afp->af_portmatch)(from) == 0) 128 return; 129 (*afp->af_canon)(from); 130 /* are we talking to ourselves? */ 131 ifp = if_ifwithaddr(from); 132 if (ifp) { 133 if (ifp->int_flags & IFF_PASSIVE) { 134 syslog(LOG_ERR, 135 "bogus input (from passive interface, %s)", 136 (*afswitch[from->sa_family].af_format)(from)); 137 return; 138 } 139 rt = rtfind(from); 140 if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && 141 rt->rt_metric >= ifp->int_metric) 142 addrouteforif(ifp); 143 else 144 rt->rt_timer = 0; 145 return; 146 } 147 /* 148 * Update timer for interface on which the packet arrived. 149 * If from other end of a point-to-point link that isn't 150 * in the routing tables, (re-)add the route. 151 */ 152 if ((rt = rtfind(from)) && 153 (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) 154 rt->rt_timer = 0; 155 else if ((ifp = if_ifwithdstaddr(from)) && 156 (rt == 0 || rt->rt_metric >= ifp->int_metric)) 157 addrouteforif(ifp); 158 /* 159 * "Authenticate" router from which message originated. 160 * We accept routing packets from routers directly connected 161 * via broadcast or point-to-point networks, 162 * and from those listed in /etc/gateways. 163 */ 164 if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & 165 (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || 166 ifp->int_flags & IFF_PASSIVE) { 167 if (bcmp((char *)from, (char *)&badfrom, 168 sizeof(badfrom)) != 0) { 169 syslog(LOG_ERR, 170 "packet from unknown router, %s", 171 (*afswitch[from->sa_family].af_format)(from)); 172 badfrom = *from; 173 } 174 return; 175 } 176 size -= 4 * sizeof (char); 177 n = rip->rip_nets; 178 for (; size > 0; size -= sizeof (struct netinfo), n++) { 179 if (size < sizeof (struct netinfo)) 180 break; 181 #if BSD < 198810 182 if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 183 n->rip_dst.sa_family = 184 ntohs(n->rip_dst.sa_family); 185 #else 186 n->rip_dst.sa_family = 187 ntohs(osa(n->rip_dst)->sa_family); 188 n->rip_dst.sa_len = sizeof(n->rip_dst); 189 #endif 190 n->rip_metric = ntohl(n->rip_metric); 191 if (n->rip_dst.sa_family >= af_max || 192 (afp = &afswitch[n->rip_dst.sa_family])->af_hash == 193 (int (*)())0) { 194 syslog(LOG_INFO, 195 "route in unsupported address family (%d), from %s (af %d)\n", 196 n->rip_dst.sa_family, 197 (*afswitch[from->sa_family].af_format)(from), 198 from->sa_family); 199 continue; 200 } 201 if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { 202 syslog(LOG_DEBUG, 203 "bad host in route from %s (af %d)\n", 204 (*afswitch[from->sa_family].af_format)(from), 205 from->sa_family); 206 continue; 207 } 208 if (n->rip_metric == 0 || 209 (unsigned) n->rip_metric > HOPCNT_INFINITY) { 210 if (bcmp((char *)from, (char *)&badfrom2, 211 sizeof(badfrom2)) != 0) { 212 syslog(LOG_ERR, 213 "bad metric (%d) from %s\n", 214 n->rip_metric, 215 (*afswitch[from->sa_family].af_format)(from)); 216 badfrom2 = *from; 217 } 218 continue; 219 } 220 /* 221 * Adjust metric according to incoming interface. 222 */ 223 if ((unsigned) n->rip_metric < HOPCNT_INFINITY) 224 n->rip_metric += ifp->int_metric; 225 if ((unsigned) n->rip_metric > HOPCNT_INFINITY) 226 n->rip_metric = HOPCNT_INFINITY; 227 rt = rtlookup(&n->rip_dst); 228 if (rt == 0 || 229 (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == 230 (RTS_INTERNAL|RTS_INTERFACE)) { 231 /* 232 * If we're hearing a logical network route 233 * back from a peer to which we sent it, 234 * ignore it. 235 */ 236 if (rt && rt->rt_state & RTS_SUBNET && 237 (*afp->af_sendroute)(rt, from)) 238 continue; 239 if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { 240 /* 241 * Look for an equivalent route that 242 * includes this one before adding 243 * this route. 244 */ 245 rt = rtfind(&n->rip_dst); 246 if (rt && equal(from, &rt->rt_router)) 247 continue; 248 rtadd(&n->rip_dst, from, n->rip_metric, 0); 249 changes++; 250 } 251 continue; 252 } 253 254 /* 255 * Update if from gateway and different, 256 * shorter, or equivalent but old route 257 * is getting stale. 258 */ 259 if (equal(from, &rt->rt_router)) { 260 if (n->rip_metric != rt->rt_metric) { 261 rtchange(rt, from, n->rip_metric); 262 changes++; 263 rt->rt_timer = 0; 264 if (rt->rt_metric >= HOPCNT_INFINITY) 265 rt->rt_timer = 266 GARBAGE_TIME - EXPIRE_TIME; 267 } else if (rt->rt_metric < HOPCNT_INFINITY) 268 rt->rt_timer = 0; 269 } else if ((unsigned) n->rip_metric < rt->rt_metric || 270 (rt->rt_metric == n->rip_metric && 271 rt->rt_timer > (EXPIRE_TIME/2) && 272 (unsigned) n->rip_metric < HOPCNT_INFINITY)) { 273 rtchange(rt, from, n->rip_metric); 274 changes++; 275 rt->rt_timer = 0; 276 } 277 } 278 break; 279 } 280 281 /* 282 * If changes have occurred, and if we have not sent a broadcast 283 * recently, send a dynamic update. This update is sent only 284 * on interfaces other than the one on which we received notice 285 * of the change. If we are within MIN_WAITTIME of a full update, 286 * don't bother sending; if we just sent a dynamic update 287 * and set a timer (nextbcast), delay until that time. 288 * If we just sent a full update, delay the dynamic update. 289 * Set a timer for a randomized value to suppress additional 290 * dynamic updates until it expires; if we delayed sending 291 * the current changes, set needupdate. 292 */ 293 if (changes && supplier && 294 now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) { 295 u_long delay; 296 extern long random(); 297 298 if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME && 299 timercmp(&nextbcast, &now, <)) { 300 if (traceactions) 301 fprintf(ftrace, "send dynamic update\n"); 302 toall(supply, RTS_CHANGED, ifp); 303 lastbcast = now; 304 needupdate = 0; 305 nextbcast.tv_sec = 0; 306 } else { 307 needupdate++; 308 if (traceactions) 309 fprintf(ftrace, "delay dynamic update\n"); 310 } 311 #define RANDOMDELAY() (MIN_WAITTIME * 1000000 + \ 312 (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000)) 313 314 if (nextbcast.tv_sec == 0) { 315 delay = RANDOMDELAY(); 316 if (traceactions) 317 fprintf(ftrace, 318 "inhibit dynamic update for %d usec\n", 319 delay); 320 nextbcast.tv_sec = delay / 1000000; 321 nextbcast.tv_usec = delay % 1000000; 322 timevaladd(&nextbcast, &now); 323 /* 324 * If the next possibly dynamic update 325 * is within MIN_WAITTIME of the next full update, 326 * force the delay past the full update, 327 * or we might send a dynamic update just before 328 * the full update. 329 */ 330 if (nextbcast.tv_sec > lastfullupdate.tv_sec + 331 SUPPLY_INTERVAL - MIN_WAITTIME) 332 nextbcast.tv_sec = lastfullupdate.tv_sec + 333 SUPPLY_INTERVAL + 1; 334 } 335 } 336 } 337