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.3.1.1 (Berkeley) 02/23/95 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 if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && 79 ((rn->rn_flags & RNF_ROOT) == 0)) { 80 newrt = rt = (struct rtentry *)rn; 81 if (report && (rt->rt_flags & RTF_CLONING)) { 82 err = rtrequest(RTM_RESOLVE, dst, SA(0), 83 SA(0), 0, &newrt); 84 if (err) { 85 newrt = rt; 86 rt->rt_refcnt++; 87 goto miss; 88 } 89 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 90 msgtype = RTM_RESOLVE; 91 goto miss; 92 } 93 } else 94 rt->rt_refcnt++; 95 } else { 96 rtstat.rts_unreach++; 97 miss: if (report) { 98 bzero((caddr_t)&info, sizeof(info)); 99 info.rti_info[RTAX_DST] = dst; 100 rt_missmsg(msgtype, &info, 0, err); 101 } 102 } 103 splx(s); 104 return (newrt); 105 } 106 107 void 108 rtfree(rt) 109 register struct rtentry *rt; 110 { 111 register struct ifaddr *ifa; 112 113 if (rt == 0) 114 panic("rtfree"); 115 rt->rt_refcnt--; 116 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 117 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 118 panic ("rtfree 2"); 119 rttrash--; 120 if (rt->rt_refcnt < 0) { 121 printf("rtfree: %x not freed (neg refs)\n", rt); 122 return; 123 } 124 ifa = rt->rt_ifa; 125 IFAFREE(ifa); 126 Free(rt_key(rt)); 127 Free(rt); 128 } 129 } 130 131 void 132 ifafree(ifa) 133 register struct ifaddr *ifa; 134 { 135 if (ifa == NULL) 136 panic("ifafree"); 137 if (ifa->ifa_refcnt == 0) 138 free(ifa, M_IFADDR); 139 else 140 ifa->ifa_refcnt--; 141 } 142 143 /* 144 * Force a routing table entry to the specified 145 * destination to go through the given gateway. 146 * Normally called as a result of a routing redirect 147 * message from the network layer. 148 * 149 * N.B.: must be called at splnet 150 * 151 */ 152 int 153 rtredirect(dst, gateway, netmask, flags, src, rtp) 154 struct sockaddr *dst, *gateway, *netmask, *src; 155 int flags; 156 struct rtentry **rtp; 157 { 158 register struct rtentry *rt; 159 int error = 0; 160 short *stat = 0; 161 struct rt_addrinfo info; 162 struct ifaddr *ifa; 163 164 /* verify the gateway is directly reachable */ 165 if ((ifa = ifa_ifwithnet(gateway)) == 0) { 166 error = ENETUNREACH; 167 goto out; 168 } 169 rt = rtalloc1(dst, 0); 170 /* 171 * If the redirect isn't from our current router for this dst, 172 * it's either old or wrong. If it redirects us to ourselves, 173 * we have a routing loop, perhaps as a result of an interface 174 * going down recently. 175 */ 176 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) 177 if (!(flags & RTF_DONE) && rt && 178 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 179 error = EINVAL; 180 else if (ifa_ifwithaddr(gateway)) 181 error = EHOSTUNREACH; 182 if (error) 183 goto done; 184 /* 185 * Create a new entry if we just got back a wildcard entry 186 * or the the lookup failed. This is necessary for hosts 187 * which use routing redirects generated by smart gateways 188 * to dynamically build the routing tables. 189 */ 190 if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 191 goto create; 192 /* 193 * Don't listen to the redirect if it's 194 * for a route to an interface. 195 */ 196 if (rt->rt_flags & RTF_GATEWAY) { 197 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 198 /* 199 * Changing from route to net => route to host. 200 * Create new route, rather than smashing route to net. 201 */ 202 create: 203 flags |= RTF_GATEWAY | RTF_DYNAMIC; 204 error = rtrequest((int)RTM_ADD, dst, gateway, 205 netmask, flags, 206 (struct rtentry **)0); 207 stat = &rtstat.rts_dynamic; 208 } else { 209 /* 210 * Smash the current notion of the gateway to 211 * this destination. Should check about netmask!!! 212 */ 213 rt->rt_flags |= RTF_MODIFIED; 214 flags |= RTF_MODIFIED; 215 stat = &rtstat.rts_newgateway; 216 rt_setgate(rt, rt_key(rt), gateway); 217 } 218 } else 219 error = EHOSTUNREACH; 220 done: 221 if (rt) { 222 if (rtp && !error) 223 *rtp = rt; 224 else 225 rtfree(rt); 226 } 227 out: 228 if (error) 229 rtstat.rts_badredirect++; 230 else if (stat != NULL) 231 (*stat)++; 232 bzero((caddr_t)&info, sizeof(info)); 233 info.rti_info[RTAX_DST] = dst; 234 info.rti_info[RTAX_GATEWAY] = gateway; 235 info.rti_info[RTAX_NETMASK] = netmask; 236 info.rti_info[RTAX_AUTHOR] = src; 237 rt_missmsg(RTM_REDIRECT, &info, flags, error); 238 } 239 240 /* 241 * Routing table ioctl interface. 242 */ 243 int 244 rtioctl(req, data, p) 245 u_long req; 246 caddr_t data; 247 struct proc *p; 248 { 249 return (EOPNOTSUPP); 250 } 251 252 struct ifaddr * 253 ifa_ifwithroute(flags, dst, gateway) 254 int flags; 255 struct sockaddr *dst, *gateway; 256 { 257 register struct ifaddr *ifa; 258 if ((flags & RTF_GATEWAY) == 0) { 259 /* 260 * If we are adding a route to an interface, 261 * and the interface is a pt to pt link 262 * we should search for the destination 263 * as our clue to the interface. Otherwise 264 * we can use the local address. 265 */ 266 ifa = 0; 267 if (flags & RTF_HOST) 268 ifa = ifa_ifwithdstaddr(dst); 269 if (ifa == 0) 270 ifa = ifa_ifwithaddr(gateway); 271 } else { 272 /* 273 * If we are adding a route to a remote net 274 * or host, the gateway may still be on the 275 * other end of a pt to pt link. 276 */ 277 ifa = ifa_ifwithdstaddr(gateway); 278 } 279 if (ifa == 0) 280 ifa = ifa_ifwithnet(gateway); 281 return (ifa); 282 } 283 284 int 285 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 286 int req, flags; 287 struct sockaddr *dst, *gateway, *netmask; 288 struct rtentry **ret_nrt; 289 { 290 struct rt_addrinfo info; 291 292 bzero((caddr_t)&info, sizeof(info)); 293 info.rti_flags = flags; 294 info.rti_info[RTAX_DST] = dst; 295 info.rti_info[RTAX_GATEWAY] = gateway; 296 info.rti_info[RTAX_NETMASK] = netmask; 297 return rtrequest1(req, &info, ret_nrt); 298 } 299 300 /* 301 * These (questionable) definitions of apparent local variables apply 302 * to the next two functions. XXXXXX!!! 303 */ 304 #define dst info->rti_info[RTAX_DST] 305 #define gateway info->rti_info[RTAX_GATEWAY] 306 #define netmask info->rti_info[RTAX_NETMASK] 307 #define ifaaddr info->rti_info[RTAX_IFA] 308 #define ifpaddr info->rti_info[RTAX_IFP] 309 #define flags info->rti_flags 310 311 int 312 rt_getifa(info) 313 register struct rt_addrinfo *info; 314 { 315 struct ifaddr *ifa; 316 int error = 0; 317 318 /* ifp may be specified by sockaddr_dl 319 when protocol address is ambiguous */ 320 if (info->rti_ifp == 0 && ifpaddr && ifpaddr->sa_family == AF_LINK) { 321 ifa = ifa_ifwithnet(ifpaddr); 322 info->rti_ifp = ifa ? ifa->ifa_ifp : 0; 323 } 324 if (info->rti_ifa == 0) { 325 struct sockaddr *sa; 326 327 sa = ifaaddr ? ifaaddr : (gateway ? gateway : dst); 328 if (sa && info->rti_ifp) 329 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 330 else if (dst && gateway) 331 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 332 else if (sa) 333 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 334 } 335 if (ifa = info->rti_ifa) { 336 if (info->rti_ifp == 0) 337 info->rti_ifp = ifa->ifa_ifp; 338 } else 339 error = ENETUNREACH; 340 return error; 341 } 342 343 int 344 rtrequest1(req, info, ret_nrt) 345 int req; 346 register struct rt_addrinfo *info; 347 struct rtentry **ret_nrt; 348 { 349 int s = splnet(); int error = 0; 350 register struct rtentry *rt; 351 register struct radix_node *rn; 352 register struct radix_node_head *rnh; 353 struct ifaddr *ifa; 354 struct sockaddr *ndst; 355 #define senderr(x) { error = x ; goto bad; } 356 357 if ((rnh = rt_tables[dst->sa_family]) == 0) 358 senderr(EAFNOSUPPORT); 359 if (flags & RTF_HOST) 360 netmask = 0; 361 switch (req) { 362 case RTM_DELPKT: 363 if (rnh->rnh_deladdr == 0) 364 senderr(EOPNOTSUPP); 365 rn = rnh->rnh_delpkt(info->rti_pkthdr, (caddr_t)info, rnh); 366 goto delete; 367 case RTM_DELETE: 368 rn = rnh->rnh_deladdr(dst, netmask, rnh); 369 delete: 370 if (rn == 0) 371 senderr(ESRCH); 372 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 373 panic ("rtrequest delete"); 374 rt = (struct rtentry *)rn; 375 rt->rt_flags &= ~RTF_UP; 376 if (rt->rt_gwroute) { 377 rt = rt->rt_gwroute; RTFREE(rt); 378 (rt = (struct rtentry *)rn)->rt_gwroute = 0; 379 } 380 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 381 ifa->ifa_rtrequest(req, rt, info); 382 rttrash++; 383 if (ret_nrt) 384 *ret_nrt = rt; 385 else if (rt->rt_refcnt <= 0) { 386 rt->rt_refcnt++; 387 rtfree(rt); 388 } 389 break; 390 391 case RTM_RESOLVE: 392 if (ret_nrt == 0 || (rt = *ret_nrt) == 0) 393 senderr(EINVAL); 394 ifa = rt->rt_ifa; 395 flags = rt->rt_flags & ~RTF_CLONING; 396 gateway = rt->rt_gateway; 397 if ((netmask = rt->rt_genmask) == 0) 398 flags |= RTF_HOST; 399 goto makeroute; 400 401 case RTM_ADDPKT: 402 if (rnh->rnh_addpkt == 0) 403 senderr(EOPNOTSUPP); 404 /*FALLTHROUGH*/ 405 case RTM_ADD: 406 if (info->rti_ifa == 0 && (error = rt_getifa(info))) 407 senderr(error); 408 ifa = info->rti_ifa; 409 makeroute: 410 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 411 if (rt == 0) 412 senderr(ENOBUFS); 413 Bzero(rt, sizeof(*rt)); 414 rt->rt_flags = RTF_UP | flags; 415 if (rt_setgate(rt, dst, gateway)) { 416 Free(rt); 417 senderr(ENOBUFS); 418 } 419 if (req == RTM_ADDPKT) { 420 rn = rnh->rnh_addpkt(info->rti_pkthdr, (caddr_t)info, 421 rnh, rt->rt_nodes); 422 goto add; /* addpkt() must allocate space */ 423 } 424 ndst = rt_key(rt); 425 if (netmask) { 426 rt_maskedcopy(dst, ndst, netmask); 427 } else 428 Bcopy(dst, ndst, dst->sa_len); 429 rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, 430 rnh, rt->rt_nodes); 431 add: 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 (req == RTM_RESOLVE) 443 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 444 if (ifa->ifa_rtrequest) 445 ifa->ifa_rtrequest(req, rt, info); 446 if (ret_nrt) { 447 *ret_nrt = rt; 448 rt->rt_refcnt++; 449 } 450 break; 451 default: 452 error = EOPNOTSUPP; 453 } 454 bad: 455 splx(s); 456 return (error); 457 #undef dst 458 #undef gateway 459 #undef netmask 460 #undef ifaaddr 461 #undef ifpaddr 462 #undef flags 463 } 464 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 465 466 int 467 rt_setgate(rt0, dst, gate) 468 struct rtentry *rt0; 469 struct sockaddr *dst, *gate; 470 { 471 caddr_t new, old; 472 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 473 register struct rtentry *rt = rt0; 474 475 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 476 old = (caddr_t)rt_key(rt); 477 R_Malloc(new, caddr_t, dlen + glen); 478 if (new == 0) 479 return 1; 480 rt->rt_nodes->rn_key = new; 481 } else { 482 new = rt->rt_nodes->rn_key; 483 old = 0; 484 } 485 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 486 if (old) { 487 Bcopy(dst, new, dlen); 488 Free(old); 489 } 490 if (rt->rt_gwroute) { 491 rt = rt->rt_gwroute; RTFREE(rt); 492 rt = rt0; rt->rt_gwroute = 0; 493 } 494 return 0; 495 } 496 497 void 498 rt_maskedcopy(src, dst, netmask) 499 struct sockaddr *src, *dst, *netmask; 500 { 501 register u_char *cp1 = (u_char *)src; 502 register u_char *cp2 = (u_char *)dst; 503 register u_char *cp3 = (u_char *)netmask; 504 u_char *cplim = cp2 + *cp3; 505 u_char *cplim2 = cp2 + *cp1; 506 507 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 508 cp3 += 2; 509 if (cplim > cplim2) 510 cplim = cplim2; 511 while (cp2 < cplim) 512 *cp2++ = *cp1++ & *cp3++; 513 if (cp2 < cplim2) 514 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 515 } 516 517 /* 518 * Set up a routing table entry, normally 519 * for an interface. 520 */ 521 int 522 rtinit(ifa, cmd, flags) 523 register struct ifaddr *ifa; 524 int cmd, flags; 525 { 526 register struct rtentry *rt; 527 register struct sockaddr *dst; 528 register struct sockaddr *deldst; 529 struct mbuf *m = 0; 530 struct rtentry *nrt = 0; 531 struct radix_node_head *rnh; 532 struct radix_node *rn; 533 int error; 534 struct rt_addrinfo info; 535 536 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 537 if (cmd == RTM_DELETE) { 538 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 539 m = m_get(M_WAIT, MT_SONAME); 540 deldst = mtod(m, struct sockaddr *); 541 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 542 dst = deldst; 543 } 544 if ((rnh = rt_tables[dst->sa_family]) == 0 || 545 (rn = rnh->rnh_lookup(dst, ifa->ifa_netmask, rnh)) == 0 || 546 (rn->rn_flags & RNF_ROOT) != 0 || 547 ((struct rtentry *)rn)->rt_ifa != ifa || 548 !equal(rt_key(rt), dst)) 549 { 550 if (m) 551 (void) m_free(m); 552 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 553 } 554 } 555 bzero((caddr_t)&info, sizeof(info)); 556 info.rti_ifa = ifa; 557 info.rti_flags = flags | ifa->ifa_flags; 558 info.rti_info[RTAX_DST] = dst; 559 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 560 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 561 error = rtrequest1(cmd, &info, &nrt); 562 563 if (error == 0 && (rt = nrt)) { 564 rt_newaddrmsg(cmd, ifa, error, rt); 565 if (cmd == RTM_DELETE) { 566 if (rt->rt_refcnt <= 0) { 567 rt->rt_refcnt++; 568 rtfree(rt); 569 } 570 } else if (cmd == RTM_ADD) 571 rt->rt_refcnt--; 572 } 573 if (m) 574 (void) m_free(m); 575 return (error); 576 } 577