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