1 /* 2 * Copyright (c) 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 34 * $FreeBSD$ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/domain.h> 39 #include <sys/kernel.h> 40 #include <sys/jail.h> 41 #include <sys/malloc.h> 42 #include <sys/mbuf.h> 43 #include <sys/proc.h> 44 #include <sys/protosw.h> 45 #include <sys/signalvar.h> 46 #include <sys/socket.h> 47 #include <sys/socketvar.h> 48 #include <sys/sysctl.h> 49 #include <sys/systm.h> 50 51 #include <net/if.h> 52 #include <net/raw_cb.h> 53 #include <net/route.h> 54 55 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); 56 57 /* NB: these are not modified */ 58 static struct sockaddr route_dst = { 2, PF_ROUTE, }; 59 static struct sockaddr route_src = { 2, PF_ROUTE, }; 60 static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, }; 61 62 static struct { 63 int ip_count; /* attacked w/ AF_INET */ 64 int ip6_count; /* attached w/ AF_INET6 */ 65 int ipx_count; /* attached w/ AF_IPX */ 66 int any_count; /* total attached */ 67 } route_cb; 68 69 struct mtx rtsock_mtx; 70 MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF); 71 72 #define RTSOCK_LOCK() mtx_lock(&rtsock_mtx) 73 #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx) 74 #define RTSOCK_LOCK_ASSERT() mtx_assert(&rtsock_mtx, MA_OWNED) 75 76 struct walkarg { 77 int w_tmemsize; 78 int w_op, w_arg; 79 caddr_t w_tmem; 80 struct sysctl_req *w_req; 81 }; 82 83 static struct mbuf *rt_msg1(int, struct rt_addrinfo *); 84 static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *); 85 static int rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 86 static int sysctl_dumpentry(struct radix_node *rn, void *vw); 87 static int sysctl_iflist(int af, struct walkarg *w); 88 static int route_output(struct mbuf *, struct socket *); 89 static void rt_setmetrics(u_long, struct rt_metrics *, struct rt_metrics *); 90 static void rt_dispatch(struct mbuf *, struct sockaddr *); 91 92 /* 93 * It really doesn't make any sense at all for this code to share much 94 * with raw_usrreq.c, since its functionality is so restricted. XXX 95 */ 96 static int 97 rts_abort(struct socket *so) 98 { 99 int s, error; 100 s = splnet(); 101 error = raw_usrreqs.pru_abort(so); 102 splx(s); 103 return error; 104 } 105 106 /* pru_accept is EOPNOTSUPP */ 107 108 static int 109 rts_attach(struct socket *so, int proto, struct thread *td) 110 { 111 struct rawcb *rp; 112 int s, error; 113 114 if (sotorawcb(so) != 0) 115 return EISCONN; /* XXX panic? */ 116 /* XXX */ 117 MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK | M_ZERO); 118 if (rp == 0) 119 return ENOBUFS; 120 121 /* 122 * The splnet() is necessary to block protocols from sending 123 * error notifications (like RTM_REDIRECT or RTM_LOSING) while 124 * this PCB is extant but incompletely initialized. 125 * Probably we should try to do more of this work beforehand and 126 * eliminate the spl. 127 */ 128 s = splnet(); 129 so->so_pcb = (caddr_t)rp; 130 error = raw_attach(so, proto); 131 rp = sotorawcb(so); 132 if (error) { 133 splx(s); 134 so->so_pcb = NULL; 135 free(rp, M_PCB); 136 return error; 137 } 138 RTSOCK_LOCK(); 139 switch(rp->rcb_proto.sp_protocol) { 140 case AF_INET: 141 route_cb.ip_count++; 142 break; 143 case AF_INET6: 144 route_cb.ip6_count++; 145 break; 146 case AF_IPX: 147 route_cb.ipx_count++; 148 break; 149 } 150 rp->rcb_faddr = &route_src; 151 route_cb.any_count++; 152 RTSOCK_UNLOCK(); 153 soisconnected(so); 154 so->so_options |= SO_USELOOPBACK; 155 splx(s); 156 return 0; 157 } 158 159 static int 160 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 161 { 162 int s, error; 163 s = splnet(); 164 error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */ 165 splx(s); 166 return error; 167 } 168 169 static int 170 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 171 { 172 int s, error; 173 s = splnet(); 174 error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */ 175 splx(s); 176 return error; 177 } 178 179 /* pru_connect2 is EOPNOTSUPP */ 180 /* pru_control is EOPNOTSUPP */ 181 182 static int 183 rts_detach(struct socket *so) 184 { 185 struct rawcb *rp = sotorawcb(so); 186 int s, error; 187 188 s = splnet(); 189 if (rp != 0) { 190 RTSOCK_LOCK(); 191 switch(rp->rcb_proto.sp_protocol) { 192 case AF_INET: 193 route_cb.ip_count--; 194 break; 195 case AF_INET6: 196 route_cb.ip6_count--; 197 break; 198 case AF_IPX: 199 route_cb.ipx_count--; 200 break; 201 } 202 route_cb.any_count--; 203 RTSOCK_UNLOCK(); 204 } 205 error = raw_usrreqs.pru_detach(so); 206 splx(s); 207 return error; 208 } 209 210 static int 211 rts_disconnect(struct socket *so) 212 { 213 int s, error; 214 s = splnet(); 215 error = raw_usrreqs.pru_disconnect(so); 216 splx(s); 217 return error; 218 } 219 220 /* pru_listen is EOPNOTSUPP */ 221 222 static int 223 rts_peeraddr(struct socket *so, struct sockaddr **nam) 224 { 225 int s, error; 226 s = splnet(); 227 error = raw_usrreqs.pru_peeraddr(so, nam); 228 splx(s); 229 return error; 230 } 231 232 /* pru_rcvd is EOPNOTSUPP */ 233 /* pru_rcvoob is EOPNOTSUPP */ 234 235 static int 236 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 237 struct mbuf *control, struct thread *td) 238 { 239 int s, error; 240 s = splnet(); 241 error = raw_usrreqs.pru_send(so, flags, m, nam, control, td); 242 splx(s); 243 return error; 244 } 245 246 /* pru_sense is null */ 247 248 static int 249 rts_shutdown(struct socket *so) 250 { 251 int s, error; 252 s = splnet(); 253 error = raw_usrreqs.pru_shutdown(so); 254 splx(s); 255 return error; 256 } 257 258 static int 259 rts_sockaddr(struct socket *so, struct sockaddr **nam) 260 { 261 int s, error; 262 s = splnet(); 263 error = raw_usrreqs.pru_sockaddr(so, nam); 264 splx(s); 265 return error; 266 } 267 268 static struct pr_usrreqs route_usrreqs = { 269 rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect, 270 pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect, 271 pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, 272 rts_send, pru_sense_null, rts_shutdown, rts_sockaddr, 273 sosend, soreceive, sopoll 274 }; 275 276 /*ARGSUSED*/ 277 static int 278 route_output(m, so) 279 register struct mbuf *m; 280 struct socket *so; 281 { 282 #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0) 283 register struct rt_msghdr *rtm = 0; 284 register struct rtentry *rt = 0; 285 struct radix_node_head *rnh; 286 struct rt_addrinfo info; 287 int len, error = 0; 288 struct ifnet *ifp = 0; 289 struct ifaddr *ifa = 0; 290 291 #define senderr(e) { error = e; goto flush;} 292 if (m == 0 || ((m->m_len < sizeof(long)) && 293 (m = m_pullup(m, sizeof(long))) == 0)) 294 return (ENOBUFS); 295 if ((m->m_flags & M_PKTHDR) == 0) 296 panic("route_output"); 297 len = m->m_pkthdr.len; 298 if (len < sizeof(*rtm) || 299 len != mtod(m, struct rt_msghdr *)->rtm_msglen) { 300 info.rti_info[RTAX_DST] = 0; 301 senderr(EINVAL); 302 } 303 R_Malloc(rtm, struct rt_msghdr *, len); 304 if (rtm == 0) { 305 info.rti_info[RTAX_DST] = 0; 306 senderr(ENOBUFS); 307 } 308 m_copydata(m, 0, len, (caddr_t)rtm); 309 if (rtm->rtm_version != RTM_VERSION) { 310 info.rti_info[RTAX_DST] = 0; 311 senderr(EPROTONOSUPPORT); 312 } 313 rtm->rtm_pid = curproc->p_pid; 314 bzero(&info, sizeof(info)); 315 info.rti_addrs = rtm->rtm_addrs; 316 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) { 317 info.rti_info[RTAX_DST] = 0; 318 senderr(EINVAL); 319 } 320 info.rti_flags = rtm->rtm_flags; 321 if (info.rti_info[RTAX_DST] == 0 || 322 info.rti_info[RTAX_DST]->sa_family >= AF_MAX || 323 (info.rti_info[RTAX_GATEWAY] != 0 && 324 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) 325 senderr(EINVAL); 326 if (info.rti_info[RTAX_GENMASK]) { 327 struct radix_node *t; 328 t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1); 329 if (t && Bcmp((caddr_t *) info.rti_info[RTAX_GENMASK] + 1, 330 (caddr_t *)t->rn_key + 1, 331 *(u_char *)t->rn_key - 1) == 0) 332 info.rti_info[RTAX_GENMASK] = 333 (struct sockaddr *)(t->rn_key); 334 else 335 senderr(ENOBUFS); 336 } 337 338 /* 339 * Verify that the caller has the appropriate privilege; RTM_GET 340 * is the only operation the non-superuser is allowed. 341 */ 342 if (rtm->rtm_type != RTM_GET && (error = suser(curthread)) != 0) 343 senderr(error); 344 345 switch (rtm->rtm_type) { 346 struct rtentry *saved_nrt; 347 348 case RTM_ADD: 349 if (info.rti_info[RTAX_GATEWAY] == 0) 350 senderr(EINVAL); 351 saved_nrt = 0; 352 error = rtrequest1(RTM_ADD, &info, &saved_nrt); 353 if (error == 0 && saved_nrt) { 354 RT_LOCK(saved_nrt); 355 rt_setmetrics(rtm->rtm_inits, 356 &rtm->rtm_rmx, &saved_nrt->rt_rmx); 357 saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 358 saved_nrt->rt_rmx.rmx_locks |= 359 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 360 saved_nrt->rt_refcnt--; 361 saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK]; 362 RT_UNLOCK(saved_nrt); 363 } 364 break; 365 366 case RTM_DELETE: 367 saved_nrt = 0; 368 error = rtrequest1(RTM_DELETE, &info, &saved_nrt); 369 if (error == 0) { 370 RT_LOCK(saved_nrt); 371 rt = saved_nrt; 372 goto report; 373 } 374 break; 375 376 case RTM_GET: 377 case RTM_CHANGE: 378 case RTM_LOCK: 379 rnh = rt_tables[info.rti_info[RTAX_DST]->sa_family]; 380 if (rnh == 0) 381 senderr(EAFNOSUPPORT); 382 RADIX_NODE_HEAD_LOCK(rnh); 383 rt = (struct rtentry *) rnh->rnh_lookup(info.rti_info[RTAX_DST], 384 info.rti_info[RTAX_NETMASK], rnh); 385 RADIX_NODE_HEAD_UNLOCK(rnh); 386 if (rt == NULL) /* XXX looks bogus */ 387 senderr(ESRCH); 388 RT_LOCK(rt); 389 rt->rt_refcnt++; 390 391 switch(rtm->rtm_type) { 392 393 case RTM_GET: 394 report: 395 RT_LOCK_ASSERT(rt); 396 info.rti_info[RTAX_DST] = rt_key(rt); 397 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 398 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 399 info.rti_info[RTAX_GENMASK] = rt->rt_genmask; 400 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 401 ifp = rt->rt_ifp; 402 if (ifp) { 403 info.rti_info[RTAX_IFP] = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr; 404 info.rti_info[RTAX_IFA] = 405 rt->rt_ifa->ifa_addr; 406 if (ifp->if_flags & IFF_POINTOPOINT) 407 info.rti_info[RTAX_BRD] = 408 rt->rt_ifa->ifa_dstaddr; 409 rtm->rtm_index = ifp->if_index; 410 } else { 411 info.rti_info[RTAX_IFP] = 0; 412 info.rti_info[RTAX_IFA] = 0; 413 } 414 } 415 len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, 416 (struct walkarg *)0); 417 if (len > rtm->rtm_msglen) { 418 struct rt_msghdr *new_rtm; 419 R_Malloc(new_rtm, struct rt_msghdr *, len); 420 if (new_rtm == 0) { 421 RT_UNLOCK(rt); 422 senderr(ENOBUFS); 423 } 424 Bcopy(rtm, new_rtm, rtm->rtm_msglen); 425 Free(rtm); rtm = new_rtm; 426 } 427 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, 428 (struct walkarg *)0); 429 rtm->rtm_flags = rt->rt_flags; 430 rtm->rtm_rmx = rt->rt_rmx; 431 rtm->rtm_addrs = info.rti_addrs; 432 break; 433 434 case RTM_CHANGE: 435 /* 436 * New gateway could require new ifaddr, ifp; 437 * flags may also be different; ifp may be specified 438 * by ll sockaddr when protocol address is ambiguous 439 */ 440 if (((rt->rt_flags & RTF_GATEWAY) && 441 info.rti_info[RTAX_GATEWAY] != NULL) || 442 info.rti_info[RTAX_IFP] != NULL || 443 (info.rti_info[RTAX_IFA] != NULL && 444 !sa_equal(info.rti_info[RTAX_IFA], 445 rt->rt_ifa->ifa_addr))) { 446 if ((error = rt_getifa(&info)) != 0) { 447 RT_UNLOCK(rt); 448 senderr(error); 449 } 450 } 451 if (info.rti_info[RTAX_GATEWAY] != NULL && 452 (error = rt_setgate(rt, rt_key(rt), 453 info.rti_info[RTAX_GATEWAY])) != 0) { 454 RT_UNLOCK(rt); 455 senderr(error); 456 } 457 if ((ifa = info.rti_ifa) != NULL) { 458 struct ifaddr *oifa = rt->rt_ifa; 459 if (oifa != ifa) { 460 if (oifa) { 461 if (oifa->ifa_rtrequest) 462 oifa->ifa_rtrequest( 463 RTM_DELETE, rt, 464 &info); 465 IFAFREE(oifa); 466 } 467 IFAREF(ifa); 468 rt->rt_ifa = ifa; 469 rt->rt_ifp = info.rti_ifp; 470 } 471 } 472 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 473 &rt->rt_rmx); 474 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 475 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 476 if (info.rti_info[RTAX_GENMASK]) 477 rt->rt_genmask = info.rti_info[RTAX_GENMASK]; 478 /* FALLTHROUGH */ 479 case RTM_LOCK: 480 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 481 rt->rt_rmx.rmx_locks |= 482 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 483 break; 484 } 485 RT_UNLOCK(rt); 486 break; 487 488 default: 489 senderr(EOPNOTSUPP); 490 } 491 492 flush: 493 if (rtm) { 494 if (error) 495 rtm->rtm_errno = error; 496 else 497 rtm->rtm_flags |= RTF_DONE; 498 } 499 if (rt) /* XXX can this be true? */ 500 RTFREE(rt); 501 { 502 register struct rawcb *rp = 0; 503 /* 504 * Check to see if we don't want our own messages. 505 */ 506 if ((so->so_options & SO_USELOOPBACK) == 0) { 507 if (route_cb.any_count <= 1) { 508 if (rtm) 509 Free(rtm); 510 m_freem(m); 511 return (error); 512 } 513 /* There is another listener, so construct message */ 514 rp = sotorawcb(so); 515 } 516 if (rtm) { 517 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 518 if (m->m_pkthdr.len < rtm->rtm_msglen) { 519 m_freem(m); 520 m = NULL; 521 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 522 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 523 Free(rtm); 524 } 525 if (m) { 526 if (rp) { 527 /* 528 * XXX insure we don't get a copy by 529 * invalidating our protocol 530 */ 531 unsigned short family = rp->rcb_proto.sp_family; 532 rp->rcb_proto.sp_family = 0; 533 rt_dispatch(m, info.rti_info[RTAX_DST]); 534 rp->rcb_proto.sp_family = family; 535 } else 536 rt_dispatch(m, info.rti_info[RTAX_DST]); 537 } 538 } 539 return (error); 540 #undef sa_equal 541 } 542 543 static void 544 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out) 545 { 546 #define metric(f, e) if (which & (f)) out->e = in->e; 547 metric(RTV_RPIPE, rmx_recvpipe); 548 metric(RTV_SPIPE, rmx_sendpipe); 549 metric(RTV_SSTHRESH, rmx_ssthresh); 550 metric(RTV_RTT, rmx_rtt); 551 metric(RTV_RTTVAR, rmx_rttvar); 552 metric(RTV_HOPCOUNT, rmx_hopcount); 553 metric(RTV_MTU, rmx_mtu); 554 metric(RTV_EXPIRE, rmx_expire); 555 #undef metric 556 } 557 558 #define ROUNDUP(a) \ 559 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 560 561 /* 562 * Extract the addresses of the passed sockaddrs. 563 * Do a little sanity checking so as to avoid bad memory references. 564 * This data is derived straight from userland. 565 */ 566 static int 567 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 568 { 569 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 570 register struct sockaddr *sa; 571 register int i; 572 573 for (i = 0; i < RTAX_MAX && cp < cplim; i++) { 574 if ((rtinfo->rti_addrs & (1 << i)) == 0) 575 continue; 576 sa = (struct sockaddr *)cp; 577 /* 578 * It won't fit. 579 */ 580 if (cp + sa->sa_len > cplim) 581 return (EINVAL); 582 /* 583 * there are no more.. quit now 584 * If there are more bits, they are in error. 585 * I've seen this. route(1) can evidently generate these. 586 * This causes kernel to core dump. 587 * for compatibility, If we see this, point to a safe address. 588 */ 589 if (sa->sa_len == 0) { 590 rtinfo->rti_info[i] = &sa_zero; 591 return (0); /* should be EINVAL but for compat */ 592 } 593 /* accept it */ 594 rtinfo->rti_info[i] = sa; 595 ADVANCE(cp, sa); 596 } 597 return (0); 598 #undef ADVANCE 599 } 600 601 static struct mbuf * 602 rt_msg1(int type, struct rt_addrinfo *rtinfo) 603 { 604 register struct rt_msghdr *rtm; 605 register struct mbuf *m; 606 register int i; 607 register struct sockaddr *sa; 608 int len, dlen; 609 610 switch (type) { 611 612 case RTM_DELADDR: 613 case RTM_NEWADDR: 614 len = sizeof(struct ifa_msghdr); 615 break; 616 617 case RTM_DELMADDR: 618 case RTM_NEWMADDR: 619 len = sizeof(struct ifma_msghdr); 620 break; 621 622 case RTM_IFINFO: 623 len = sizeof(struct if_msghdr); 624 break; 625 626 case RTM_IFANNOUNCE: 627 len = sizeof(struct if_announcemsghdr); 628 break; 629 630 default: 631 len = sizeof(struct rt_msghdr); 632 } 633 if (len > MCLBYTES) 634 panic("rt_msg1"); 635 m = m_gethdr(M_DONTWAIT, MT_DATA); 636 if (m && len > MHLEN) { 637 MCLGET(m, M_DONTWAIT); 638 if ((m->m_flags & M_EXT) == 0) { 639 m_free(m); 640 m = NULL; 641 } 642 } 643 if (m == 0) 644 return (m); 645 m->m_pkthdr.len = m->m_len = len; 646 m->m_pkthdr.rcvif = 0; 647 rtm = mtod(m, struct rt_msghdr *); 648 bzero((caddr_t)rtm, len); 649 for (i = 0; i < RTAX_MAX; i++) { 650 if ((sa = rtinfo->rti_info[i]) == NULL) 651 continue; 652 rtinfo->rti_addrs |= (1 << i); 653 dlen = ROUNDUP(sa->sa_len); 654 m_copyback(m, len, dlen, (caddr_t)sa); 655 len += dlen; 656 } 657 if (m->m_pkthdr.len != len) { 658 m_freem(m); 659 return (NULL); 660 } 661 rtm->rtm_msglen = len; 662 rtm->rtm_version = RTM_VERSION; 663 rtm->rtm_type = type; 664 return (m); 665 } 666 667 static int 668 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w) 669 { 670 register int i; 671 int len, dlen, second_time = 0; 672 caddr_t cp0; 673 674 rtinfo->rti_addrs = 0; 675 again: 676 switch (type) { 677 678 case RTM_DELADDR: 679 case RTM_NEWADDR: 680 len = sizeof(struct ifa_msghdr); 681 break; 682 683 case RTM_IFINFO: 684 len = sizeof(struct if_msghdr); 685 break; 686 687 default: 688 len = sizeof(struct rt_msghdr); 689 } 690 cp0 = cp; 691 if (cp0) 692 cp += len; 693 for (i = 0; i < RTAX_MAX; i++) { 694 register struct sockaddr *sa; 695 696 if ((sa = rtinfo->rti_info[i]) == 0) 697 continue; 698 rtinfo->rti_addrs |= (1 << i); 699 dlen = ROUNDUP(sa->sa_len); 700 if (cp) { 701 bcopy((caddr_t)sa, cp, (unsigned)dlen); 702 cp += dlen; 703 } 704 len += dlen; 705 } 706 len = ALIGN(len); 707 if (cp == 0 && w != NULL && !second_time) { 708 register struct walkarg *rw = w; 709 710 if (rw->w_req) { 711 if (rw->w_tmemsize < len) { 712 if (rw->w_tmem) 713 free(rw->w_tmem, M_RTABLE); 714 rw->w_tmem = (caddr_t) 715 malloc(len, M_RTABLE, M_NOWAIT); 716 if (rw->w_tmem) 717 rw->w_tmemsize = len; 718 } 719 if (rw->w_tmem) { 720 cp = rw->w_tmem; 721 second_time = 1; 722 goto again; 723 } 724 } 725 } 726 if (cp) { 727 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 728 729 rtm->rtm_version = RTM_VERSION; 730 rtm->rtm_type = type; 731 rtm->rtm_msglen = len; 732 } 733 return (len); 734 } 735 736 /* 737 * This routine is called to generate a message from the routing 738 * socket indicating that a redirect has occured, a routing lookup 739 * has failed, or that a protocol has detected timeouts to a particular 740 * destination. 741 */ 742 void 743 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error) 744 { 745 struct rt_msghdr *rtm; 746 struct mbuf *m; 747 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 748 749 if (route_cb.any_count == 0) 750 return; 751 m = rt_msg1(type, rtinfo); 752 if (m == 0) 753 return; 754 rtm = mtod(m, struct rt_msghdr *); 755 rtm->rtm_flags = RTF_DONE | flags; 756 rtm->rtm_errno = error; 757 rtm->rtm_addrs = rtinfo->rti_addrs; 758 rt_dispatch(m, sa); 759 } 760 761 /* 762 * This routine is called to generate a message from the routing 763 * socket indicating that the status of a network interface has changed. 764 */ 765 void 766 rt_ifmsg(struct ifnet *ifp) 767 { 768 struct if_msghdr *ifm; 769 struct mbuf *m; 770 struct rt_addrinfo info; 771 772 if (route_cb.any_count == 0) 773 return; 774 bzero((caddr_t)&info, sizeof(info)); 775 m = rt_msg1(RTM_IFINFO, &info); 776 if (m == 0) 777 return; 778 ifm = mtod(m, struct if_msghdr *); 779 ifm->ifm_index = ifp->if_index; 780 ifm->ifm_flags = ifp->if_flags; 781 ifm->ifm_data = ifp->if_data; 782 ifm->ifm_addrs = 0; 783 rt_dispatch(m, NULL); 784 } 785 786 /* 787 * This is called to generate messages from the routing socket 788 * indicating a network interface has had addresses associated with it. 789 * if we ever reverse the logic and replace messages TO the routing 790 * socket indicate a request to configure interfaces, then it will 791 * be unnecessary as the routing socket will automatically generate 792 * copies of it. 793 */ 794 void 795 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) 796 { 797 struct rt_addrinfo info; 798 struct sockaddr *sa = 0; 799 int pass; 800 struct mbuf *m = 0; 801 struct ifnet *ifp = ifa->ifa_ifp; 802 803 if (route_cb.any_count == 0) 804 return; 805 for (pass = 1; pass < 3; pass++) { 806 bzero((caddr_t)&info, sizeof(info)); 807 if ((cmd == RTM_ADD && pass == 1) || 808 (cmd == RTM_DELETE && pass == 2)) { 809 register struct ifa_msghdr *ifam; 810 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 811 812 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; 813 info.rti_info[RTAX_IFP] = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr; 814 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 815 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 816 if ((m = rt_msg1(ncmd, &info)) == NULL) 817 continue; 818 ifam = mtod(m, struct ifa_msghdr *); 819 ifam->ifam_index = ifp->if_index; 820 ifam->ifam_metric = ifa->ifa_metric; 821 ifam->ifam_flags = ifa->ifa_flags; 822 ifam->ifam_addrs = info.rti_addrs; 823 } 824 if ((cmd == RTM_ADD && pass == 2) || 825 (cmd == RTM_DELETE && pass == 1)) { 826 register struct rt_msghdr *rtm; 827 828 if (rt == 0) 829 continue; 830 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 831 info.rti_info[RTAX_DST] = sa = rt_key(rt); 832 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 833 if ((m = rt_msg1(cmd, &info)) == NULL) 834 continue; 835 rtm = mtod(m, struct rt_msghdr *); 836 rtm->rtm_index = ifp->if_index; 837 rtm->rtm_flags |= rt->rt_flags; 838 rtm->rtm_errno = error; 839 rtm->rtm_addrs = info.rti_addrs; 840 } 841 rt_dispatch(m, sa); 842 } 843 } 844 845 /* 846 * This is the analogue to the rt_newaddrmsg which performs the same 847 * function but for multicast group memberhips. This is easier since 848 * there is no route state to worry about. 849 */ 850 void 851 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma) 852 { 853 struct rt_addrinfo info; 854 struct mbuf *m = 0; 855 struct ifnet *ifp = ifma->ifma_ifp; 856 struct ifma_msghdr *ifmam; 857 858 if (route_cb.any_count == 0) 859 return; 860 861 bzero((caddr_t)&info, sizeof(info)); 862 info.rti_info[RTAX_IFA] = ifma->ifma_addr; 863 if (ifp && TAILQ_FIRST(&ifp->if_addrhead)) 864 info.rti_info[RTAX_IFP] = 865 TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr; 866 else 867 info.rti_info[RTAX_IFP] = NULL; 868 /* 869 * If a link-layer address is present, present it as a ``gateway'' 870 * (similarly to how ARP entries, e.g., are presented). 871 */ 872 info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr; 873 m = rt_msg1(cmd, &info); 874 if (m == NULL) 875 return; 876 ifmam = mtod(m, struct ifma_msghdr *); 877 ifmam->ifmam_index = ifp->if_index; 878 ifmam->ifmam_addrs = info.rti_addrs; 879 rt_dispatch(m, ifma->ifma_addr); 880 } 881 882 /* 883 * This is called to generate routing socket messages indicating 884 * network interface arrival and departure. 885 */ 886 void 887 rt_ifannouncemsg(struct ifnet *ifp, int what) 888 { 889 struct if_announcemsghdr *ifan; 890 struct mbuf *m; 891 struct rt_addrinfo info; 892 893 if (route_cb.any_count == 0) 894 return; 895 bzero((caddr_t)&info, sizeof(info)); 896 m = rt_msg1(RTM_IFANNOUNCE, &info); 897 if (m == NULL) 898 return; 899 ifan = mtod(m, struct if_announcemsghdr *); 900 ifan->ifan_index = ifp->if_index; 901 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name)); 902 ifan->ifan_what = what; 903 rt_dispatch(m, NULL); 904 } 905 906 static void 907 rt_dispatch(struct mbuf *m, struct sockaddr *sa) 908 { 909 struct sockproto route_proto; 910 911 route_proto.sp_family = PF_ROUTE; 912 route_proto.sp_protocol = sa ? sa->sa_family : 0; 913 raw_input(m, &route_proto, &route_src, &route_dst); 914 } 915 916 /* 917 * This is used in dumping the kernel table via sysctl(). 918 */ 919 static int 920 sysctl_dumpentry(struct radix_node *rn, void *vw) 921 { 922 struct walkarg *w = vw; 923 struct rtentry *rt = (struct rtentry *)rn; 924 int error = 0, size; 925 struct rt_addrinfo info; 926 927 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 928 return 0; 929 bzero((caddr_t)&info, sizeof(info)); 930 info.rti_info[RTAX_DST] = rt_key(rt); 931 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 932 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 933 info.rti_info[RTAX_GENMASK] = rt->rt_genmask; 934 if (rt->rt_ifp) { 935 info.rti_info[RTAX_IFP] = 936 TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr; 937 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 938 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 939 info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; 940 } 941 size = rt_msg2(RTM_GET, &info, 0, w); 942 if (w->w_req && w->w_tmem) { 943 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 944 945 rtm->rtm_flags = rt->rt_flags; 946 rtm->rtm_use = rt->rt_use; 947 rtm->rtm_rmx = rt->rt_rmx; 948 rtm->rtm_index = rt->rt_ifp->if_index; 949 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 950 rtm->rtm_addrs = info.rti_addrs; 951 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); 952 return (error); 953 } 954 return (error); 955 } 956 957 static int 958 sysctl_iflist(int af, struct walkarg *w) 959 { 960 struct ifnet *ifp; 961 struct ifaddr *ifa; 962 struct rt_addrinfo info; 963 int len, error = 0; 964 965 bzero((caddr_t)&info, sizeof(info)); 966 /* IFNET_RLOCK(); */ /* could sleep XXX */ 967 TAILQ_FOREACH(ifp, &ifnet, if_link) { 968 if (w->w_arg && w->w_arg != ifp->if_index) 969 continue; 970 ifa = TAILQ_FIRST(&ifp->if_addrhead); 971 info.rti_info[RTAX_IFP] = ifa->ifa_addr; 972 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 973 info.rti_info[RTAX_IFP] = 0; 974 if (w->w_req && w->w_tmem) { 975 struct if_msghdr *ifm; 976 977 ifm = (struct if_msghdr *)w->w_tmem; 978 ifm->ifm_index = ifp->if_index; 979 ifm->ifm_flags = ifp->if_flags; 980 ifm->ifm_data = ifp->if_data; 981 ifm->ifm_addrs = info.rti_addrs; 982 error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len); 983 if (error) 984 goto done; 985 } 986 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) { 987 if (af && af != ifa->ifa_addr->sa_family) 988 continue; 989 if (jailed(curthread->td_ucred) && 990 prison_if(curthread->td_ucred, ifa->ifa_addr)) 991 continue; 992 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 993 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 994 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 995 len = rt_msg2(RTM_NEWADDR, &info, 0, w); 996 if (w->w_req && w->w_tmem) { 997 struct ifa_msghdr *ifam; 998 999 ifam = (struct ifa_msghdr *)w->w_tmem; 1000 ifam->ifam_index = ifa->ifa_ifp->if_index; 1001 ifam->ifam_flags = ifa->ifa_flags; 1002 ifam->ifam_metric = ifa->ifa_metric; 1003 ifam->ifam_addrs = info.rti_addrs; 1004 error = SYSCTL_OUT(w->w_req, w->w_tmem, len); 1005 if (error) 1006 goto done; 1007 } 1008 } 1009 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 1010 info.rti_info[RTAX_BRD] = 0; 1011 } 1012 done: 1013 /* IFNET_RUNLOCK(); */ /* XXX */ 1014 return (error); 1015 } 1016 1017 static int 1018 sysctl_rtsock(SYSCTL_HANDLER_ARGS) 1019 { 1020 int *name = (int *)arg1; 1021 u_int namelen = arg2; 1022 struct radix_node_head *rnh; 1023 int i, s, error = EINVAL; 1024 u_char af; 1025 struct walkarg w; 1026 1027 name ++; 1028 namelen--; 1029 if (req->newptr) 1030 return (EPERM); 1031 if (namelen != 3) 1032 return ((namelen < 3) ? EISDIR : ENOTDIR); 1033 af = name[0]; 1034 if (af > AF_MAX) 1035 return (EINVAL); 1036 Bzero(&w, sizeof(w)); 1037 w.w_op = name[1]; 1038 w.w_arg = name[2]; 1039 w.w_req = req; 1040 1041 s = splnet(); 1042 switch (w.w_op) { 1043 1044 case NET_RT_DUMP: 1045 case NET_RT_FLAGS: 1046 if (af != 0) { 1047 if ((rnh = rt_tables[af]) != NULL) { 1048 /* RADIX_NODE_HEAD_LOCK(rnh); */ 1049 error = rnh->rnh_walktree(rnh, 1050 sysctl_dumpentry, &w);/* could sleep XXX */ 1051 /* RADIX_NODE_HEAD_UNLOCK(rnh); */ 1052 } else 1053 error = EAFNOSUPPORT; 1054 } else { 1055 for (i = 1; i <= AF_MAX; i++) 1056 if ((rnh = rt_tables[i]) != NULL) { 1057 /* RADIX_NODE_HEAD_LOCK(rnh); */ 1058 error = rnh->rnh_walktree(rnh, 1059 sysctl_dumpentry, &w); 1060 /* RADIX_NODE_HEAD_UNLOCK(rnh); */ 1061 if (error) 1062 break; 1063 } 1064 } 1065 break; 1066 1067 case NET_RT_IFLIST: 1068 error = sysctl_iflist(af, &w); 1069 } 1070 splx(s); 1071 if (w.w_tmem) 1072 free(w.w_tmem, M_RTABLE); 1073 return (error); 1074 } 1075 1076 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, ""); 1077 1078 /* 1079 * Definitions of protocols supported in the ROUTE domain. 1080 */ 1081 1082 extern struct domain routedomain; /* or at least forward */ 1083 1084 static struct protosw routesw[] = { 1085 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 1086 0, route_output, raw_ctlinput, 0, 1087 0, 1088 raw_init, 0, 0, 0, 1089 &route_usrreqs 1090 } 1091 }; 1092 1093 static struct domain routedomain = 1094 { PF_ROUTE, "route", 0, 0, 0, 1095 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 1096 1097 DOMAIN_SET(route); 1098