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