1 /* 2 * Copyright (c) 1980, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)route.c 8.2.1.1 (Berkeley) 12/02/94 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/proc.h> 13 #include <sys/mbuf.h> 14 #include <sys/socket.h> 15 #include <sys/socketvar.h> 16 #include <sys/domain.h> 17 #include <sys/protosw.h> 18 #include <sys/ioctl.h> 19 20 #include <net/if.h> 21 #include <net/route.h> 22 #include <net/raw_cb.h> 23 24 #include <netinet/in.h> 25 #include <netinet/in_var.h> 26 27 #ifdef NS 28 #include <netns/ns.h> 29 #endif 30 31 #define SA(p) ((struct sockaddr *)(p)) 32 33 int rttrash; /* routes not in table but not freed */ 34 struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ 35 36 void 37 rtable_init(table) 38 void **table; 39 { 40 struct domain *dom; 41 for (dom = domains; dom; dom = dom->dom_next) 42 if (dom->dom_rtattach) 43 dom->dom_rtattach(&table[dom->dom_family], 44 dom->dom_rtoffset); 45 } 46 47 void 48 route_init() 49 { 50 rn_init(); /* initialize all zeroes, all ones, mask table */ 51 rtable_init((void **)rt_tables); 52 } 53 54 /* 55 * Packet routing routines. 56 */ 57 void 58 rtalloc(ro) 59 register struct route *ro; 60 { 61 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 62 return; /* XXX */ 63 ro->ro_rt = rtalloc1(&ro->ro_dst, 1); 64 } 65 66 struct rtentry * 67 rtalloc1(dst, report) 68 register struct sockaddr *dst; 69 int report; 70 { 71 register struct radix_node_head *rnh = rt_tables[dst->sa_family]; 72 register struct rtentry *rt; 73 register struct radix_node *rn; 74 struct rtentry *newrt = 0; 75 struct rt_addrinfo info; 76 int s = splnet(), err = 0, msgtype = RTM_MISS; 77 78 bzero((caddr_t)&info, sizeof(info)); 79 info.rti_info[RTAX_DST] = dst; 80 if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && 81 ((rn->rn_flags & RNF_ROOT) == 0)) { 82 newrt = rt = (struct rtentry *)rn; 83 if (report && (rt->rt_flags & RTF_CLONING)) { 84 info.rti_ifa = rt->rt_ifa; 85 info.rti_ifp = rt->rt_ifp; 86 info.rti_flags = rt->rt_flags & ~RTF_CLONING; 87 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 88 if ((info.rti_info[RTAX_NETMASK] = rt->rt_genmask) == 0) 89 info.rti_flags |= RTF_HOST; 90 err = rtrequest1(RTM_RESOLVE, &info, &newrt); 91 if (err) { 92 newrt = rt; 93 rt->rt_refcnt++; 94 goto miss; 95 } 96 newrt->rt_rmx = rt->rt_rmx; 97 if (rt->rt_flags & RTF_XRESOLVE) { 98 msgtype = RTM_RESOLVE; 99 goto miss; 100 } 101 } else 102 rt->rt_refcnt++; 103 } else { 104 rtstat.rts_unreach++; 105 miss: if (report) { 106 rt_missmsg(msgtype, &info, 0, err); 107 } 108 } 109 splx(s); 110 return (newrt); 111 } 112 113 void 114 rtfree(rt) 115 register struct rtentry *rt; 116 { 117 register struct ifaddr *ifa; 118 119 if (rt == 0) 120 panic("rtfree"); 121 rt->rt_refcnt--; 122 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 123 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 124 panic ("rtfree 2"); 125 rttrash--; 126 if (rt->rt_refcnt < 0) { 127 printf("rtfree: %x not freed (neg refs)\n", rt); 128 return; 129 } 130 ifa = rt->rt_ifa; 131 IFAFREE(ifa); 132 Free(rt_key(rt)); 133 Free(rt); 134 } 135 } 136 137 void 138 ifafree(ifa) 139 register struct ifaddr *ifa; 140 { 141 if (ifa == NULL) 142 panic("ifafree"); 143 if (ifa->ifa_refcnt == 0) 144 free(ifa, M_IFADDR); 145 else 146 ifa->ifa_refcnt--; 147 } 148 149 /* 150 * Force a routing table entry to the specified 151 * destination to go through the given gateway. 152 * Normally called as a result of a routing redirect 153 * message from the network layer. 154 * 155 * N.B.: must be called at splnet 156 * 157 */ 158 int 159 rtredirect(dst, gateway, netmask, flags, src, rtp) 160 struct sockaddr *dst, *gateway, *netmask, *src; 161 int flags; 162 struct rtentry **rtp; 163 { 164 register struct rtentry *rt; 165 int error = 0; 166 short *stat = 0; 167 struct rt_addrinfo info; 168 struct ifaddr *ifa; 169 170 /* verify the gateway is directly reachable */ 171 if ((ifa = ifa_ifwithnet(gateway)) == 0) { 172 error = ENETUNREACH; 173 goto out; 174 } 175 rt = rtalloc1(dst, 0); 176 /* 177 * If the redirect isn't from our current router for this dst, 178 * it's either old or wrong. If it redirects us to ourselves, 179 * we have a routing loop, perhaps as a result of an interface 180 * going down recently. 181 */ 182 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) 183 if (!(flags & RTF_DONE) && rt && 184 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 185 error = EINVAL; 186 else if (ifa_ifwithaddr(gateway)) 187 error = EHOSTUNREACH; 188 if (error) 189 goto done; 190 /* 191 * Create a new entry if we just got back a wildcard entry 192 * or the the lookup failed. This is necessary for hosts 193 * which use routing redirects generated by smart gateways 194 * to dynamically build the routing tables. 195 */ 196 if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 197 goto create; 198 /* 199 * Don't listen to the redirect if it's 200 * for a route to an interface. 201 */ 202 if (rt->rt_flags & RTF_GATEWAY) { 203 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 204 /* 205 * Changing from route to net => route to host. 206 * Create new route, rather than smashing route to net. 207 */ 208 create: 209 flags |= RTF_GATEWAY | RTF_DYNAMIC; 210 error = rtrequest((int)RTM_ADD, dst, gateway, 211 netmask, flags, 212 (struct rtentry **)0); 213 stat = &rtstat.rts_dynamic; 214 } else { 215 /* 216 * Smash the current notion of the gateway to 217 * this destination. Should check about netmask!!! 218 */ 219 rt->rt_flags |= RTF_MODIFIED; 220 flags |= RTF_MODIFIED; 221 stat = &rtstat.rts_newgateway; 222 rt_setgate(rt, rt_key(rt), gateway); 223 } 224 } else 225 error = EHOSTUNREACH; 226 done: 227 if (rt) { 228 if (rtp && !error) 229 *rtp = rt; 230 else 231 rtfree(rt); 232 } 233 out: 234 if (error) 235 rtstat.rts_badredirect++; 236 else if (stat != NULL) 237 (*stat)++; 238 bzero((caddr_t)&info, sizeof(info)); 239 info.rti_info[RTAX_DST] = dst; 240 info.rti_info[RTAX_GATEWAY] = gateway; 241 info.rti_info[RTAX_NETMASK] = netmask; 242 info.rti_info[RTAX_AUTHOR] = src; 243 rt_missmsg(RTM_REDIRECT, &info, flags, error); 244 } 245 246 /* 247 * Routing table ioctl interface. 248 */ 249 int 250 rtioctl(req, data, p) 251 int req; 252 caddr_t data; 253 struct proc *p; 254 { 255 return (EOPNOTSUPP); 256 } 257 258 struct ifaddr * 259 ifa_ifwithroute(flags, dst, gateway) 260 int flags; 261 struct sockaddr *dst, *gateway; 262 { 263 register struct ifaddr *ifa; 264 if ((flags & RTF_GATEWAY) == 0) { 265 /* 266 * If we are adding a route to an interface, 267 * and the interface is a pt to pt link 268 * we should search for the destination 269 * as our clue to the interface. Otherwise 270 * we can use the local address. 271 */ 272 ifa = 0; 273 if (flags & RTF_HOST) 274 ifa = ifa_ifwithdstaddr(dst); 275 if (ifa == 0) 276 ifa = ifa_ifwithaddr(gateway); 277 } else { 278 /* 279 * If we are adding a route to a remote net 280 * or host, the gateway may still be on the 281 * other end of a pt to pt link. 282 */ 283 ifa = ifa_ifwithdstaddr(gateway); 284 } 285 if (ifa == 0) 286 ifa = ifa_ifwithnet(gateway); 287 if (ifa == 0) { 288 struct rtentry *rt = rtalloc1(dst, 0); 289 if (rt == 0) 290 return (0); 291 rt->rt_refcnt--; 292 if ((ifa = rt->rt_ifa) == 0) 293 return (0); 294 } 295 if (ifa->ifa_addr->sa_family != dst->sa_family) { 296 struct ifaddr *oifa = ifa; 297 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 298 if (ifa == 0) 299 ifa = oifa; 300 } 301 return (ifa); 302 } 303 304 int 305 rtgateinfo(info) 306 register struct rt_addrinfo *info; 307 { 308 struct ifaddr *ifa; 309 struct ifnet *ifp; 310 int error = 0; 311 /* Sleazy use of local variables throughout this function and next, XXX!!!! */ 312 #define dst info->rti_info[RTAX_DST] 313 #define gateway info->rti_info[RTAX_GATEWAY] 314 #define netmask info->rti_info[RTAX_NETMASK] 315 #define ifaaddr info->rti_info[RTAX_IFA] 316 #define ifpaddr info->rti_info[RTAX_IFP] 317 #define flags info->rti_flags 318 319 /* ifp may be specified by sockaddr_dl 320 when protcol address is ambiguous */ 321 if (info->rti_ifp == 0 && ifpaddr) { 322 ifa = ifa_ifwithnet(ifpaddr); 323 info->rti_ifp = ifa ? ifa->ifa_ifp : 0; 324 } 325 if (info->rti_ifa == 0) { 326 struct sockaddr *sa; 327 if (ifp = info->rti_ifp) { 328 sa = ifaaddr ? ifaaddr : (gateway ? gateway : dst); 329 info->rti_ifa = ifaof_ifpforaddr(sa, ifp); 330 } else 331 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 332 } 333 if (ifa = info->rti_ifa) { 334 if (info->rti_ifp == 0) 335 info->rti_ifp = ifa->ifa_ifp; 336 if (gateway == 0) 337 gateway = ifa->ifa_addr; 338 } else 339 error = ENETUNREACH; 340 return error; 341 } 342 343 344 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 345 346 int 347 rtrequest1(req, info, ret_nrt) 348 int req; 349 register struct rt_addrinfo *info; 350 struct rtentry **ret_nrt; 351 { 352 int s = splnet(); int error = 0; 353 register struct rtentry *rt; 354 register struct radix_node *rn; 355 register struct radix_node_head *rnh; 356 struct sockaddr *ndst; 357 struct ifaddr *ifa = info->rti_ifa; 358 struct ifnet *ifp; 359 #define senderr(x) { error = x ; goto bad; } 360 #define RTE(x) ((struct rtentry *)x) 361 362 if ((rnh = rt_tables[dst->sa_family]) == 0) 363 senderr(ESRCH); 364 if (flags & RTF_HOST) 365 netmask = 0; 366 switch (req) { 367 case RTM_DELETE: 368 if ((ifaaddr || ifpaddr) && rnh->rnh_delete1) { 369 extern struct radix_node_head *mask_rnhead; 370 if (error = rtgateinfo(info)) 371 senderr(error); 372 ifa = info->rti_ifa; 373 ifp = info->rti_ifp; 374 if (netmask && (rn = rn_search(netmask, 375 mask_rnhead->rnh_treetop))) 376 netmask = SA(rn->rn_key); 377 for (rn = rnh->rnh_matchaddr(dst, rnh); rn; 378 rn = rn->rn_dupedkey) { 379 /* following test includes case netmask == 0 */ 380 if (SA(rn->rn_mask) == netmask && 381 ((ifaaddr && ifa == RTE(rn)->rt_ifa) || 382 (!ifaaddr && ifp == RTE(rn)->rt_ifp))) 383 break; 384 if (rn == 0 || (rn = rnh->rnh_delete1(rn, rnh)) == 0) 385 senderr(ESRCH); 386 } 387 } else if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) 388 senderr(ESRCH); 389 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 390 panic ("rtrequest delete"); 391 rt = RTE(rn); 392 rt->rt_flags &= ~RTF_UP; 393 if (rt->rt_gwroute) { 394 rt = rt->rt_gwroute; RTFREE(rt); 395 (rt = RTE(rn))->rt_gwroute = 0; 396 } 397 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 398 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 399 rttrash++; 400 if (ret_nrt) 401 *ret_nrt = rt; 402 else if (rt->rt_refcnt <= 0) { 403 rt->rt_refcnt++; 404 rtfree(rt); 405 } 406 break; 407 408 409 case RTM_ADD: 410 if (ifa == 0) { 411 if (error = rtgateinfo(info)) 412 senderr(error); 413 ifa = info->rti_ifa; 414 } 415 case RTM_RESOLVE: 416 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 417 if (rt == 0) 418 senderr(ENOBUFS); 419 Bzero(rt, sizeof(*rt)); 420 rt->rt_flags = RTF_UP | flags; 421 if (rt_setgate(rt, dst, gateway)) { 422 Free(rt); 423 senderr(ENOBUFS); 424 } 425 ndst = rt_key(rt); 426 if (netmask) { 427 rt_maskedcopy(dst, ndst, netmask); 428 } else 429 Bcopy(dst, ndst, dst->sa_len); 430 rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, 431 rnh, rt->rt_nodes); 432 if (rn == 0) { 433 if (rt->rt_gwroute) 434 rtfree(rt->rt_gwroute); 435 Free(rt_key(rt)); 436 Free(rt); 437 senderr(EEXIST); 438 } 439 ifa->ifa_refcnt++; 440 rt->rt_ifa = ifa; 441 rt->rt_ifp = ifa->ifa_ifp; 442 if (ifa->ifa_rtrequest) 443 ifa->ifa_rtrequest(req, rt, info); 444 if (ret_nrt) { 445 *ret_nrt = rt; 446 rt->rt_refcnt++; 447 } 448 break; 449 } 450 bad: 451 splx(s); 452 return (error); 453 #undef dst 454 #undef gateway 455 #undef netmask 456 #undef ifaaddr 457 #undef ifpaddr 458 #undef flags 459 } 460 461 int 462 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 463 int req, flags; 464 struct sockaddr *dst, *gateway, *netmask; 465 struct rtentry **ret_nrt; 466 { 467 struct rt_addrinfo info; 468 469 bzero((caddr_t)&info, sizeof(info)); 470 info.rti_flags = flags; 471 info.rti_info[RTAX_DST] = dst; 472 info.rti_info[RTAX_GATEWAY] = gateway; 473 info.rti_info[RTAX_NETMASK] = netmask; 474 return rtrequest1(req, info, ret_nrt); 475 } 476 477 int 478 rt_setgate(rt0, dst, gate) 479 struct rtentry *rt0; 480 struct sockaddr *dst, *gate; 481 { 482 caddr_t new, old; 483 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 484 register struct rtentry *rt = rt0; 485 486 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 487 old = (caddr_t)rt_key(rt); 488 R_Malloc(new, caddr_t, dlen + glen); 489 if (new == 0) 490 return 1; 491 rt->rt_nodes->rn_key = new; 492 } else { 493 new = rt->rt_nodes->rn_key; 494 old = 0; 495 } 496 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 497 if (old) { 498 Bcopy(dst, new, dlen); 499 Free(old); 500 } 501 if (rt->rt_gwroute) { 502 rt = rt->rt_gwroute; RTFREE(rt); 503 rt = rt0; rt->rt_gwroute = 0; 504 } 505 if (rt->rt_flags & RTF_GATEWAY) { 506 rt->rt_gwroute = rtalloc1(gate, 1); 507 } 508 return 0; 509 } 510 511 void 512 rt_maskedcopy(src, dst, netmask) 513 struct sockaddr *src, *dst, *netmask; 514 { 515 register u_char *cp1 = (u_char *)src; 516 register u_char *cp2 = (u_char *)dst; 517 register u_char *cp3 = (u_char *)netmask; 518 u_char *cplim = cp2 + *cp3; 519 u_char *cplim2 = cp2 + *cp1; 520 521 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 522 cp3 += 2; 523 if (cplim > cplim2) 524 cplim = cplim2; 525 while (cp2 < cplim) 526 *cp2++ = *cp1++ & *cp3++; 527 if (cp2 < cplim2) 528 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 529 } 530 531 /* 532 * Set up a routing table entry, normally 533 * for an interface. 534 */ 535 int 536 rtinit(ifa, cmd, flags) 537 register struct ifaddr *ifa; 538 int cmd, flags; 539 { 540 register struct rtentry *rt; 541 register struct sockaddr *dst; 542 register struct sockaddr *deldst; 543 struct mbuf *m = 0; 544 struct rtentry *nrt = 0; 545 int error; 546 547 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 548 if (cmd == RTM_DELETE) { 549 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 550 m = m_get(M_WAIT, MT_SONAME); 551 deldst = mtod(m, struct sockaddr *); 552 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 553 dst = deldst; 554 } 555 if (rt = rtalloc1(dst, 0)) { 556 rt->rt_refcnt--; 557 if (rt->rt_ifa != ifa) { 558 if (m) 559 (void) m_free(m); 560 return (flags & RTF_HOST ? EHOSTUNREACH 561 : ENETUNREACH); 562 } 563 } 564 } 565 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, 566 flags | ifa->ifa_flags, &nrt); 567 if (m) 568 (void) m_free(m); 569 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { 570 rt_newaddrmsg(cmd, ifa, error, nrt); 571 if (rt->rt_refcnt <= 0) { 572 rt->rt_refcnt++; 573 rtfree(rt); 574 } 575 } 576 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { 577 rt->rt_refcnt--; 578 if (rt->rt_ifa != ifa) { 579 printf("rtinit: wrong ifa (%x) was (%x)\n", ifa, 580 rt->rt_ifa); 581 if (rt->rt_ifa->ifa_rtrequest) 582 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 583 IFAFREE(rt->rt_ifa); 584 rt->rt_ifa = ifa; 585 rt->rt_ifp = ifa->ifa_ifp; 586 ifa->ifa_refcnt++; 587 if (ifa->ifa_rtrequest) 588 ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); 589 } 590 rt_newaddrmsg(cmd, ifa, error, nrt); 591 } 592 return (error); 593 } 594