1 /* 2 * Copyright (c) 1980, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)route.c 8.2 (Berkeley) 11/15/93 34 * $Id: route.c,v 1.14 1995/01/23 02:00:34 wollman Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/proc.h> 41 #include <sys/mbuf.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/domain.h> 45 #include <sys/protosw.h> 46 #include <sys/ioctl.h> 47 48 #include <net/if.h> 49 #include <net/route.h> 50 #include <net/raw_cb.h> 51 52 #include <netinet/in.h> 53 #include <netinet/in_var.h> 54 55 #ifdef NS 56 #include <netns/ns.h> 57 #endif 58 59 #define SA(p) ((struct sockaddr *)(p)) 60 61 int rttrash; /* routes not in table but not freed */ 62 struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ 63 64 void 65 rtable_init(table) 66 void **table; 67 { 68 struct domain *dom; 69 for (dom = domains; dom; dom = dom->dom_next) 70 if (dom->dom_rtattach) 71 dom->dom_rtattach(&table[dom->dom_family], 72 dom->dom_rtoffset); 73 } 74 75 void 76 route_init() 77 { 78 rn_init(); /* initialize all zeroes, all ones, mask table */ 79 rtable_init((void **)rt_tables); 80 } 81 82 /* 83 * Packet routing routines. 84 */ 85 void 86 rtalloc(ro) 87 register struct route *ro; 88 { 89 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 90 return; /* XXX */ 91 ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL); 92 } 93 94 void 95 rtalloc_ign(ro, ignore) 96 register struct route *ro; 97 u_long ignore; 98 { 99 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 100 return; /* XXX */ 101 ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); 102 } 103 104 struct rtentry * 105 rtalloc1(dst, report, ignflags) 106 register struct sockaddr *dst; 107 int report; 108 u_long ignflags; 109 { 110 register struct radix_node_head *rnh = rt_tables[dst->sa_family]; 111 register struct rtentry *rt; 112 register struct radix_node *rn; 113 struct rtentry *newrt = 0; 114 struct rt_addrinfo info; 115 u_long nflags; 116 int s = splnet(), err = 0, msgtype = RTM_MISS; 117 118 if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && 119 ((rn->rn_flags & RNF_ROOT) == 0)) { 120 newrt = rt = (struct rtentry *)rn; 121 nflags = rt->rt_flags & ~ignflags; 122 if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { 123 err = rtrequest(RTM_RESOLVE, dst, SA(0), 124 SA(0), 0, &newrt); 125 if (err) { 126 newrt = rt; 127 rt->rt_refcnt++; 128 goto miss; 129 } 130 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 131 msgtype = RTM_RESOLVE; 132 goto miss; 133 } 134 } else 135 rt->rt_refcnt++; 136 } else { 137 rtstat.rts_unreach++; 138 miss: if (report) { 139 bzero((caddr_t)&info, sizeof(info)); 140 info.rti_info[RTAX_DST] = dst; 141 rt_missmsg(msgtype, &info, 0, err); 142 } 143 } 144 splx(s); 145 return (newrt); 146 } 147 148 void 149 rtfree(rt) 150 register struct rtentry *rt; 151 { 152 register struct radix_node_head *rnh = 153 rt_tables[rt_key(rt)->sa_family]; 154 register struct ifaddr *ifa; 155 156 if (rt == 0) 157 panic("rtfree"); 158 rt->rt_refcnt--; 159 if(rnh->rnh_close && rt->rt_refcnt == 0) { 160 rnh->rnh_close((struct radix_node *)rt, rnh); 161 } 162 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 163 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 164 panic ("rtfree 2"); 165 rttrash--; 166 if (rt->rt_refcnt < 0) { 167 printf("rtfree: %p not freed (neg refs)\n", rt); 168 return; 169 } 170 ifa = rt->rt_ifa; 171 IFAFREE(ifa); 172 Free(rt_key(rt)); 173 Free(rt); 174 } 175 } 176 177 void 178 ifafree(ifa) 179 register struct ifaddr *ifa; 180 { 181 if (ifa == NULL) 182 panic("ifafree"); 183 if (ifa->ifa_refcnt == 0) 184 free(ifa, M_IFADDR); 185 else 186 ifa->ifa_refcnt--; 187 } 188 189 /* 190 * Force a routing table entry to the specified 191 * destination to go through the given gateway. 192 * Normally called as a result of a routing redirect 193 * message from the network layer. 194 * 195 * N.B.: must be called at splnet 196 * 197 */ 198 void 199 rtredirect(dst, gateway, netmask, flags, src, rtp) 200 struct sockaddr *dst, *gateway, *netmask, *src; 201 int flags; 202 struct rtentry **rtp; 203 { 204 register struct rtentry *rt; 205 int error = 0; 206 short *stat = 0; 207 struct rt_addrinfo info; 208 struct ifaddr *ifa; 209 210 /* verify the gateway is directly reachable */ 211 if ((ifa = ifa_ifwithnet(gateway)) == 0) { 212 error = ENETUNREACH; 213 goto out; 214 } 215 rt = rtalloc1(dst, 0, 0UL); 216 /* 217 * If the redirect isn't from our current router for this dst, 218 * it's either old or wrong. If it redirects us to ourselves, 219 * we have a routing loop, perhaps as a result of an interface 220 * going down recently. 221 */ 222 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) 223 if (!(flags & RTF_DONE) && rt && 224 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 225 error = EINVAL; 226 else if (ifa_ifwithaddr(gateway)) 227 error = EHOSTUNREACH; 228 if (error) 229 goto done; 230 /* 231 * Create a new entry if we just got back a wildcard entry 232 * or the the lookup failed. This is necessary for hosts 233 * which use routing redirects generated by smart gateways 234 * to dynamically build the routing tables. 235 */ 236 if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 237 goto create; 238 /* 239 * Don't listen to the redirect if it's 240 * for a route to an interface. 241 */ 242 if (rt->rt_flags & RTF_GATEWAY) { 243 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 244 /* 245 * Changing from route to net => route to host. 246 * Create new route, rather than smashing route to net. 247 */ 248 create: 249 flags |= RTF_GATEWAY | RTF_DYNAMIC; 250 error = rtrequest((int)RTM_ADD, dst, gateway, 251 netmask, flags, 252 (struct rtentry **)0); 253 stat = &rtstat.rts_dynamic; 254 } else { 255 /* 256 * Smash the current notion of the gateway to 257 * this destination. Should check about netmask!!! 258 */ 259 rt->rt_flags |= RTF_MODIFIED; 260 flags |= RTF_MODIFIED; 261 stat = &rtstat.rts_newgateway; 262 rt_setgate(rt, rt_key(rt), gateway); 263 } 264 } else 265 error = EHOSTUNREACH; 266 done: 267 if (rt) { 268 if (rtp && !error) 269 *rtp = rt; 270 else 271 rtfree(rt); 272 } 273 out: 274 if (error) 275 rtstat.rts_badredirect++; 276 else if (stat != NULL) 277 (*stat)++; 278 bzero((caddr_t)&info, sizeof(info)); 279 info.rti_info[RTAX_DST] = dst; 280 info.rti_info[RTAX_GATEWAY] = gateway; 281 info.rti_info[RTAX_NETMASK] = netmask; 282 info.rti_info[RTAX_AUTHOR] = src; 283 rt_missmsg(RTM_REDIRECT, &info, flags, error); 284 } 285 286 /* 287 * Routing table ioctl interface. 288 */ 289 int 290 rtioctl(req, data, p) 291 int req; 292 caddr_t data; 293 struct proc *p; 294 { 295 #ifdef INET 296 extern int (*mrt_ioctl)(int, caddr_t, struct proc *); 297 /* Multicast goop, grrr... */ 298 return mrt_ioctl(req, data, p); 299 #else /* INET */ 300 return ENXIO; 301 #endif /* INET */ 302 } 303 304 struct ifaddr * 305 ifa_ifwithroute(flags, dst, gateway) 306 int flags; 307 struct sockaddr *dst, *gateway; 308 { 309 register struct ifaddr *ifa; 310 if ((flags & RTF_GATEWAY) == 0) { 311 /* 312 * If we are adding a route to an interface, 313 * and the interface is a pt to pt link 314 * we should search for the destination 315 * as our clue to the interface. Otherwise 316 * we can use the local address. 317 */ 318 ifa = 0; 319 if (flags & RTF_HOST) { 320 ifa = ifa_ifwithdstaddr(dst); 321 } 322 if (ifa == 0) 323 ifa = ifa_ifwithaddr(gateway); 324 } else { 325 /* 326 * If we are adding a route to a remote net 327 * or host, the gateway may still be on the 328 * other end of a pt to pt link. 329 */ 330 ifa = ifa_ifwithdstaddr(gateway); 331 } 332 if (ifa == 0) 333 ifa = ifa_ifwithnet(gateway); 334 if (ifa == 0) { 335 struct rtentry *rt = rtalloc1(dst, 0, 0UL); 336 if (rt == 0) 337 return (0); 338 rt->rt_refcnt--; 339 if ((ifa = rt->rt_ifa) == 0) 340 return (0); 341 } 342 if (ifa->ifa_addr->sa_family != dst->sa_family) { 343 struct ifaddr *oifa = ifa; 344 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 345 if (ifa == 0) 346 ifa = oifa; 347 } 348 return (ifa); 349 } 350 351 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 352 353 static void rt_fixfamily(struct rtentry *rt); 354 355 int 356 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 357 int req, flags; 358 struct sockaddr *dst, *gateway, *netmask; 359 struct rtentry **ret_nrt; 360 { 361 int s = splnet(); int error = 0; 362 register struct rtentry *rt; 363 register struct radix_node *rn; 364 register struct radix_node_head *rnh; 365 struct ifaddr *ifa; 366 struct sockaddr *ndst; 367 u_long prflags = 0UL; 368 #define senderr(x) { error = x ; goto bad; } 369 370 if ((rnh = rt_tables[dst->sa_family]) == 0) 371 senderr(ESRCH); 372 if (flags & RTF_HOST) 373 netmask = 0; 374 switch (req) { 375 case RTM_DELETE: 376 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) 377 senderr(ESRCH); 378 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 379 panic ("rtrequest delete"); 380 rt = (struct rtentry *)rn; 381 rt->rt_flags &= ~RTF_UP; 382 rt_fixfamily(rt); 383 if (rt->rt_gwroute) { 384 rt = rt->rt_gwroute; RTFREE(rt); 385 (rt = (struct rtentry *)rn)->rt_gwroute = 0; 386 } 387 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 388 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 389 rttrash++; 390 if (ret_nrt) 391 *ret_nrt = rt; 392 else if (rt->rt_refcnt <= 0) { 393 rt->rt_refcnt++; 394 rtfree(rt); 395 } 396 break; 397 398 case RTM_RESOLVE: 399 if (ret_nrt == 0 || (rt = *ret_nrt) == 0) 400 senderr(EINVAL); 401 ifa = rt->rt_ifa; 402 flags = rt->rt_flags & ~(RTF_CLONING | RTF_PRCLONING); 403 flags |= RTF_WASCLONED; 404 gateway = rt->rt_gateway; 405 if ((netmask = rt->rt_genmask) == 0) 406 flags |= RTF_HOST; 407 if (flags & RTF_STATIC) { 408 flags &= ~RTF_STATIC; 409 } 410 411 goto makeroute; 412 413 case RTM_ADD: 414 if ((flags & RTF_GATEWAY) && !gateway) 415 panic("rtrequest: GATEWAY but no gateway"); 416 417 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) 418 senderr(ENETUNREACH); 419 420 makeroute: 421 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 422 if (rt == 0) 423 senderr(ENOBUFS); 424 Bzero(rt, sizeof(*rt)); 425 rt->rt_flags = RTF_UP | flags; 426 if (rt_setgate(rt, dst, gateway)) { 427 Free(rt); 428 senderr(ENOBUFS); 429 } 430 ndst = rt_key(rt); 431 if (netmask) { 432 rt_maskedcopy(dst, ndst, netmask); 433 } else 434 Bcopy(dst, ndst, dst->sa_len); 435 rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, 436 rnh, rt->rt_nodes); 437 if (rn == 0) { 438 if (rt->rt_gwroute) 439 rtfree(rt->rt_gwroute); 440 Free(rt_key(rt)); 441 Free(rt); 442 senderr(EEXIST); 443 } 444 ifa->ifa_refcnt++; 445 rt->rt_ifa = ifa; 446 rt->rt_ifp = ifa->ifa_ifp; 447 if (req == RTM_RESOLVE) 448 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 449 if ((req == RTM_RESOLVE) 450 && ((*ret_nrt)->rt_flags & RTF_PRCLONING)) { 451 rt->rt_parent = (*ret_nrt); 452 rt->rt_nextchild = (*ret_nrt)->rt_nextchild; 453 (*ret_nrt)->rt_nextchild = rt; 454 } 455 if (ifa->ifa_rtrequest) 456 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); 457 if (ret_nrt) { 458 *ret_nrt = rt; 459 rt->rt_refcnt++; 460 } 461 break; 462 } 463 bad: 464 splx(s); 465 return (error); 466 } 467 468 /* 469 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' 470 * (i.e., the routes related to it by the operation of cloning). This 471 * involves deleting the entire chain of descendants (in the case of a parent 472 * route being deleted), or removing this route from the chain (in the case 473 * of a child route being deleted). 474 */ 475 static void 476 rt_fixfamily(struct rtentry *rt0) 477 { 478 struct rtentry *rt, *lrt, *nrt; 479 480 if(rt = rt0->rt_parent) { 481 if(rt->rt_flags & RTF_CHAINDELETE) 482 return; /* relax, it will all be done for us */ 483 484 /* So what if it takes linear time? */ 485 do { 486 lrt = rt; 487 rt = rt->rt_nextchild; 488 } while(rt && rt != rt0); 489 lrt->rt_nextchild = rt0->rt_nextchild; 490 } else if((rt = rt0)->rt_nextchild) { 491 lrt = rt; 492 rt->rt_flags |= RTF_CHAINDELETE; 493 494 rt = rt->rt_nextchild; 495 496 while(rt) { 497 nrt = rt->rt_nextchild; 498 /* 499 * There might be some value to open-coding this 500 * rtrequest call, but I am not yet convinced of 501 * the value of this. 502 */ 503 rtrequest(RTM_DELETE, rt_key(rt), 504 (struct sockaddr *)0, rt_mask(rt), 505 rt->rt_flags, (struct rtentry **)0); 506 rt = nrt; 507 } 508 lrt->rt_flags &= ~RTF_CHAINDELETE; 509 } 510 } 511 512 int 513 rt_setgate(rt0, dst, gate) 514 struct rtentry *rt0; 515 struct sockaddr *dst, *gate; 516 { 517 caddr_t new, old; 518 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 519 register struct rtentry *rt = rt0; 520 521 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 522 old = (caddr_t)rt_key(rt); 523 R_Malloc(new, caddr_t, dlen + glen); 524 if (new == 0) 525 return 1; 526 rt->rt_nodes->rn_key = new; 527 } else { 528 new = rt->rt_nodes->rn_key; 529 old = 0; 530 } 531 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 532 if (old) { 533 Bcopy(dst, new, dlen); 534 Free(old); 535 } 536 if (rt->rt_gwroute) { 537 rt = rt->rt_gwroute; RTFREE(rt); 538 rt = rt0; rt->rt_gwroute = 0; 539 } 540 if (rt->rt_flags & RTF_GATEWAY) { 541 rt->rt_gwroute = rtalloc1(gate, 1, 0UL); 542 } 543 return 0; 544 } 545 546 void 547 rt_maskedcopy(src, dst, netmask) 548 struct sockaddr *src, *dst, *netmask; 549 { 550 register u_char *cp1 = (u_char *)src; 551 register u_char *cp2 = (u_char *)dst; 552 register u_char *cp3 = (u_char *)netmask; 553 u_char *cplim = cp2 + *cp3; 554 u_char *cplim2 = cp2 + *cp1; 555 556 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 557 cp3 += 2; 558 if (cplim > cplim2) 559 cplim = cplim2; 560 while (cp2 < cplim) 561 *cp2++ = *cp1++ & *cp3++; 562 if (cp2 < cplim2) 563 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 564 } 565 566 /* 567 * Set up a routing table entry, normally 568 * for an interface. 569 */ 570 int 571 rtinit(ifa, cmd, flags) 572 register struct ifaddr *ifa; 573 int cmd, flags; 574 { 575 register struct rtentry *rt; 576 register struct sockaddr *dst; 577 register struct sockaddr *deldst; 578 struct mbuf *m = 0; 579 struct rtentry *nrt = 0; 580 int error; 581 582 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 583 if (cmd == RTM_DELETE) { 584 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 585 m = m_get(M_WAIT, MT_SONAME); 586 deldst = mtod(m, struct sockaddr *); 587 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 588 dst = deldst; 589 } 590 rt = rtalloc1(dst, 0, 0UL); 591 if (rt) { 592 rt->rt_refcnt--; 593 if (rt->rt_ifa != ifa) { 594 if (m) 595 (void) m_free(m); 596 return (flags & RTF_HOST ? EHOSTUNREACH 597 : ENETUNREACH); 598 } 599 } 600 } 601 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, 602 flags | ifa->ifa_flags, &nrt); 603 if (m) 604 (void) m_free(m); 605 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { 606 rt_newaddrmsg(cmd, ifa, error, nrt); 607 if (rt->rt_refcnt <= 0) { 608 rt->rt_refcnt++; 609 rtfree(rt); 610 } 611 } 612 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { 613 rt->rt_refcnt--; 614 if (rt->rt_ifa != ifa) { 615 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 616 rt->rt_ifa); 617 if (rt->rt_ifa->ifa_rtrequest) 618 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 619 IFAFREE(rt->rt_ifa); 620 rt->rt_ifa = ifa; 621 rt->rt_ifp = ifa->ifa_ifp; 622 ifa->ifa_refcnt++; 623 if (ifa->ifa_rtrequest) 624 ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); 625 } 626 rt_newaddrmsg(cmd, ifa, error, nrt); 627 } 628 return (error); 629 } 630