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.27 (Berkeley) 01/30/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 done; 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 if (error) 212 rtstat.rts_badredirect++; 213 else 214 (stat && (*stat)++); 215 rt_missmsg(RTM_REDIRECT, dst, gateway, netmask, src, flags, error); 216 } 217 218 /* 219 * Routing table ioctl interface. 220 */ 221 rtioctl(req, data, p) 222 int req; 223 caddr_t data; 224 struct proc *p; 225 { 226 #ifndef COMPAT_43 227 return (EOPNOTSUPP); 228 #else 229 register struct ortentry *entry = (struct ortentry *)data; 230 int error; 231 struct sockaddr *netmask = 0; 232 233 if (req == SIOCADDRT) 234 req = RTM_ADD; 235 else if (req == SIOCDELRT) 236 req = RTM_DELETE; 237 else 238 return (EINVAL); 239 240 if (error = suser(p->p_ucred, &p->p_acflag)) 241 return (error); 242 #if BYTE_ORDER != BIG_ENDIAN 243 if (entry->rt_dst.sa_family == 0 && entry->rt_dst.sa_len < 16) { 244 entry->rt_dst.sa_family = entry->rt_dst.sa_len; 245 entry->rt_dst.sa_len = 16; 246 } 247 if (entry->rt_gateway.sa_family == 0 && entry->rt_gateway.sa_len < 16) { 248 entry->rt_gateway.sa_family = entry->rt_gateway.sa_len; 249 entry->rt_gateway.sa_len = 16; 250 } 251 #else 252 if (entry->rt_dst.sa_len == 0) 253 entry->rt_dst.sa_len = 16; 254 if (entry->rt_gateway.sa_len == 0) 255 entry->rt_gateway.sa_len = 16; 256 #endif 257 if ((entry->rt_flags & RTF_HOST) == 0) 258 switch (entry->rt_dst.sa_family) { 259 #ifdef INET 260 case AF_INET: 261 { 262 extern struct sockaddr_in icmpmask; 263 struct sockaddr_in *dst_in = 264 (struct sockaddr_in *)&entry->rt_dst; 265 266 in_sockmaskof(dst_in->sin_addr, &icmpmask); 267 netmask = (struct sockaddr *)&icmpmask; 268 } 269 break; 270 #endif 271 #ifdef NS 272 case AF_NS: 273 { 274 extern struct sockaddr_ns ns_netmask; 275 netmask = (struct sockaddr *)&ns_netmask; 276 } 277 #endif 278 } 279 error = rtrequest(req, &(entry->rt_dst), &(entry->rt_gateway), netmask, 280 entry->rt_flags, (struct rtentry **)0); 281 rt_missmsg((req == RTM_ADD ? RTM_OLDADD : RTM_OLDDEL), 282 &(entry->rt_dst), &(entry->rt_gateway), 283 netmask, SA(0), entry->rt_flags, error); 284 return (error); 285 #endif 286 } 287 288 struct ifaddr * 289 ifa_ifwithroute(flags, dst, gateway) 290 int flags; 291 struct sockaddr *dst, *gateway; 292 { 293 register struct ifaddr *ifa; 294 if ((flags & RTF_GATEWAY) == 0) { 295 /* 296 * If we are adding a route to an interface, 297 * and the interface is a pt to pt link 298 * we should search for the destination 299 * as our clue to the interface. Otherwise 300 * we can use the local address. 301 */ 302 ifa = 0; 303 if (flags & RTF_HOST) 304 ifa = ifa_ifwithdstaddr(dst); 305 if (ifa == 0) 306 ifa = ifa_ifwithaddr(gateway); 307 } else { 308 /* 309 * If we are adding a route to a remote net 310 * or host, the gateway may still be on the 311 * other end of a pt to pt link. 312 */ 313 ifa = ifa_ifwithdstaddr(gateway); 314 } 315 if (ifa == 0) 316 ifa = ifa_ifwithnet(gateway); 317 if (ifa == 0) { 318 struct rtentry *rt = rtalloc1(dst, 0); 319 if (rt == 0) 320 return (0); 321 rt->rt_refcnt--; 322 if ((ifa = rt->rt_ifa) == 0) 323 return (0); 324 } 325 if (ifa->ifa_addr->sa_family != dst->sa_family) { 326 struct ifaddr *oifa = ifa, *ifaof_ifpforaddr(); 327 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 328 if (ifa == 0) 329 ifa = oifa; 330 } 331 return (ifa); 332 } 333 334 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 335 336 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 337 int req, flags; 338 struct sockaddr *dst, *gateway, *netmask; 339 struct rtentry **ret_nrt; 340 { 341 int s = splnet(); int error = 0; 342 register struct rtentry *rt; 343 register struct radix_node *rn; 344 register struct radix_node_head *rnh; 345 struct ifaddr *ifa, *ifa_ifwithdstaddr(); 346 struct sockaddr *ndst; 347 #define senderr(x) { error = x ; goto bad; } 348 349 if (rtinits_done == 0) 350 rtinitheads(); 351 if ((rnh = rt_tables[dst->sa_family]) == 0) 352 senderr(ESRCH); 353 if (flags & RTF_HOST) 354 netmask = 0; 355 switch (req) { 356 case RTM_DELETE: 357 if ((rn = rnh->rnh_delete((caddr_t)dst, (caddr_t)netmask, 358 rnh->rnh_treetop)) == 0) 359 senderr(ESRCH); 360 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 361 panic ("rtrequest delete"); 362 rt = (struct rtentry *)rn; 363 rt->rt_flags &= ~RTF_UP; 364 if (rt->rt_gwroute) { 365 rt = rt->rt_gwroute; RTFREE(rt); 366 (rt = (struct rtentry *)rn)->rt_gwroute = 0; 367 } 368 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 369 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 370 rttrash++; 371 if (rt->rt_refcnt <= 0) 372 rtfree(rt); 373 break; 374 375 case RTM_RESOLVE: 376 if (ret_nrt == 0 || (rt = *ret_nrt) == 0) 377 senderr(EINVAL); 378 ifa = rt->rt_ifa; 379 flags = rt->rt_flags & ~RTF_CLONING; 380 gateway = rt->rt_gateway; 381 if ((netmask = rt->rt_genmask) == 0) 382 flags |= RTF_HOST; 383 goto makeroute; 384 385 case RTM_ADD: 386 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) 387 senderr(ENETUNREACH); 388 makeroute: 389 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 390 if (rt == 0) 391 senderr(ENOBUFS); 392 Bzero(rt, sizeof(*rt)); 393 rt->rt_flags = RTF_UP | flags; 394 if (rt_setgate(rt, dst, gateway)) { 395 Free(rt); 396 senderr(ENOBUFS); 397 } 398 ndst = rt_key(rt); 399 if (netmask) { 400 rt_maskedcopy(dst, ndst, netmask); 401 } else 402 Bcopy(dst, ndst, dst->sa_len); 403 rn = rnh->rnh_add((caddr_t)ndst, (caddr_t)netmask, 404 rnh->rnh_treetop, rt->rt_nodes); 405 if (rn == 0) { 406 if (rt->rt_gwroute) 407 rtfree(rt->rt_gwroute); 408 Free(rt_key(rt)); 409 Free(rt); 410 senderr(EEXIST); 411 } 412 ifa->ifa_refcnt++; 413 rt->rt_ifa = ifa; 414 rt->rt_ifp = ifa->ifa_ifp; 415 if (req == RTM_RESOLVE) 416 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 417 if (ifa->ifa_rtrequest) 418 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); 419 if (ret_nrt) { 420 *ret_nrt = rt; 421 rt->rt_refcnt++; 422 } 423 break; 424 } 425 bad: 426 splx(s); 427 return (error); 428 } 429 430 rt_setgate(rt0, dst, gate) 431 struct rtentry *rt0; 432 struct sockaddr *dst, *gate; 433 { 434 caddr_t new, old; 435 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 436 register struct rtentry *rt = rt0; 437 438 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 439 old = (caddr_t)rt_key(rt); 440 R_Malloc(new, caddr_t, dlen + glen); 441 if (new == 0) 442 return 1; 443 rt->rt_nodes->rn_key = new; 444 } else { 445 new = rt->rt_nodes->rn_key; 446 old = 0; 447 } 448 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 449 if (old) { 450 Bcopy(dst, new, dlen); 451 Free(old); 452 } 453 if (rt->rt_gwroute) { 454 rt = rt->rt_gwroute; RTFREE(rt); 455 rt = rt0; rt->rt_gwroute = 0; 456 } 457 if (rt->rt_flags & RTF_GATEWAY) { 458 rt->rt_gwroute = rtalloc1(gate, 1); 459 } 460 return 0; 461 } 462 463 rt_maskedcopy(src, dst, netmask) 464 struct sockaddr *src, *dst, *netmask; 465 { 466 register u_char *cp1 = (u_char *)src; 467 register u_char *cp2 = (u_char *)dst; 468 register u_char *cp3 = (u_char *)netmask; 469 u_char *cplim = cp2 + *cp3; 470 u_char *cplim2 = cp2 + *cp1; 471 472 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 473 cp3 += 2; 474 if (cplim > cplim2) 475 cplim = cplim2; 476 while (cp2 < cplim) 477 *cp2++ = *cp1++ & *cp3++; 478 if (cp2 < cplim2) 479 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 480 } 481 /* 482 * Set up a routing table entry, normally 483 * for an interface. 484 */ 485 rtinit(ifa, cmd, flags) 486 register struct ifaddr *ifa; 487 int cmd, flags; 488 { 489 register struct rtentry *rt; 490 register struct sockaddr *dst; 491 register struct sockaddr *deldst; 492 struct mbuf *m = 0; 493 int error; 494 495 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 496 if (rt = ifa->ifa_rt) { 497 rtfree(rt); 498 ifa->ifa_rt = 0; 499 } 500 if (cmd == RTM_DELETE) { 501 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 502 m = m_get(M_WAIT, MT_SONAME); 503 deldst = mtod(m, struct sockaddr *); 504 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 505 dst = deldst; 506 } 507 if (rt = rtalloc1(dst, 0)) { 508 rt->rt_refcnt--; 509 if (rt->rt_ifa != ifa) { 510 if (m) 511 (void) m_free(m); 512 return (flags & RTF_HOST ? EHOSTUNREACH 513 : ENETUNREACH); 514 } 515 } 516 } 517 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, 518 flags | ifa->ifa_flags, &ifa->ifa_rt); 519 if (m) 520 (void) m_free(m); 521 if (cmd == RTM_ADD && error == 0 && (rt = ifa->ifa_rt) 522 && rt->rt_ifa != ifa) { 523 rt->rt_ifa = ifa; 524 rt->rt_ifp = ifa->ifa_ifp; 525 } 526 return (error); 527 } 528