1 /*- 2 * Copyright 1994, 1995 Massachusetts Institute of Technology 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose and without fee is hereby 6 * granted, provided that both the above copyright notice and this 7 * permission notice appear in all copies, that both the above 8 * copyright notice and this permission notice appear in all 9 * supporting documentation, and that the name of M.I.T. not be used 10 * in advertising or publicity pertaining to distribution of the 11 * software without specific, written prior permission. M.I.T. makes 12 * no representations about the suitability of this software for any 13 * purpose. It is provided "as is" without express or implied 14 * warranty. 15 * 16 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 17 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 20 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/sysctl.h> 37 #include <sys/socket.h> 38 #include <sys/mbuf.h> 39 #include <sys/syslog.h> 40 #include <sys/callout.h> 41 42 #include <net/if.h> 43 #include <net/if_var.h> 44 #include <net/route.h> 45 #include <net/vnet.h> 46 47 #include <netinet/in.h> 48 #include <netinet/in_var.h> 49 #include <netinet/ip.h> 50 #include <netinet/ip_icmp.h> 51 #include <netinet/ip_var.h> 52 53 extern int in_inithead(void **head, int off); 54 #ifdef VIMAGE 55 extern int in_detachhead(void **head, int off); 56 #endif 57 58 #define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */ 59 60 /* 61 * Do what we need to do when inserting a route. 62 */ 63 static struct radix_node * 64 in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, 65 struct radix_node *treenodes) 66 { 67 struct rtentry *rt = (struct rtentry *)treenodes; 68 struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt); 69 70 RADIX_NODE_HEAD_WLOCK_ASSERT(head); 71 /* 72 * A little bit of help for both IP output and input: 73 * For host routes, we make sure that RTF_BROADCAST 74 * is set for anything that looks like a broadcast address. 75 * This way, we can avoid an expensive call to in_broadcast() 76 * in ip_output() most of the time (because the route passed 77 * to ip_output() is almost always a host route). 78 * 79 * We also do the same for local addresses, with the thought 80 * that this might one day be used to speed up ip_input(). 81 * 82 * We also mark routes to multicast addresses as such, because 83 * it's easy to do and might be useful (but this is much more 84 * dubious since it's so easy to inspect the address). 85 */ 86 if (rt->rt_flags & RTF_HOST) { 87 if (in_broadcast(sin->sin_addr, rt->rt_ifp)) { 88 rt->rt_flags |= RTF_BROADCAST; 89 } else if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr == 90 sin->sin_addr.s_addr) { 91 rt->rt_flags |= RTF_LOCAL; 92 } 93 } 94 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 95 rt->rt_flags |= RTF_MULTICAST; 96 97 if (rt->rt_ifp != NULL) { 98 99 /* 100 * Check route MTU: 101 * inherit interface MTU if not set or 102 * check if MTU is too large. 103 */ 104 if (rt->rt_mtu == 0) { 105 rt->rt_mtu = rt->rt_ifp->if_mtu; 106 } else if (rt->rt_mtu > rt->rt_ifp->if_mtu) 107 rt->rt_mtu = rt->rt_ifp->if_mtu; 108 } 109 110 return (rn_addroute(v_arg, n_arg, head, treenodes)); 111 } 112 113 /* 114 * This code is the inverse of in_clsroute: on first reference, if we 115 * were managing the route, stop doing so and set the expiration timer 116 * back off again. 117 */ 118 static struct radix_node * 119 in_matroute(void *v_arg, struct radix_node_head *head) 120 { 121 struct radix_node *rn = rn_match(v_arg, head); 122 struct rtentry *rt = (struct rtentry *)rn; 123 124 if (rt) { 125 RT_LOCK(rt); 126 if (rt->rt_flags & RTPRF_OURS) { 127 rt->rt_flags &= ~RTPRF_OURS; 128 rt->rt_expire = 0; 129 } 130 RT_UNLOCK(rt); 131 } 132 return rn; 133 } 134 135 static VNET_DEFINE(int, rtq_reallyold) = 60*60; /* one hour is "really old" */ 136 #define V_rtq_reallyold VNET(rtq_reallyold) 137 SYSCTL_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire, CTLFLAG_VNET | CTLFLAG_RW, 138 &VNET_NAME(rtq_reallyold), 0, 139 "Default expiration time on dynamically learned routes"); 140 141 /* never automatically crank down to less */ 142 static VNET_DEFINE(int, rtq_minreallyold) = 10; 143 #define V_rtq_minreallyold VNET(rtq_minreallyold) 144 SYSCTL_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire, CTLFLAG_VNET | CTLFLAG_RW, 145 &VNET_NAME(rtq_minreallyold), 0, 146 "Minimum time to attempt to hold onto dynamically learned routes"); 147 148 /* 128 cached routes is "too many" */ 149 static VNET_DEFINE(int, rtq_toomany) = 128; 150 #define V_rtq_toomany VNET(rtq_toomany) 151 SYSCTL_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache, CTLFLAG_VNET | CTLFLAG_RW, 152 &VNET_NAME(rtq_toomany), 0, 153 "Upper limit on dynamically learned routes"); 154 155 /* 156 * On last reference drop, mark the route as belong to us so that it can be 157 * timed out. 158 */ 159 static void 160 in_clsroute(struct radix_node *rn, struct radix_node_head *head) 161 { 162 struct rtentry *rt = (struct rtentry *)rn; 163 164 RT_LOCK_ASSERT(rt); 165 166 if (!(rt->rt_flags & RTF_UP)) 167 return; /* prophylactic measures */ 168 169 if (rt->rt_flags & RTPRF_OURS) 170 return; 171 172 if (!(rt->rt_flags & RTF_DYNAMIC)) 173 return; 174 175 /* 176 * If rtq_reallyold is 0, just delete the route without 177 * waiting for a timeout cycle to kill it. 178 */ 179 if (V_rtq_reallyold != 0) { 180 rt->rt_flags |= RTPRF_OURS; 181 rt->rt_expire = time_uptime + V_rtq_reallyold; 182 } else 183 rt_expunge(head, rt); 184 } 185 186 struct rtqk_arg { 187 struct radix_node_head *rnh; 188 int draining; 189 int killed; 190 int found; 191 int updating; 192 time_t nextstop; 193 }; 194 195 /* 196 * Get rid of old routes. When draining, this deletes everything, even when 197 * the timeout is not expired yet. When updating, this makes sure that 198 * nothing has a timeout longer than the current value of rtq_reallyold. 199 */ 200 static int 201 in_rtqkill(struct radix_node *rn, void *rock) 202 { 203 struct rtqk_arg *ap = rock; 204 struct rtentry *rt = (struct rtentry *)rn; 205 int err; 206 207 RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh); 208 209 if (rt->rt_flags & RTPRF_OURS) { 210 ap->found++; 211 212 if (ap->draining || rt->rt_expire <= time_uptime) { 213 if (rt->rt_refcnt > 0) 214 panic("rtqkill route really not free"); 215 216 err = in_rtrequest(RTM_DELETE, 217 (struct sockaddr *)rt_key(rt), 218 rt->rt_gateway, rt_mask(rt), 219 rt->rt_flags | RTF_RNH_LOCKED, 0, 220 rt->rt_fibnum); 221 if (err) { 222 log(LOG_WARNING, "in_rtqkill: error %d\n", err); 223 } else { 224 ap->killed++; 225 } 226 } else { 227 if (ap->updating && 228 (rt->rt_expire - time_uptime > V_rtq_reallyold)) 229 rt->rt_expire = time_uptime + V_rtq_reallyold; 230 ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 231 } 232 } 233 234 return 0; 235 } 236 237 #define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ 238 static VNET_DEFINE(int, rtq_timeout) = RTQ_TIMEOUT; 239 static VNET_DEFINE(struct callout, rtq_timer); 240 241 #define V_rtq_timeout VNET(rtq_timeout) 242 #define V_rtq_timer VNET(rtq_timer) 243 244 static void in_rtqtimo_one(void *rock); 245 246 static void 247 in_rtqtimo(void *rock) 248 { 249 CURVNET_SET((struct vnet *) rock); 250 int fibnum; 251 void *newrock; 252 struct timeval atv; 253 254 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 255 newrock = rt_tables_get_rnh(fibnum, AF_INET); 256 if (newrock != NULL) 257 in_rtqtimo_one(newrock); 258 } 259 atv.tv_usec = 0; 260 atv.tv_sec = V_rtq_timeout; 261 callout_reset(&V_rtq_timer, tvtohz(&atv), in_rtqtimo, rock); 262 CURVNET_RESTORE(); 263 } 264 265 static void 266 in_rtqtimo_one(void *rock) 267 { 268 struct radix_node_head *rnh = rock; 269 struct rtqk_arg arg; 270 static time_t last_adjusted_timeout = 0; 271 272 arg.found = arg.killed = 0; 273 arg.rnh = rnh; 274 arg.nextstop = time_uptime + V_rtq_timeout; 275 arg.draining = arg.updating = 0; 276 RADIX_NODE_HEAD_LOCK(rnh); 277 rnh->rnh_walktree(rnh, in_rtqkill, &arg); 278 RADIX_NODE_HEAD_UNLOCK(rnh); 279 280 /* 281 * Attempt to be somewhat dynamic about this: 282 * If there are ``too many'' routes sitting around taking up space, 283 * then crank down the timeout, and see if we can't make some more 284 * go away. However, we make sure that we will never adjust more 285 * than once in rtq_timeout seconds, to keep from cranking down too 286 * hard. 287 */ 288 if ((arg.found - arg.killed > V_rtq_toomany) && 289 (time_uptime - last_adjusted_timeout >= V_rtq_timeout) && 290 V_rtq_reallyold > V_rtq_minreallyold) { 291 V_rtq_reallyold = 2 * V_rtq_reallyold / 3; 292 if (V_rtq_reallyold < V_rtq_minreallyold) { 293 V_rtq_reallyold = V_rtq_minreallyold; 294 } 295 296 last_adjusted_timeout = time_uptime; 297 #ifdef DIAGNOSTIC 298 log(LOG_DEBUG, "in_rtqtimo: adjusted rtq_reallyold to %d\n", 299 V_rtq_reallyold); 300 #endif 301 arg.found = arg.killed = 0; 302 arg.updating = 1; 303 RADIX_NODE_HEAD_LOCK(rnh); 304 rnh->rnh_walktree(rnh, in_rtqkill, &arg); 305 RADIX_NODE_HEAD_UNLOCK(rnh); 306 } 307 308 } 309 310 void 311 in_rtqdrain(void) 312 { 313 VNET_ITERATOR_DECL(vnet_iter); 314 struct radix_node_head *rnh; 315 struct rtqk_arg arg; 316 int fibnum; 317 318 VNET_LIST_RLOCK_NOSLEEP(); 319 VNET_FOREACH(vnet_iter) { 320 CURVNET_SET(vnet_iter); 321 322 for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { 323 rnh = rt_tables_get_rnh(fibnum, AF_INET); 324 arg.found = arg.killed = 0; 325 arg.rnh = rnh; 326 arg.nextstop = 0; 327 arg.draining = 1; 328 arg.updating = 0; 329 RADIX_NODE_HEAD_LOCK(rnh); 330 rnh->rnh_walktree(rnh, in_rtqkill, &arg); 331 RADIX_NODE_HEAD_UNLOCK(rnh); 332 } 333 CURVNET_RESTORE(); 334 } 335 VNET_LIST_RUNLOCK_NOSLEEP(); 336 } 337 338 void 339 in_setmatchfunc(struct radix_node_head *rnh, int val) 340 { 341 342 rnh->rnh_matchaddr = (val != 0) ? rn_match : in_matroute; 343 } 344 345 static int _in_rt_was_here; 346 /* 347 * Initialize our routing tree. 348 */ 349 int 350 in_inithead(void **head, int off) 351 { 352 struct radix_node_head *rnh; 353 354 if (!rn_inithead(head, 32)) 355 return 0; 356 357 rnh = *head; 358 RADIX_NODE_HEAD_LOCK_INIT(rnh); 359 360 rnh->rnh_addaddr = in_addroute; 361 in_setmatchfunc(rnh, V_drop_redirect); 362 rnh->rnh_close = in_clsroute; 363 if (_in_rt_was_here == 0 ) { 364 callout_init(&V_rtq_timer, CALLOUT_MPSAFE); 365 callout_reset(&V_rtq_timer, 1, in_rtqtimo, curvnet); 366 _in_rt_was_here = 1; 367 } 368 return 1; 369 } 370 371 #ifdef VIMAGE 372 int 373 in_detachhead(void **head, int off) 374 { 375 376 callout_drain(&V_rtq_timer); 377 return (1); 378 } 379 #endif 380 381 /* 382 * This zaps old routes when the interface goes down or interface 383 * address is deleted. In the latter case, it deletes static routes 384 * that point to this address. If we don't do this, we may end up 385 * using the old address in the future. The ones we always want to 386 * get rid of are things like ARP entries, since the user might down 387 * the interface, walk over to a completely different network, and 388 * plug back in. 389 */ 390 struct in_ifadown_arg { 391 struct radix_node_head *rnh; 392 struct ifaddr *ifa; 393 int del; 394 }; 395 396 static int 397 in_ifadownkill(struct radix_node *rn, void *xap) 398 { 399 struct in_ifadown_arg *ap = xap; 400 struct rtentry *rt = (struct rtentry *)rn; 401 402 RT_LOCK(rt); 403 if (rt->rt_ifa == ap->ifa && 404 (ap->del || !(rt->rt_flags & RTF_STATIC))) { 405 /* 406 * Aquire a reference so that it can later be freed 407 * as the refcount would be 0 here in case of at least 408 * ap->del. 409 */ 410 RT_ADDREF(rt); 411 /* 412 * Disconnect it from the tree and permit protocols 413 * to cleanup. 414 */ 415 rt_expunge(ap->rnh, rt); 416 /* 417 * At this point it is an rttrash node, and in case 418 * the above is the only reference we must free it. 419 * If we do not noone will have a pointer and the 420 * rtentry will be leaked forever. 421 * In case someone else holds a reference, we are 422 * fine as we only decrement the refcount. In that 423 * case if the other entity calls RT_REMREF, we 424 * will still be leaking but at least we tried. 425 */ 426 RTFREE_LOCKED(rt); 427 return (0); 428 } 429 RT_UNLOCK(rt); 430 return 0; 431 } 432 433 void 434 in_ifadown(struct ifaddr *ifa, int delete) 435 { 436 struct in_ifadown_arg arg; 437 struct radix_node_head *rnh; 438 int fibnum; 439 440 KASSERT(ifa->ifa_addr->sa_family == AF_INET, 441 ("%s: wrong family", __func__)); 442 443 for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { 444 rnh = rt_tables_get_rnh(fibnum, AF_INET); 445 arg.rnh = rnh; 446 arg.ifa = ifa; 447 arg.del = delete; 448 RADIX_NODE_HEAD_LOCK(rnh); 449 rnh->rnh_walktree(rnh, in_ifadownkill, &arg); 450 RADIX_NODE_HEAD_UNLOCK(rnh); 451 ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ 452 } 453 } 454 455 /* 456 * inet versions of rt functions. These have fib extensions and 457 * for now will just reference the _fib variants. 458 * eventually this order will be reversed, 459 */ 460 void 461 in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum) 462 { 463 rtalloc_ign_fib(ro, ignflags, fibnum); 464 } 465 466 int 467 in_rtrequest( int req, 468 struct sockaddr *dst, 469 struct sockaddr *gateway, 470 struct sockaddr *netmask, 471 int flags, 472 struct rtentry **ret_nrt, 473 u_int fibnum) 474 { 475 return (rtrequest_fib(req, dst, gateway, netmask, 476 flags, ret_nrt, fibnum)); 477 } 478 479 struct rtentry * 480 in_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 481 { 482 return (rtalloc1_fib(dst, report, ignflags, fibnum)); 483 } 484 485 void 486 in_rtredirect(struct sockaddr *dst, 487 struct sockaddr *gateway, 488 struct sockaddr *netmask, 489 int flags, 490 struct sockaddr *src, 491 u_int fibnum) 492 { 493 rtredirect_fib(dst, gateway, netmask, flags, src, fibnum); 494 } 495 496 void 497 in_rtalloc(struct route *ro, u_int fibnum) 498 { 499 rtalloc_ign_fib(ro, 0UL, fibnum); 500 } 501 502 #if 0 503 int in_rt_getifa(struct rt_addrinfo *, u_int fibnum); 504 int in_rtioctl(u_long, caddr_t, u_int); 505 int in_rtrequest1(int, struct rt_addrinfo *, struct rtentry **, u_int); 506 #endif 507 508 509