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.3 (Berkeley) 04/28/95"; 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 memmove(packet, rip, 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 (memcmp(from, &badfrom, sizeof(badfrom)) != 0) { 168 syslog(LOG_ERR, 169 "packet from unknown router, %s", 170 (*afswitch[from->sa_family].af_format)(from)); 171 badfrom = *from; 172 } 173 return; 174 } 175 size -= 4 * sizeof (char); 176 n = rip->rip_nets; 177 for (; size > 0; size -= sizeof (struct netinfo), n++) { 178 if (size < sizeof (struct netinfo)) 179 break; 180 #if BSD < 198810 181 if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 182 n->rip_dst.sa_family = 183 ntohs(n->rip_dst.sa_family); 184 #else 185 n->rip_dst.sa_family = 186 ntohs(osa(n->rip_dst)->sa_family); 187 n->rip_dst.sa_len = sizeof(n->rip_dst); 188 #endif 189 n->rip_metric = ntohl(n->rip_metric); 190 if (n->rip_dst.sa_family >= af_max || 191 (afp = &afswitch[n->rip_dst.sa_family])->af_hash == 192 (int (*)())0) { 193 syslog(LOG_INFO, 194 "route in unsupported address family (%d), from %s (af %d)\n", 195 n->rip_dst.sa_family, 196 (*afswitch[from->sa_family].af_format)(from), 197 from->sa_family); 198 continue; 199 } 200 if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { 201 syslog(LOG_DEBUG, 202 "bad host in route from %s (af %d)\n", 203 (*afswitch[from->sa_family].af_format)(from), 204 from->sa_family); 205 continue; 206 } 207 if (n->rip_metric == 0 || 208 (unsigned) n->rip_metric > HOPCNT_INFINITY) { 209 if (memcmp(from, &badfrom2, 210 sizeof(badfrom2)) != 0) { 211 syslog(LOG_ERR, 212 "bad metric (%d) from %s\n", 213 n->rip_metric, 214 (*afswitch[from->sa_family].af_format)(from)); 215 badfrom2 = *from; 216 } 217 continue; 218 } 219 /* 220 * Adjust metric according to incoming interface. 221 */ 222 if ((unsigned) n->rip_metric < HOPCNT_INFINITY) 223 n->rip_metric += ifp->int_metric; 224 if ((unsigned) n->rip_metric > HOPCNT_INFINITY) 225 n->rip_metric = HOPCNT_INFINITY; 226 rt = rtlookup(&n->rip_dst); 227 if (rt == 0 || 228 (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == 229 (RTS_INTERNAL|RTS_INTERFACE)) { 230 /* 231 * If we're hearing a logical network route 232 * back from a peer to which we sent it, 233 * ignore it. 234 */ 235 if (rt && rt->rt_state & RTS_SUBNET && 236 (*afp->af_sendroute)(rt, from)) 237 continue; 238 if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { 239 /* 240 * Look for an equivalent route that 241 * includes this one before adding 242 * this route. 243 */ 244 rt = rtfind(&n->rip_dst); 245 if (rt && equal(from, &rt->rt_router)) 246 continue; 247 rtadd(&n->rip_dst, from, n->rip_metric, 0); 248 changes++; 249 } 250 continue; 251 } 252 253 /* 254 * Update if from gateway and different, 255 * shorter, or equivalent but old route 256 * is getting stale. 257 */ 258 if (equal(from, &rt->rt_router)) { 259 if (n->rip_metric != rt->rt_metric) { 260 rtchange(rt, from, n->rip_metric); 261 changes++; 262 rt->rt_timer = 0; 263 if (rt->rt_metric >= HOPCNT_INFINITY) 264 rt->rt_timer = 265 GARBAGE_TIME - EXPIRE_TIME; 266 } else if (rt->rt_metric < HOPCNT_INFINITY) 267 rt->rt_timer = 0; 268 } else if ((unsigned) n->rip_metric < rt->rt_metric || 269 (rt->rt_metric == n->rip_metric && 270 rt->rt_timer > (EXPIRE_TIME/2) && 271 (unsigned) n->rip_metric < HOPCNT_INFINITY)) { 272 rtchange(rt, from, n->rip_metric); 273 changes++; 274 rt->rt_timer = 0; 275 } 276 } 277 break; 278 } 279 280 /* 281 * If changes have occurred, and if we have not sent a broadcast 282 * recently, send a dynamic update. This update is sent only 283 * on interfaces other than the one on which we received notice 284 * of the change. If we are within MIN_WAITTIME of a full update, 285 * don't bother sending; if we just sent a dynamic update 286 * and set a timer (nextbcast), delay until that time. 287 * If we just sent a full update, delay the dynamic update. 288 * Set a timer for a randomized value to suppress additional 289 * dynamic updates until it expires; if we delayed sending 290 * the current changes, set needupdate. 291 */ 292 if (changes && supplier && 293 now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) { 294 u_long delay; 295 extern long random(); 296 297 if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME && 298 timercmp(&nextbcast, &now, <)) { 299 if (traceactions) 300 fprintf(ftrace, "send dynamic update\n"); 301 toall(supply, RTS_CHANGED, ifp); 302 lastbcast = now; 303 needupdate = 0; 304 nextbcast.tv_sec = 0; 305 } else { 306 needupdate++; 307 if (traceactions) 308 fprintf(ftrace, "delay dynamic update\n"); 309 } 310 #define RANDOMDELAY() (MIN_WAITTIME * 1000000 + \ 311 (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000)) 312 313 if (nextbcast.tv_sec == 0) { 314 delay = RANDOMDELAY(); 315 if (traceactions) 316 fprintf(ftrace, 317 "inhibit dynamic update for %d usec\n", 318 delay); 319 nextbcast.tv_sec = delay / 1000000; 320 nextbcast.tv_usec = delay % 1000000; 321 timevaladd(&nextbcast, &now); 322 /* 323 * If the next possibly dynamic update 324 * is within MIN_WAITTIME of the next full update, 325 * force the delay past the full update, 326 * or we might send a dynamic update just before 327 * the full update. 328 */ 329 if (nextbcast.tv_sec > lastfullupdate.tv_sec + 330 SUPPLY_INTERVAL - MIN_WAITTIME) 331 nextbcast.tv_sec = lastfullupdate.tv_sec + 332 SUPPLY_INTERVAL + 1; 333 } 334 } 335 } 336