1 /* 2 * Copyright (c) 2004, 2005 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Jeffrey M. Hsu. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of The DragonFly Project nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific, prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1988, 1991, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 62 * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $ 63 */ 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/kernel.h> 68 #include <sys/sysctl.h> 69 #include <sys/proc.h> 70 #include <sys/priv.h> 71 #include <sys/malloc.h> 72 #include <sys/mbuf.h> 73 #include <sys/protosw.h> 74 #include <sys/socket.h> 75 #include <sys/socketvar.h> 76 #include <sys/domain.h> 77 78 #include <sys/thread2.h> 79 #include <sys/socketvar2.h> 80 81 #include <net/if.h> 82 #include <net/route.h> 83 #include <net/raw_cb.h> 84 #include <net/netmsg2.h> 85 #include <net/netisr2.h> 86 87 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); 88 89 static struct route_cb { 90 int ip_count; 91 int ip6_count; 92 int ns_count; 93 int any_count; 94 } route_cb; 95 96 static const struct sockaddr route_src = { 2, PF_ROUTE, }; 97 98 struct walkarg { 99 int w_tmemsize; 100 int w_op, w_arg; 101 void *w_tmem; 102 struct sysctl_req *w_req; 103 }; 104 105 static struct mbuf * 106 rt_msg_mbuf (int, struct rt_addrinfo *); 107 static void rt_msg_buffer (int, struct rt_addrinfo *, void *buf, int len); 108 static int rt_msgsize(int type, const struct rt_addrinfo *rtinfo); 109 static int rt_xaddrs (char *, char *, struct rt_addrinfo *); 110 static int sysctl_dumpentry (struct radix_node *rn, void *vw); 111 static int sysctl_rttable(int af, struct sysctl_req *req, int op, int arg); 112 static int sysctl_iflist (int af, struct walkarg *w); 113 static int route_output(struct mbuf *, struct socket *, ...); 114 static void rt_setmetrics (u_long, struct rt_metrics *, 115 struct rt_metrics *); 116 117 /* 118 * It really doesn't make any sense at all for this code to share much 119 * with raw_usrreq.c, since its functionality is so restricted. XXX 120 */ 121 static void 122 rts_abort(netmsg_t msg) 123 { 124 crit_enter(); 125 raw_usrreqs.pru_abort(msg); 126 /* msg invalid now */ 127 crit_exit(); 128 } 129 130 /* pru_accept is EOPNOTSUPP */ 131 132 static void 133 rts_attach(netmsg_t msg) 134 { 135 struct socket *so = msg->base.nm_so; 136 struct pru_attach_info *ai = msg->attach.nm_ai; 137 struct rawcb *rp; 138 int proto = msg->attach.nm_proto; 139 int error; 140 141 crit_enter(); 142 if (sotorawcb(so) != NULL) { 143 error = EISCONN; 144 goto done; 145 } 146 147 rp = kmalloc(sizeof *rp, M_PCB, M_WAITOK | M_ZERO); 148 149 /* 150 * The critical section is necessary to block protocols from sending 151 * error notifications (like RTM_REDIRECT or RTM_LOSING) while 152 * this PCB is extant but incompletely initialized. 153 * Probably we should try to do more of this work beforehand and 154 * eliminate the critical section. 155 */ 156 so->so_pcb = rp; 157 soreference(so); /* so_pcb assignment */ 158 error = raw_attach(so, proto, ai->sb_rlimit); 159 rp = sotorawcb(so); 160 if (error) { 161 kfree(rp, M_PCB); 162 goto done; 163 } 164 switch(rp->rcb_proto.sp_protocol) { 165 case AF_INET: 166 route_cb.ip_count++; 167 break; 168 case AF_INET6: 169 route_cb.ip6_count++; 170 break; 171 } 172 rp->rcb_faddr = &route_src; 173 route_cb.any_count++; 174 soisconnected(so); 175 so->so_options |= SO_USELOOPBACK; 176 error = 0; 177 done: 178 crit_exit(); 179 lwkt_replymsg(&msg->lmsg, error); 180 } 181 182 static void 183 rts_bind(netmsg_t msg) 184 { 185 crit_enter(); 186 raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */ 187 /* msg invalid now */ 188 crit_exit(); 189 } 190 191 static void 192 rts_connect(netmsg_t msg) 193 { 194 crit_enter(); 195 raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */ 196 /* msg invalid now */ 197 crit_exit(); 198 } 199 200 /* pru_connect2 is EOPNOTSUPP */ 201 /* pru_control is EOPNOTSUPP */ 202 203 static void 204 rts_detach(netmsg_t msg) 205 { 206 struct socket *so = msg->base.nm_so; 207 struct rawcb *rp = sotorawcb(so); 208 209 crit_enter(); 210 if (rp != NULL) { 211 switch(rp->rcb_proto.sp_protocol) { 212 case AF_INET: 213 route_cb.ip_count--; 214 break; 215 case AF_INET6: 216 route_cb.ip6_count--; 217 break; 218 } 219 route_cb.any_count--; 220 } 221 raw_usrreqs.pru_detach(msg); 222 /* msg invalid now */ 223 crit_exit(); 224 } 225 226 static void 227 rts_disconnect(netmsg_t msg) 228 { 229 crit_enter(); 230 raw_usrreqs.pru_disconnect(msg); 231 /* msg invalid now */ 232 crit_exit(); 233 } 234 235 /* pru_listen is EOPNOTSUPP */ 236 237 static void 238 rts_peeraddr(netmsg_t msg) 239 { 240 crit_enter(); 241 raw_usrreqs.pru_peeraddr(msg); 242 /* msg invalid now */ 243 crit_exit(); 244 } 245 246 /* pru_rcvd is EOPNOTSUPP */ 247 /* pru_rcvoob is EOPNOTSUPP */ 248 249 static void 250 rts_send(netmsg_t msg) 251 { 252 crit_enter(); 253 raw_usrreqs.pru_send(msg); 254 /* msg invalid now */ 255 crit_exit(); 256 } 257 258 /* pru_sense is null */ 259 260 static void 261 rts_shutdown(netmsg_t msg) 262 { 263 crit_enter(); 264 raw_usrreqs.pru_shutdown(msg); 265 /* msg invalid now */ 266 crit_exit(); 267 } 268 269 static void 270 rts_sockaddr(netmsg_t msg) 271 { 272 crit_enter(); 273 raw_usrreqs.pru_sockaddr(msg); 274 /* msg invalid now */ 275 crit_exit(); 276 } 277 278 static struct pr_usrreqs route_usrreqs = { 279 .pru_abort = rts_abort, 280 .pru_accept = pr_generic_notsupp, 281 .pru_attach = rts_attach, 282 .pru_bind = rts_bind, 283 .pru_connect = rts_connect, 284 .pru_connect2 = pr_generic_notsupp, 285 .pru_control = pr_generic_notsupp, 286 .pru_detach = rts_detach, 287 .pru_disconnect = rts_disconnect, 288 .pru_listen = pr_generic_notsupp, 289 .pru_peeraddr = rts_peeraddr, 290 .pru_rcvd = pr_generic_notsupp, 291 .pru_rcvoob = pr_generic_notsupp, 292 .pru_send = rts_send, 293 .pru_sense = pru_sense_null, 294 .pru_shutdown = rts_shutdown, 295 .pru_sockaddr = rts_sockaddr, 296 .pru_sosend = sosend, 297 .pru_soreceive = soreceive 298 }; 299 300 static __inline sa_family_t 301 familyof(struct sockaddr *sa) 302 { 303 return (sa != NULL ? sa->sa_family : 0); 304 } 305 306 /* 307 * Routing socket input function. The packet must be serialized onto cpu 0. 308 * We use the cpu0_soport() netisr processing loop to handle it. 309 * 310 * This looks messy but it means that anyone, including interrupt code, 311 * can send a message to the routing socket. 312 */ 313 static void 314 rts_input_handler(netmsg_t msg) 315 { 316 static const struct sockaddr route_dst = { 2, PF_ROUTE, }; 317 struct sockproto route_proto; 318 struct netmsg_packet *pmsg = &msg->packet; 319 struct mbuf *m; 320 sa_family_t family; 321 struct rawcb *skip; 322 323 family = pmsg->base.lmsg.u.ms_result; 324 route_proto.sp_family = PF_ROUTE; 325 route_proto.sp_protocol = family; 326 327 m = pmsg->nm_packet; 328 M_ASSERTPKTHDR(m); 329 330 skip = m->m_pkthdr.header; 331 m->m_pkthdr.header = NULL; 332 333 raw_input(m, &route_proto, &route_src, &route_dst, skip); 334 } 335 336 static void 337 rts_input_skip(struct mbuf *m, sa_family_t family, struct rawcb *skip) 338 { 339 struct netmsg_packet *pmsg; 340 lwkt_port_t port; 341 342 M_ASSERTPKTHDR(m); 343 344 port = netisr_cpuport(0); /* XXX same as for routing socket */ 345 pmsg = &m->m_hdr.mh_netmsg; 346 netmsg_init(&pmsg->base, NULL, &netisr_apanic_rport, 347 0, rts_input_handler); 348 pmsg->nm_packet = m; 349 pmsg->base.lmsg.u.ms_result = family; 350 m->m_pkthdr.header = skip; /* XXX steal field in pkthdr */ 351 lwkt_sendmsg(port, &pmsg->base.lmsg); 352 } 353 354 static __inline void 355 rts_input(struct mbuf *m, sa_family_t family) 356 { 357 rts_input_skip(m, family, NULL); 358 } 359 360 static void * 361 reallocbuf_nofree(void *ptr, size_t len, size_t olen) 362 { 363 void *newptr; 364 365 newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK); 366 if (newptr == NULL) 367 return NULL; 368 bcopy(ptr, newptr, olen); 369 return (newptr); 370 } 371 372 /* 373 * Internal helper routine for route_output(). 374 */ 375 static int 376 _fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt, 377 struct rt_addrinfo *rtinfo) 378 { 379 int msglen; 380 struct rt_msghdr *rtm = *prtm; 381 382 /* Fill in rt_addrinfo for call to rt_msg_buffer(). */ 383 rtinfo->rti_dst = rt_key(rt); 384 rtinfo->rti_gateway = rt->rt_gateway; 385 rtinfo->rti_netmask = rt_mask(rt); /* might be NULL */ 386 rtinfo->rti_genmask = rt->rt_genmask; /* might be NULL */ 387 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 388 if (rt->rt_ifp != NULL) { 389 rtinfo->rti_ifpaddr = 390 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid]) 391 ->ifa->ifa_addr; 392 rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr; 393 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 394 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr; 395 rtm->rtm_index = rt->rt_ifp->if_index; 396 } else { 397 rtinfo->rti_ifpaddr = NULL; 398 rtinfo->rti_ifaaddr = NULL; 399 } 400 } else if (rt->rt_ifp != NULL) { 401 rtm->rtm_index = rt->rt_ifp->if_index; 402 } 403 404 msglen = rt_msgsize(rtm->rtm_type, rtinfo); 405 if (rtm->rtm_msglen < msglen) { 406 /* NOTE: Caller will free the old rtm accordingly */ 407 rtm = reallocbuf_nofree(rtm, msglen, rtm->rtm_msglen); 408 if (rtm == NULL) 409 return (ENOBUFS); 410 *prtm = rtm; 411 } 412 rt_msg_buffer(rtm->rtm_type, rtinfo, rtm, msglen); 413 414 rtm->rtm_flags = rt->rt_flags; 415 rtm->rtm_rmx = rt->rt_rmx; 416 rtm->rtm_addrs = rtinfo->rti_addrs; 417 418 return (0); 419 } 420 421 struct rtm_arg { 422 struct rt_msghdr *bak_rtm; 423 struct rt_msghdr *new_rtm; 424 }; 425 426 static int 427 fillrtmsg(struct rtm_arg *arg, struct rtentry *rt, 428 struct rt_addrinfo *rtinfo) 429 { 430 struct rt_msghdr *rtm = arg->new_rtm; 431 int error; 432 433 error = _fillrtmsg(&rtm, rt, rtinfo); 434 if (!error) { 435 if (arg->new_rtm != rtm) { 436 /* 437 * _fillrtmsg() just allocated a new rtm; 438 * if the previously allocated rtm is not 439 * the backing rtm, it should be freed. 440 */ 441 if (arg->new_rtm != arg->bak_rtm) 442 kfree(arg->new_rtm, M_RTABLE); 443 arg->new_rtm = rtm; 444 } 445 } 446 return error; 447 } 448 449 static void route_output_add_callback(int, int, struct rt_addrinfo *, 450 struct rtentry *, void *); 451 static void route_output_delete_callback(int, int, struct rt_addrinfo *, 452 struct rtentry *, void *); 453 static int route_output_get_callback(int, struct rt_addrinfo *, 454 struct rtentry *, void *, int); 455 static int route_output_change_callback(int, struct rt_addrinfo *, 456 struct rtentry *, void *, int); 457 static int route_output_lock_callback(int, struct rt_addrinfo *, 458 struct rtentry *, void *, int); 459 460 /*ARGSUSED*/ 461 static int 462 route_output(struct mbuf *m, struct socket *so, ...) 463 { 464 struct rtm_arg arg; 465 struct rt_msghdr *rtm = NULL; 466 struct rawcb *rp = NULL; 467 struct pr_output_info *oi; 468 struct rt_addrinfo rtinfo; 469 sa_family_t family; 470 int len, error = 0; 471 __va_list ap; 472 473 M_ASSERTPKTHDR(m); 474 475 __va_start(ap, so); 476 oi = __va_arg(ap, struct pr_output_info *); 477 __va_end(ap); 478 479 family = familyof(NULL); 480 481 #define gotoerr(e) { error = e; goto flush;} 482 483 if (m == NULL || 484 (m->m_len < sizeof(long) && 485 (m = m_pullup(m, sizeof(long))) == NULL)) 486 return (ENOBUFS); 487 len = m->m_pkthdr.len; 488 if (len < sizeof(struct rt_msghdr) || 489 len != mtod(m, struct rt_msghdr *)->rtm_msglen) 490 gotoerr(EINVAL); 491 492 rtm = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK); 493 if (rtm == NULL) 494 gotoerr(ENOBUFS); 495 496 m_copydata(m, 0, len, (caddr_t)rtm); 497 if (rtm->rtm_version != RTM_VERSION) 498 gotoerr(EPROTONOSUPPORT); 499 500 rtm->rtm_pid = oi->p_pid; 501 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 502 rtinfo.rti_addrs = rtm->rtm_addrs; 503 if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0) 504 gotoerr(EINVAL); 505 506 rtinfo.rti_flags = rtm->rtm_flags; 507 if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX || 508 (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX)) 509 gotoerr(EINVAL); 510 511 family = familyof(rtinfo.rti_dst); 512 513 /* 514 * Verify that the caller has the appropriate privilege; RTM_GET 515 * is the only operation the non-superuser is allowed. 516 */ 517 if (rtm->rtm_type != RTM_GET && 518 priv_check_cred(so->so_cred, PRIV_ROOT, 0) != 0) 519 gotoerr(EPERM); 520 521 if (rtinfo.rti_genmask != NULL) { 522 error = rtmask_add_global(rtinfo.rti_genmask, 523 rtm->rtm_type != RTM_GET ? 524 RTREQ_PRIO_HIGH : RTREQ_PRIO_NORM); 525 if (error) 526 goto flush; 527 } 528 529 switch (rtm->rtm_type) { 530 case RTM_ADD: 531 if (rtinfo.rti_gateway == NULL) { 532 error = EINVAL; 533 } else { 534 error = rtrequest1_global(RTM_ADD, &rtinfo, 535 route_output_add_callback, rtm, RTREQ_PRIO_HIGH); 536 } 537 break; 538 case RTM_DELETE: 539 /* 540 * Backing rtm (bak_rtm) could _not_ be freed during 541 * rtrequest1_global or rtsearch_global, even if the 542 * callback reallocates the rtm due to its size changes, 543 * since rtinfo points to the backing rtm's memory area. 544 * After rtrequest1_global or rtsearch_global returns, 545 * it is safe to free the backing rtm, since rtinfo will 546 * not be used anymore. 547 * 548 * new_rtm will be used to save the new rtm allocated 549 * by rtrequest1_global or rtsearch_global. 550 */ 551 arg.bak_rtm = rtm; 552 arg.new_rtm = rtm; 553 error = rtrequest1_global(RTM_DELETE, &rtinfo, 554 route_output_delete_callback, &arg, RTREQ_PRIO_HIGH); 555 rtm = arg.new_rtm; 556 if (rtm != arg.bak_rtm) 557 kfree(arg.bak_rtm, M_RTABLE); 558 break; 559 case RTM_GET: 560 /* See the comment in RTM_DELETE */ 561 arg.bak_rtm = rtm; 562 arg.new_rtm = rtm; 563 error = rtsearch_global(RTM_GET, &rtinfo, 564 route_output_get_callback, &arg, RTS_NOEXACTMATCH, 565 RTREQ_PRIO_NORM); 566 rtm = arg.new_rtm; 567 if (rtm != arg.bak_rtm) 568 kfree(arg.bak_rtm, M_RTABLE); 569 break; 570 case RTM_CHANGE: 571 error = rtsearch_global(RTM_CHANGE, &rtinfo, 572 route_output_change_callback, rtm, RTS_EXACTMATCH, 573 RTREQ_PRIO_HIGH); 574 break; 575 case RTM_LOCK: 576 error = rtsearch_global(RTM_LOCK, &rtinfo, 577 route_output_lock_callback, rtm, RTS_EXACTMATCH, 578 RTREQ_PRIO_HIGH); 579 break; 580 default: 581 error = EOPNOTSUPP; 582 break; 583 } 584 flush: 585 if (rtm != NULL) { 586 if (error != 0) 587 rtm->rtm_errno = error; 588 else 589 rtm->rtm_flags |= RTF_DONE; 590 } 591 592 /* 593 * Check to see if we don't want our own messages. 594 */ 595 if (!(so->so_options & SO_USELOOPBACK)) { 596 if (route_cb.any_count <= 1) { 597 if (rtm != NULL) 598 kfree(rtm, M_RTABLE); 599 m_freem(m); 600 return (error); 601 } 602 /* There is another listener, so construct message */ 603 rp = sotorawcb(so); 604 } 605 if (rtm != NULL) { 606 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 607 if (m->m_pkthdr.len < rtm->rtm_msglen) { 608 m_freem(m); 609 m = NULL; 610 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 611 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 612 kfree(rtm, M_RTABLE); 613 } 614 if (m != NULL) 615 rts_input_skip(m, family, rp); 616 return (error); 617 } 618 619 static void 620 route_output_add_callback(int cmd, int error, struct rt_addrinfo *rtinfo, 621 struct rtentry *rt, void *arg) 622 { 623 struct rt_msghdr *rtm = arg; 624 625 if (error == 0 && rt != NULL) { 626 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 627 &rt->rt_rmx); 628 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 629 rt->rt_rmx.rmx_locks |= 630 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 631 if (rtinfo->rti_genmask != NULL) { 632 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask); 633 if (rt->rt_genmask == NULL) { 634 /* 635 * This should not happen, since we 636 * have already installed genmask 637 * on each CPU before we reach here. 638 */ 639 panic("genmask is gone!?"); 640 } 641 } else { 642 rt->rt_genmask = NULL; 643 } 644 rtm->rtm_index = rt->rt_ifp->if_index; 645 } 646 } 647 648 static void 649 route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo, 650 struct rtentry *rt, void *arg) 651 { 652 if (error == 0 && rt) { 653 ++rt->rt_refcnt; 654 if (fillrtmsg(arg, rt, rtinfo) != 0) { 655 error = ENOBUFS; 656 /* XXX no way to return the error */ 657 } 658 --rt->rt_refcnt; 659 } 660 if (rt && rt->rt_refcnt == 0) { 661 ++rt->rt_refcnt; 662 rtfree(rt); 663 } 664 } 665 666 static int 667 route_output_get_callback(int cmd, struct rt_addrinfo *rtinfo, 668 struct rtentry *rt, void *arg, int found_cnt) 669 { 670 int error, found = 0; 671 672 if (((rtinfo->rti_flags ^ rt->rt_flags) & RTF_HOST) == 0) 673 found = 1; 674 675 error = fillrtmsg(arg, rt, rtinfo); 676 if (!error && found) { 677 /* Got the exact match, we could return now! */ 678 error = EJUSTRETURN; 679 } 680 return error; 681 } 682 683 static int 684 route_output_change_callback(int cmd, struct rt_addrinfo *rtinfo, 685 struct rtentry *rt, void *arg, int found_cnt) 686 { 687 struct rt_msghdr *rtm = arg; 688 struct ifaddr *ifa; 689 int error = 0; 690 691 /* 692 * new gateway could require new ifaddr, ifp; 693 * flags may also be different; ifp may be specified 694 * by ll sockaddr when protocol address is ambiguous 695 */ 696 if (((rt->rt_flags & RTF_GATEWAY) && rtinfo->rti_gateway != NULL) || 697 rtinfo->rti_ifpaddr != NULL || 698 (rtinfo->rti_ifaaddr != NULL && 699 !sa_equal(rtinfo->rti_ifaaddr, rt->rt_ifa->ifa_addr))) { 700 error = rt_getifa(rtinfo); 701 if (error != 0) 702 goto done; 703 } 704 if (rtinfo->rti_gateway != NULL) { 705 /* 706 * We only need to generate rtmsg upon the 707 * first route to be changed. 708 */ 709 error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway, 710 found_cnt == 1 ? RTL_REPORTMSG : RTL_DONTREPORT); 711 if (error != 0) 712 goto done; 713 } 714 if ((ifa = rtinfo->rti_ifa) != NULL) { 715 struct ifaddr *oifa = rt->rt_ifa; 716 717 if (oifa != ifa) { 718 if (oifa && oifa->ifa_rtrequest) 719 oifa->ifa_rtrequest(RTM_DELETE, rt); 720 IFAFREE(rt->rt_ifa); 721 IFAREF(ifa); 722 rt->rt_ifa = ifa; 723 rt->rt_ifp = rtinfo->rti_ifp; 724 } 725 } 726 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx); 727 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 728 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt); 729 if (rtinfo->rti_genmask != NULL) { 730 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask); 731 if (rt->rt_genmask == NULL) { 732 /* 733 * This should not happen, since we 734 * have already installed genmask 735 * on each CPU before we reach here. 736 */ 737 panic("genmask is gone!?"); 738 } 739 } 740 rtm->rtm_index = rt->rt_ifp->if_index; 741 done: 742 return error; 743 } 744 745 static int 746 route_output_lock_callback(int cmd, struct rt_addrinfo *rtinfo, 747 struct rtentry *rt, void *arg, 748 int found_cnt __unused) 749 { 750 struct rt_msghdr *rtm = arg; 751 752 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 753 rt->rt_rmx.rmx_locks |= 754 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 755 return 0; 756 } 757 758 static void 759 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out) 760 { 761 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt; 762 setmetric(RTV_RPIPE, rmx_recvpipe); 763 setmetric(RTV_SPIPE, rmx_sendpipe); 764 setmetric(RTV_SSTHRESH, rmx_ssthresh); 765 setmetric(RTV_RTT, rmx_rtt); 766 setmetric(RTV_RTTVAR, rmx_rttvar); 767 setmetric(RTV_HOPCOUNT, rmx_hopcount); 768 setmetric(RTV_MTU, rmx_mtu); 769 setmetric(RTV_EXPIRE, rmx_expire); 770 setmetric(RTV_MSL, rmx_msl); 771 setmetric(RTV_IWMAXSEGS, rmx_iwmaxsegs); 772 setmetric(RTV_IWCAPSEGS, rmx_iwcapsegs); 773 #undef setmetric 774 } 775 776 /* 777 * Extract the addresses of the passed sockaddrs. 778 * Do a little sanity checking so as to avoid bad memory references. 779 * This data is derived straight from userland. 780 */ 781 static int 782 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo) 783 { 784 struct sockaddr *sa; 785 int i; 786 787 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 788 if ((rtinfo->rti_addrs & (1 << i)) == 0) 789 continue; 790 sa = (struct sockaddr *)cp; 791 /* 792 * It won't fit. 793 */ 794 if ((cp + sa->sa_len) > cplim) { 795 return (EINVAL); 796 } 797 798 /* 799 * There are no more... Quit now. 800 * If there are more bits, they are in error. 801 * I've seen this. route(1) can evidently generate these. 802 * This causes kernel to core dump. 803 * For compatibility, if we see this, point to a safe address. 804 */ 805 if (sa->sa_len == 0) { 806 static struct sockaddr sa_zero = { 807 sizeof sa_zero, AF_INET, 808 }; 809 810 rtinfo->rti_info[i] = &sa_zero; 811 kprintf("rtsock: received more addr bits than sockaddrs.\n"); 812 return (0); /* should be EINVAL but for compat */ 813 } 814 815 /* Accept the sockaddr. */ 816 rtinfo->rti_info[i] = sa; 817 cp += RT_ROUNDUP(sa->sa_len); 818 } 819 return (0); 820 } 821 822 static int 823 rt_msghdrsize(int type) 824 { 825 switch (type) { 826 case RTM_DELADDR: 827 case RTM_NEWADDR: 828 return sizeof(struct ifa_msghdr); 829 case RTM_DELMADDR: 830 case RTM_NEWMADDR: 831 return sizeof(struct ifma_msghdr); 832 case RTM_IFINFO: 833 return sizeof(struct if_msghdr); 834 case RTM_IFANNOUNCE: 835 case RTM_IEEE80211: 836 return sizeof(struct if_announcemsghdr); 837 default: 838 return sizeof(struct rt_msghdr); 839 } 840 } 841 842 static int 843 rt_msgsize(int type, const struct rt_addrinfo *rtinfo) 844 { 845 int len, i; 846 847 len = rt_msghdrsize(type); 848 for (i = 0; i < RTAX_MAX; i++) { 849 if (rtinfo->rti_info[i] != NULL) 850 len += RT_ROUNDUP(rtinfo->rti_info[i]->sa_len); 851 } 852 len = ALIGN(len); 853 return len; 854 } 855 856 /* 857 * Build a routing message in a buffer. 858 * Copy the addresses in the rtinfo->rti_info[] sockaddr array 859 * to the end of the buffer after the message header. 860 * 861 * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[]. 862 * This side-effect can be avoided if we reorder the addrs bitmask field in all 863 * the route messages to line up so we can set it here instead of back in the 864 * calling routine. 865 */ 866 static void 867 rt_msg_buffer(int type, struct rt_addrinfo *rtinfo, void *buf, int msglen) 868 { 869 struct rt_msghdr *rtm; 870 char *cp; 871 int dlen, i; 872 873 rtm = (struct rt_msghdr *) buf; 874 rtm->rtm_version = RTM_VERSION; 875 rtm->rtm_type = type; 876 rtm->rtm_msglen = msglen; 877 878 cp = (char *)buf + rt_msghdrsize(type); 879 rtinfo->rti_addrs = 0; 880 for (i = 0; i < RTAX_MAX; i++) { 881 struct sockaddr *sa; 882 883 if ((sa = rtinfo->rti_info[i]) == NULL) 884 continue; 885 rtinfo->rti_addrs |= (1 << i); 886 dlen = RT_ROUNDUP(sa->sa_len); 887 bcopy(sa, cp, dlen); 888 cp += dlen; 889 } 890 } 891 892 /* 893 * Build a routing message in a mbuf chain. 894 * Copy the addresses in the rtinfo->rti_info[] sockaddr array 895 * to the end of the mbuf after the message header. 896 * 897 * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[]. 898 * This side-effect can be avoided if we reorder the addrs bitmask field in all 899 * the route messages to line up so we can set it here instead of back in the 900 * calling routine. 901 */ 902 static struct mbuf * 903 rt_msg_mbuf(int type, struct rt_addrinfo *rtinfo) 904 { 905 struct mbuf *m; 906 struct rt_msghdr *rtm; 907 int hlen, len; 908 int i; 909 910 hlen = rt_msghdrsize(type); 911 KASSERT(hlen <= MCLBYTES, ("rt_msg_mbuf: hlen %d doesn't fit", hlen)); 912 913 m = m_getl(hlen, M_NOWAIT, MT_DATA, M_PKTHDR, NULL); 914 if (m == NULL) 915 return (NULL); 916 mbuftrackid(m, 32); 917 m->m_pkthdr.len = m->m_len = hlen; 918 m->m_pkthdr.rcvif = NULL; 919 rtinfo->rti_addrs = 0; 920 len = hlen; 921 for (i = 0; i < RTAX_MAX; i++) { 922 struct sockaddr *sa; 923 int dlen; 924 925 if ((sa = rtinfo->rti_info[i]) == NULL) 926 continue; 927 rtinfo->rti_addrs |= (1 << i); 928 dlen = RT_ROUNDUP(sa->sa_len); 929 m_copyback(m, len, dlen, (caddr_t)sa); /* can grow mbuf chain */ 930 len += dlen; 931 } 932 if (m->m_pkthdr.len != len) { /* one of the m_copyback() calls failed */ 933 m_freem(m); 934 return (NULL); 935 } 936 rtm = mtod(m, struct rt_msghdr *); 937 bzero(rtm, hlen); 938 rtm->rtm_msglen = len; 939 rtm->rtm_version = RTM_VERSION; 940 rtm->rtm_type = type; 941 return (m); 942 } 943 944 /* 945 * This routine is called to generate a message from the routing 946 * socket indicating that a redirect has occurred, a routing lookup 947 * has failed, or that a protocol has detected timeouts to a particular 948 * destination. 949 */ 950 void 951 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error) 952 { 953 struct sockaddr *dst = rtinfo->rti_info[RTAX_DST]; 954 struct rt_msghdr *rtm; 955 struct mbuf *m; 956 957 if (route_cb.any_count == 0) 958 return; 959 m = rt_msg_mbuf(type, rtinfo); 960 if (m == NULL) 961 return; 962 rtm = mtod(m, struct rt_msghdr *); 963 rtm->rtm_flags = RTF_DONE | flags; 964 rtm->rtm_errno = error; 965 rtm->rtm_addrs = rtinfo->rti_addrs; 966 rts_input(m, familyof(dst)); 967 } 968 969 void 970 rt_dstmsg(int type, struct sockaddr *dst, int error) 971 { 972 struct rt_msghdr *rtm; 973 struct rt_addrinfo addrs; 974 struct mbuf *m; 975 976 if (route_cb.any_count == 0) 977 return; 978 bzero(&addrs, sizeof(struct rt_addrinfo)); 979 addrs.rti_info[RTAX_DST] = dst; 980 m = rt_msg_mbuf(type, &addrs); 981 if (m == NULL) 982 return; 983 rtm = mtod(m, struct rt_msghdr *); 984 rtm->rtm_flags = RTF_DONE; 985 rtm->rtm_errno = error; 986 rtm->rtm_addrs = addrs.rti_addrs; 987 rts_input(m, familyof(dst)); 988 } 989 990 /* 991 * This routine is called to generate a message from the routing 992 * socket indicating that the status of a network interface has changed. 993 */ 994 void 995 rt_ifmsg(struct ifnet *ifp) 996 { 997 struct if_msghdr *ifm; 998 struct mbuf *m; 999 struct rt_addrinfo rtinfo; 1000 1001 if (route_cb.any_count == 0) 1002 return; 1003 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1004 m = rt_msg_mbuf(RTM_IFINFO, &rtinfo); 1005 if (m == NULL) 1006 return; 1007 ifm = mtod(m, struct if_msghdr *); 1008 ifm->ifm_index = ifp->if_index; 1009 ifm->ifm_flags = ifp->if_flags; 1010 ifm->ifm_data = ifp->if_data; 1011 ifm->ifm_addrs = 0; 1012 rts_input(m, 0); 1013 } 1014 1015 static void 1016 rt_ifamsg(int cmd, struct ifaddr *ifa) 1017 { 1018 struct ifa_msghdr *ifam; 1019 struct rt_addrinfo rtinfo; 1020 struct mbuf *m; 1021 struct ifnet *ifp = ifa->ifa_ifp; 1022 1023 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1024 rtinfo.rti_ifaaddr = ifa->ifa_addr; 1025 rtinfo.rti_ifpaddr = 1026 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr; 1027 rtinfo.rti_netmask = ifa->ifa_netmask; 1028 rtinfo.rti_bcastaddr = ifa->ifa_dstaddr; 1029 1030 m = rt_msg_mbuf(cmd, &rtinfo); 1031 if (m == NULL) 1032 return; 1033 1034 ifam = mtod(m, struct ifa_msghdr *); 1035 ifam->ifam_index = ifp->if_index; 1036 ifam->ifam_metric = ifa->ifa_metric; 1037 ifam->ifam_flags = ifa->ifa_flags; 1038 ifam->ifam_addrs = rtinfo.rti_addrs; 1039 1040 rts_input(m, familyof(ifa->ifa_addr)); 1041 } 1042 1043 void 1044 rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error) 1045 { 1046 struct rt_msghdr *rtm; 1047 struct rt_addrinfo rtinfo; 1048 struct mbuf *m; 1049 struct sockaddr *dst; 1050 1051 if (rt == NULL) 1052 return; 1053 1054 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1055 rtinfo.rti_dst = dst = rt_key(rt); 1056 rtinfo.rti_gateway = rt->rt_gateway; 1057 rtinfo.rti_netmask = rt_mask(rt); 1058 if (ifp != NULL) { 1059 rtinfo.rti_ifpaddr = 1060 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr; 1061 } 1062 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr; 1063 1064 m = rt_msg_mbuf(cmd, &rtinfo); 1065 if (m == NULL) 1066 return; 1067 1068 rtm = mtod(m, struct rt_msghdr *); 1069 if (ifp != NULL) 1070 rtm->rtm_index = ifp->if_index; 1071 rtm->rtm_flags |= rt->rt_flags; 1072 rtm->rtm_errno = error; 1073 rtm->rtm_addrs = rtinfo.rti_addrs; 1074 1075 rts_input(m, familyof(dst)); 1076 } 1077 1078 /* 1079 * This is called to generate messages from the routing socket 1080 * indicating a network interface has had addresses associated with it. 1081 * if we ever reverse the logic and replace messages TO the routing 1082 * socket indicate a request to configure interfaces, then it will 1083 * be unnecessary as the routing socket will automatically generate 1084 * copies of it. 1085 */ 1086 void 1087 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) 1088 { 1089 if (route_cb.any_count == 0) 1090 return; 1091 1092 if (cmd == RTM_ADD) { 1093 rt_ifamsg(RTM_NEWADDR, ifa); 1094 rt_rtmsg(RTM_ADD, rt, ifa->ifa_ifp, error); 1095 } else { 1096 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd)); 1097 rt_rtmsg(RTM_DELETE, rt, ifa->ifa_ifp, error); 1098 rt_ifamsg(RTM_DELADDR, ifa); 1099 } 1100 } 1101 1102 /* 1103 * This is the analogue to the rt_newaddrmsg which performs the same 1104 * function but for multicast group memberhips. This is easier since 1105 * there is no route state to worry about. 1106 */ 1107 void 1108 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma) 1109 { 1110 struct rt_addrinfo rtinfo; 1111 struct mbuf *m = NULL; 1112 struct ifnet *ifp = ifma->ifma_ifp; 1113 struct ifma_msghdr *ifmam; 1114 1115 if (route_cb.any_count == 0) 1116 return; 1117 1118 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1119 rtinfo.rti_ifaaddr = ifma->ifma_addr; 1120 if (ifp != NULL && !TAILQ_EMPTY(&ifp->if_addrheads[mycpuid])) { 1121 rtinfo.rti_ifpaddr = 1122 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr; 1123 } 1124 /* 1125 * If a link-layer address is present, present it as a ``gateway'' 1126 * (similarly to how ARP entries, e.g., are presented). 1127 */ 1128 rtinfo.rti_gateway = ifma->ifma_lladdr; 1129 1130 m = rt_msg_mbuf(cmd, &rtinfo); 1131 if (m == NULL) 1132 return; 1133 1134 ifmam = mtod(m, struct ifma_msghdr *); 1135 ifmam->ifmam_index = ifp->if_index; 1136 ifmam->ifmam_addrs = rtinfo.rti_addrs; 1137 1138 rts_input(m, familyof(ifma->ifma_addr)); 1139 } 1140 1141 static struct mbuf * 1142 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, 1143 struct rt_addrinfo *info) 1144 { 1145 struct if_announcemsghdr *ifan; 1146 struct mbuf *m; 1147 1148 if (route_cb.any_count == 0) 1149 return NULL; 1150 1151 bzero(info, sizeof(*info)); 1152 m = rt_msg_mbuf(type, info); 1153 if (m == NULL) 1154 return NULL; 1155 1156 ifan = mtod(m, struct if_announcemsghdr *); 1157 ifan->ifan_index = ifp->if_index; 1158 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name); 1159 ifan->ifan_what = what; 1160 return m; 1161 } 1162 1163 /* 1164 * This is called to generate routing socket messages indicating 1165 * IEEE80211 wireless events. 1166 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way. 1167 */ 1168 void 1169 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len) 1170 { 1171 struct rt_addrinfo info; 1172 struct mbuf *m; 1173 1174 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info); 1175 if (m == NULL) 1176 return; 1177 1178 /* 1179 * Append the ieee80211 data. Try to stick it in the 1180 * mbuf containing the ifannounce msg; otherwise allocate 1181 * a new mbuf and append. 1182 * 1183 * NB: we assume m is a single mbuf. 1184 */ 1185 if (data_len > M_TRAILINGSPACE(m)) { 1186 /* XXX use m_getb(data_len, M_NOWAIT, MT_DATA, 0); */ 1187 struct mbuf *n = m_get(M_NOWAIT, MT_DATA); 1188 if (n == NULL) { 1189 m_freem(m); 1190 return; 1191 } 1192 KKASSERT(data_len <= M_TRAILINGSPACE(n)); 1193 bcopy(data, mtod(n, void *), data_len); 1194 n->m_len = data_len; 1195 m->m_next = n; 1196 } else if (data_len > 0) { 1197 bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len); 1198 m->m_len += data_len; 1199 } 1200 mbuftrackid(m, 33); 1201 if (m->m_flags & M_PKTHDR) 1202 m->m_pkthdr.len += data_len; 1203 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len; 1204 rts_input(m, 0); 1205 } 1206 1207 /* 1208 * This is called to generate routing socket messages indicating 1209 * network interface arrival and departure. 1210 */ 1211 void 1212 rt_ifannouncemsg(struct ifnet *ifp, int what) 1213 { 1214 struct rt_addrinfo addrinfo; 1215 struct mbuf *m; 1216 1217 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &addrinfo); 1218 if (m != NULL) 1219 rts_input(m, 0); 1220 } 1221 1222 static int 1223 resizewalkarg(struct walkarg *w, int len) 1224 { 1225 void *newptr; 1226 1227 newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK); 1228 if (newptr == NULL) 1229 return (ENOMEM); 1230 if (w->w_tmem != NULL) 1231 kfree(w->w_tmem, M_RTABLE); 1232 w->w_tmem = newptr; 1233 w->w_tmemsize = len; 1234 return (0); 1235 } 1236 1237 /* 1238 * This is used in dumping the kernel table via sysctl(). 1239 */ 1240 int 1241 sysctl_dumpentry(struct radix_node *rn, void *vw) 1242 { 1243 struct walkarg *w = vw; 1244 struct rtentry *rt = (struct rtentry *)rn; 1245 struct rt_addrinfo rtinfo; 1246 int error, msglen; 1247 1248 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 1249 return 0; 1250 1251 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1252 rtinfo.rti_dst = rt_key(rt); 1253 rtinfo.rti_gateway = rt->rt_gateway; 1254 rtinfo.rti_netmask = rt_mask(rt); 1255 rtinfo.rti_genmask = rt->rt_genmask; 1256 if (rt->rt_ifp != NULL) { 1257 rtinfo.rti_ifpaddr = 1258 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])->ifa->ifa_addr; 1259 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr; 1260 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 1261 rtinfo.rti_bcastaddr = rt->rt_ifa->ifa_dstaddr; 1262 } 1263 msglen = rt_msgsize(RTM_GET, &rtinfo); 1264 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0) 1265 return (ENOMEM); 1266 rt_msg_buffer(RTM_GET, &rtinfo, w->w_tmem, msglen); 1267 if (w->w_req != NULL) { 1268 struct rt_msghdr *rtm = w->w_tmem; 1269 1270 rtm->rtm_flags = rt->rt_flags; 1271 rtm->rtm_use = rt->rt_use; 1272 rtm->rtm_rmx = rt->rt_rmx; 1273 rtm->rtm_index = rt->rt_ifp->if_index; 1274 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 1275 rtm->rtm_addrs = rtinfo.rti_addrs; 1276 error = SYSCTL_OUT(w->w_req, rtm, msglen); 1277 return (error); 1278 } 1279 return (0); 1280 } 1281 1282 static void 1283 ifnet_compute_stats(struct ifnet *ifp) 1284 { 1285 IFNET_STAT_GET(ifp, ipackets, ifp->if_ipackets); 1286 IFNET_STAT_GET(ifp, ierrors, ifp->if_ierrors); 1287 IFNET_STAT_GET(ifp, opackets, ifp->if_opackets); 1288 IFNET_STAT_GET(ifp, collisions, ifp->if_collisions); 1289 IFNET_STAT_GET(ifp, ibytes, ifp->if_ibytes); 1290 IFNET_STAT_GET(ifp, obytes, ifp->if_obytes); 1291 IFNET_STAT_GET(ifp, imcasts, ifp->if_imcasts); 1292 IFNET_STAT_GET(ifp, omcasts, ifp->if_omcasts); 1293 IFNET_STAT_GET(ifp, iqdrops, ifp->if_iqdrops); 1294 IFNET_STAT_GET(ifp, noproto, ifp->if_noproto); 1295 } 1296 1297 static int 1298 sysctl_iflist(int af, struct walkarg *w) 1299 { 1300 struct ifnet *ifp; 1301 struct rt_addrinfo rtinfo; 1302 int msglen, error; 1303 1304 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1305 1306 ifnet_lock(); 1307 TAILQ_FOREACH(ifp, &ifnetlist, if_link) { 1308 struct ifaddr_container *ifac; 1309 struct ifaddr *ifa; 1310 1311 if (w->w_arg && w->w_arg != ifp->if_index) 1312 continue; 1313 ifac = TAILQ_FIRST(&ifp->if_addrheads[mycpuid]); 1314 ifa = ifac->ifa; 1315 rtinfo.rti_ifpaddr = ifa->ifa_addr; 1316 msglen = rt_msgsize(RTM_IFINFO, &rtinfo); 1317 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0) { 1318 ifnet_unlock(); 1319 return (ENOMEM); 1320 } 1321 rt_msg_buffer(RTM_IFINFO, &rtinfo, w->w_tmem, msglen); 1322 rtinfo.rti_ifpaddr = NULL; 1323 if (w->w_req != NULL && w->w_tmem != NULL) { 1324 struct if_msghdr *ifm = w->w_tmem; 1325 1326 ifm->ifm_index = ifp->if_index; 1327 ifm->ifm_flags = ifp->if_flags; 1328 ifnet_compute_stats(ifp); 1329 ifm->ifm_data = ifp->if_data; 1330 ifm->ifm_addrs = rtinfo.rti_addrs; 1331 error = SYSCTL_OUT(w->w_req, ifm, msglen); 1332 if (error) { 1333 ifnet_unlock(); 1334 return (error); 1335 } 1336 } 1337 while ((ifac = TAILQ_NEXT(ifac, ifa_link)) != NULL) { 1338 ifa = ifac->ifa; 1339 1340 if (af && af != ifa->ifa_addr->sa_family) 1341 continue; 1342 if (curproc->p_ucred->cr_prison && 1343 prison_if(curproc->p_ucred, ifa->ifa_addr)) 1344 continue; 1345 rtinfo.rti_ifaaddr = ifa->ifa_addr; 1346 rtinfo.rti_netmask = ifa->ifa_netmask; 1347 rtinfo.rti_bcastaddr = ifa->ifa_dstaddr; 1348 msglen = rt_msgsize(RTM_NEWADDR, &rtinfo); 1349 if (w->w_tmemsize < msglen && 1350 resizewalkarg(w, msglen) != 0) { 1351 ifnet_unlock(); 1352 return (ENOMEM); 1353 } 1354 rt_msg_buffer(RTM_NEWADDR, &rtinfo, w->w_tmem, msglen); 1355 if (w->w_req != NULL) { 1356 struct ifa_msghdr *ifam = w->w_tmem; 1357 1358 ifam->ifam_index = ifa->ifa_ifp->if_index; 1359 ifam->ifam_flags = ifa->ifa_flags; 1360 ifam->ifam_metric = ifa->ifa_metric; 1361 ifam->ifam_addrs = rtinfo.rti_addrs; 1362 error = SYSCTL_OUT(w->w_req, w->w_tmem, msglen); 1363 if (error) { 1364 ifnet_unlock(); 1365 return (error); 1366 } 1367 } 1368 } 1369 rtinfo.rti_netmask = NULL; 1370 rtinfo.rti_ifaaddr = NULL; 1371 rtinfo.rti_bcastaddr = NULL; 1372 } 1373 ifnet_unlock(); 1374 return (0); 1375 } 1376 1377 static int 1378 sysctl_rttable(int af, struct sysctl_req *req, int op, int arg) 1379 { 1380 struct walkarg w; 1381 int i, error = EINVAL; 1382 1383 bzero(&w, sizeof(w)); 1384 w.w_op = op; 1385 w.w_arg = arg; 1386 w.w_req = req; 1387 1388 for (i = 1; i <= AF_MAX; i++) { 1389 struct radix_node_head *rnh; 1390 1391 if ((rnh = rt_tables[mycpuid][i]) && (af == 0 || af == i) && 1392 (error = rnh->rnh_walktree(rnh, sysctl_dumpentry, &w))) 1393 break; 1394 } 1395 1396 if (w.w_tmem != NULL) 1397 kfree(w.w_tmem, M_RTABLE); 1398 1399 return error; 1400 } 1401 1402 static int 1403 sysctl_rtsock(SYSCTL_HANDLER_ARGS) 1404 { 1405 int *name = (int *)arg1; 1406 u_int namelen = arg2; 1407 int error = EINVAL; 1408 int origcpu; 1409 u_char af; 1410 struct walkarg w; 1411 1412 name ++; 1413 namelen--; 1414 if (req->newptr) 1415 return (EPERM); 1416 if (namelen != 3 && namelen != 4) 1417 return (EINVAL); 1418 af = name[0]; 1419 bzero(&w, sizeof w); 1420 w.w_op = name[1]; 1421 w.w_arg = name[2]; 1422 w.w_req = req; 1423 1424 /* 1425 * Optional third argument specifies cpu, used primarily for 1426 * debugging the route table. 1427 */ 1428 if (namelen == 4) { 1429 if (name[3] < 0 || name[3] >= ncpus) 1430 return (EINVAL); 1431 origcpu = mycpuid; 1432 lwkt_migratecpu(name[3]); 1433 } else { 1434 origcpu = -1; 1435 } 1436 1437 switch (w.w_op) { 1438 case NET_RT_DUMP: 1439 case NET_RT_FLAGS: 1440 error = sysctl_rttable(af, w.w_req, w.w_op, w.w_arg); 1441 break; 1442 1443 case NET_RT_IFLIST: 1444 error = sysctl_iflist(af, &w); 1445 break; 1446 } 1447 if (w.w_tmem != NULL) 1448 kfree(w.w_tmem, M_RTABLE); 1449 1450 if (origcpu >= 0) 1451 lwkt_migratecpu(origcpu); 1452 return (error); 1453 } 1454 1455 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, ""); 1456 1457 /* 1458 * Definitions of protocols supported in the ROUTE domain. 1459 */ 1460 1461 static struct domain routedomain; /* or at least forward */ 1462 1463 static struct protosw routesw[] = { 1464 { 1465 .pr_type = SOCK_RAW, 1466 .pr_domain = &routedomain, 1467 .pr_protocol = 0, 1468 .pr_flags = PR_ATOMIC|PR_ADDR, 1469 .pr_input = NULL, 1470 .pr_output = route_output, 1471 .pr_ctlinput = raw_ctlinput, 1472 .pr_ctloutput = NULL, 1473 .pr_ctlport = cpu0_ctlport, 1474 1475 .pr_init = raw_init, 1476 .pr_usrreqs = &route_usrreqs 1477 } 1478 }; 1479 1480 static struct domain routedomain = { 1481 PF_ROUTE, "route", NULL, NULL, NULL, 1482 routesw, &routesw[(sizeof routesw)/(sizeof routesw[0])], 1483 }; 1484 1485 DOMAIN_SET(route); 1486 1487