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.11 1994/11/03 01:04:30 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 int 354 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 355 int req, flags; 356 struct sockaddr *dst, *gateway, *netmask; 357 struct rtentry **ret_nrt; 358 { 359 int s = splnet(); int error = 0; 360 register struct rtentry *rt; 361 register struct radix_node *rn; 362 register struct radix_node_head *rnh; 363 struct ifaddr *ifa; 364 struct sockaddr *ndst; 365 u_long prflags = 0UL; 366 #define senderr(x) { error = x ; goto bad; } 367 368 if ((rnh = rt_tables[dst->sa_family]) == 0) 369 senderr(ESRCH); 370 if (flags & RTF_HOST) 371 netmask = 0; 372 switch (req) { 373 case RTM_DELETE: 374 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) 375 senderr(ESRCH); 376 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 377 panic ("rtrequest delete"); 378 rt = (struct rtentry *)rn; 379 rt->rt_flags &= ~RTF_UP; 380 if (rt->rt_gwroute) { 381 rt = rt->rt_gwroute; RTFREE(rt); 382 (rt = (struct rtentry *)rn)->rt_gwroute = 0; 383 } 384 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 385 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 386 rttrash++; 387 if (ret_nrt) 388 *ret_nrt = rt; 389 else if (rt->rt_refcnt <= 0) { 390 rt->rt_refcnt++; 391 rtfree(rt); 392 } 393 break; 394 395 case RTM_RESOLVE: 396 if (ret_nrt == 0 || (rt = *ret_nrt) == 0) 397 senderr(EINVAL); 398 ifa = rt->rt_ifa; 399 flags = rt->rt_flags & ~(RTF_CLONING | RTF_PRCLONING); 400 flags |= RTF_WASCLONED; 401 gateway = rt->rt_gateway; 402 if ((netmask = rt->rt_genmask) == 0) 403 flags |= RTF_HOST; 404 if (flags & RTF_STATIC) { 405 flags &= ~RTF_STATIC; 406 } 407 408 goto makeroute; 409 410 case RTM_ADD: 411 if ((flags & RTF_GATEWAY) && !gateway) 412 panic("rtrequest: GATEWAY but no gateway"); 413 414 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) 415 senderr(ENETUNREACH); 416 417 makeroute: 418 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 419 if (rt == 0) 420 senderr(ENOBUFS); 421 Bzero(rt, sizeof(*rt)); 422 rt->rt_flags = RTF_UP | flags; 423 if (rt_setgate(rt, dst, gateway)) { 424 Free(rt); 425 senderr(ENOBUFS); 426 } 427 ndst = rt_key(rt); 428 if (netmask) { 429 rt_maskedcopy(dst, ndst, netmask); 430 } else 431 Bcopy(dst, ndst, dst->sa_len); 432 rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, 433 rnh, rt->rt_nodes); 434 if (rn == 0) { 435 if (rt->rt_gwroute) 436 rtfree(rt->rt_gwroute); 437 Free(rt_key(rt)); 438 Free(rt); 439 senderr(EEXIST); 440 } 441 ifa->ifa_refcnt++; 442 rt->rt_ifa = ifa; 443 rt->rt_ifp = ifa->ifa_ifp; 444 if (req == RTM_RESOLVE) 445 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 446 if (ifa->ifa_rtrequest) 447 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); 448 if (ret_nrt) { 449 *ret_nrt = rt; 450 rt->rt_refcnt++; 451 } 452 break; 453 } 454 bad: 455 splx(s); 456 return (error); 457 } 458 459 int 460 rt_setgate(rt0, dst, gate) 461 struct rtentry *rt0; 462 struct sockaddr *dst, *gate; 463 { 464 caddr_t new, old; 465 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 466 register struct rtentry *rt = rt0; 467 468 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 469 old = (caddr_t)rt_key(rt); 470 R_Malloc(new, caddr_t, dlen + glen); 471 if (new == 0) 472 return 1; 473 rt->rt_nodes->rn_key = new; 474 } else { 475 new = rt->rt_nodes->rn_key; 476 old = 0; 477 } 478 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 479 if (old) { 480 Bcopy(dst, new, dlen); 481 Free(old); 482 } 483 if (rt->rt_gwroute) { 484 rt = rt->rt_gwroute; RTFREE(rt); 485 rt = rt0; rt->rt_gwroute = 0; 486 } 487 if (rt->rt_flags & RTF_GATEWAY) { 488 rt->rt_gwroute = rtalloc1(gate, 1, 0UL); 489 } 490 return 0; 491 } 492 493 void 494 rt_maskedcopy(src, dst, netmask) 495 struct sockaddr *src, *dst, *netmask; 496 { 497 register u_char *cp1 = (u_char *)src; 498 register u_char *cp2 = (u_char *)dst; 499 register u_char *cp3 = (u_char *)netmask; 500 u_char *cplim = cp2 + *cp3; 501 u_char *cplim2 = cp2 + *cp1; 502 503 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 504 cp3 += 2; 505 if (cplim > cplim2) 506 cplim = cplim2; 507 while (cp2 < cplim) 508 *cp2++ = *cp1++ & *cp3++; 509 if (cp2 < cplim2) 510 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 511 } 512 513 /* 514 * Set up a routing table entry, normally 515 * for an interface. 516 */ 517 int 518 rtinit(ifa, cmd, flags) 519 register struct ifaddr *ifa; 520 int cmd, flags; 521 { 522 register struct rtentry *rt; 523 register struct sockaddr *dst; 524 register struct sockaddr *deldst; 525 struct mbuf *m = 0; 526 struct rtentry *nrt = 0; 527 int error; 528 529 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 530 if (cmd == RTM_DELETE) { 531 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 532 m = m_get(M_WAIT, MT_SONAME); 533 deldst = mtod(m, struct sockaddr *); 534 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 535 dst = deldst; 536 } 537 rt = rtalloc1(dst, 0, 0UL); 538 if (rt) { 539 rt->rt_refcnt--; 540 if (rt->rt_ifa != ifa) { 541 if (m) 542 (void) m_free(m); 543 return (flags & RTF_HOST ? EHOSTUNREACH 544 : ENETUNREACH); 545 } 546 } 547 } 548 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, 549 flags | ifa->ifa_flags, &nrt); 550 if (m) 551 (void) m_free(m); 552 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { 553 rt_newaddrmsg(cmd, ifa, error, nrt); 554 if (rt->rt_refcnt <= 0) { 555 rt->rt_refcnt++; 556 rtfree(rt); 557 } 558 } 559 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { 560 rt->rt_refcnt--; 561 if (rt->rt_ifa != ifa) { 562 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 563 rt->rt_ifa); 564 if (rt->rt_ifa->ifa_rtrequest) 565 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 566 IFAFREE(rt->rt_ifa); 567 rt->rt_ifa = ifa; 568 rt->rt_ifp = ifa->ifa_ifp; 569 ifa->ifa_refcnt++; 570 if (ifa->ifa_rtrequest) 571 ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); 572 } 573 rt_newaddrmsg(cmd, ifa, error, nrt); 574 } 575 return (error); 576 } 577