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