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