1 /* $OpenBSD: rtsock.c,v 1.159 2015/05/13 10:42:46 jsg Exp $ */ 2 /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT 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.6 (Berkeley) 2/11/95 62 */ 63 64 #include <sys/param.h> 65 #include <sys/systm.h> 66 #include <sys/proc.h> 67 #include <sys/sysctl.h> 68 #include <sys/mbuf.h> 69 #include <sys/socket.h> 70 #include <sys/socketvar.h> 71 #include <sys/domain.h> 72 #include <sys/protosw.h> 73 74 #include <net/if.h> 75 #include <net/if_var.h> 76 #include <net/route.h> 77 #include <net/raw_cb.h> 78 79 #ifdef MPLS 80 #include <netmpls/mpls.h> 81 #endif 82 83 #include <sys/stdarg.h> 84 #include <sys/kernel.h> 85 #include <sys/timeout.h> 86 87 struct sockaddr route_dst = { 2, PF_ROUTE, }; 88 struct sockaddr route_src = { 2, PF_ROUTE, }; 89 struct sockproto route_proto = { PF_ROUTE, }; 90 91 struct walkarg { 92 int w_op, w_arg, w_given, w_needed, w_tmemsize; 93 caddr_t w_where, w_tmem; 94 }; 95 96 int route_ctloutput(int, struct socket *, int, int, struct mbuf **); 97 void route_input(struct mbuf *m0, ...); 98 99 struct mbuf *rt_msg1(int, struct rt_addrinfo *); 100 int rt_msg2(int, int, struct rt_addrinfo *, caddr_t, 101 struct walkarg *); 102 void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 103 104 struct routecb { 105 struct rawcb rcb; 106 struct timeout timeout; 107 unsigned int msgfilter; 108 unsigned int flags; 109 u_int rtableid; 110 }; 111 #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb) 112 113 struct route_cb { 114 int ip_count; 115 int ip6_count; 116 int mpls_count; 117 int any_count; 118 }; 119 120 struct route_cb route_cb; 121 122 /* 123 * These flags and timeout are used for indicating to userland (via a 124 * RTM_DESYNC msg) when the route socket has overflowed and messages 125 * have been lost. 126 */ 127 #define ROUTECB_FLAG_DESYNC 0x1 /* Route socket out of memory */ 128 #define ROUTECB_FLAG_FLUSH 0x2 /* Wait until socket is empty before 129 queueing more packets */ 130 131 #define ROUTE_DESYNC_RESEND_TIMEOUT (hz / 5) /* In hz */ 132 133 void rt_senddesync(void *); 134 135 int 136 route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 137 struct mbuf *control, struct proc *p) 138 { 139 struct rawcb *rp; 140 struct routecb *rop; 141 int s, af; 142 int error = 0; 143 144 s = splsoftnet(); 145 rp = sotorawcb(so); 146 147 switch (req) { 148 case PRU_ATTACH: 149 /* 150 * use the rawcb but allocate a routecb, this 151 * code does not care about the additional fields 152 * and works directly on the raw socket. 153 */ 154 rop = malloc(sizeof(struct routecb), M_PCB, M_WAITOK|M_ZERO); 155 rp = &rop->rcb; 156 so->so_pcb = rp; 157 /* Init the timeout structure */ 158 timeout_set(&((struct routecb *)rp)->timeout, rt_senddesync, rp); 159 /* 160 * Don't call raw_usrreq() in the attach case, because 161 * we want to allow non-privileged processes to listen 162 * on and send "safe" commands to the routing socket. 163 */ 164 if (curproc == 0) 165 error = EACCES; 166 else 167 error = raw_attach(so, (int)(long)nam); 168 if (error) { 169 free(rp, M_PCB, 0); 170 splx(s); 171 return (error); 172 } 173 rop->rtableid = curproc->p_p->ps_rtableid; 174 af = rp->rcb_proto.sp_protocol; 175 if (af == AF_INET) 176 route_cb.ip_count++; 177 else if (af == AF_INET6) 178 route_cb.ip6_count++; 179 #ifdef MPLS 180 else if (af == AF_MPLS) 181 route_cb.mpls_count++; 182 #endif 183 rp->rcb_faddr = &route_src; 184 route_cb.any_count++; 185 soisconnected(so); 186 so->so_options |= SO_USELOOPBACK; 187 break; 188 189 case PRU_RCVD: 190 rop = (struct routecb *)rp; 191 192 /* 193 * If we are in a FLUSH state, check if the buffer is 194 * empty so that we can clear the flag. 195 */ 196 if (((rop->flags & ROUTECB_FLAG_FLUSH) != 0) && 197 ((sbspace(&rp->rcb_socket->so_rcv) == 198 rp->rcb_socket->so_rcv.sb_hiwat))) 199 rop->flags &= ~ROUTECB_FLAG_FLUSH; 200 break; 201 202 case PRU_DETACH: 203 if (rp) { 204 timeout_del(&((struct routecb *)rp)->timeout); 205 af = rp->rcb_proto.sp_protocol; 206 if (af == AF_INET) 207 route_cb.ip_count--; 208 else if (af == AF_INET6) 209 route_cb.ip6_count--; 210 #ifdef MPLS 211 else if (af == AF_MPLS) 212 route_cb.mpls_count--; 213 #endif 214 route_cb.any_count--; 215 } 216 /* FALLTHROUGH */ 217 default: 218 error = raw_usrreq(so, req, m, nam, control, p); 219 } 220 221 splx(s); 222 return (error); 223 } 224 225 int 226 route_ctloutput(int op, struct socket *so, int level, int optname, 227 struct mbuf **mp) 228 { 229 struct routecb *rop = sotoroutecb(so); 230 struct mbuf *m = *mp; 231 int error = 0; 232 unsigned int tid; 233 234 if (level != AF_ROUTE) { 235 error = EINVAL; 236 if (op == PRCO_SETOPT && *mp) 237 m_free(*mp); 238 return (error); 239 } 240 241 switch (op) { 242 case PRCO_SETOPT: 243 switch (optname) { 244 case ROUTE_MSGFILTER: 245 if (m == NULL || m->m_len != sizeof(unsigned int)) 246 error = EINVAL; 247 else 248 rop->msgfilter = *mtod(m, unsigned int *); 249 break; 250 case ROUTE_TABLEFILTER: 251 if (m == NULL || m->m_len != sizeof(unsigned int)) { 252 error = EINVAL; 253 break; 254 } 255 tid = *mtod(m, unsigned int *); 256 if (tid != RTABLE_ANY && !rtable_exists(tid)) 257 error = ENOENT; 258 else 259 rop->rtableid = tid; 260 break; 261 default: 262 error = ENOPROTOOPT; 263 break; 264 } 265 if (m) 266 m_free(m); 267 break; 268 case PRCO_GETOPT: 269 switch (optname) { 270 case ROUTE_MSGFILTER: 271 *mp = m = m_get(M_WAIT, MT_SOOPTS); 272 m->m_len = sizeof(unsigned int); 273 *mtod(m, unsigned int *) = rop->msgfilter; 274 break; 275 case ROUTE_TABLEFILTER: 276 *mp = m = m_get(M_WAIT, MT_SOOPTS); 277 m->m_len = sizeof(unsigned int); 278 *mtod(m, unsigned int *) = rop->rtableid; 279 break; 280 default: 281 error = ENOPROTOOPT; 282 break; 283 } 284 } 285 return (error); 286 } 287 288 void 289 rt_senddesync(void *data) 290 { 291 struct rawcb *rp; 292 struct routecb *rop; 293 struct mbuf *desync_mbuf; 294 295 rp = (struct rawcb *)data; 296 rop = (struct routecb *)rp; 297 298 /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */ 299 if ((rop->flags & ROUTECB_FLAG_DESYNC) != 0) { 300 /* 301 * If we fail to alloc memory or if sbappendaddr() 302 * fails, re-add timeout and try again. 303 */ 304 desync_mbuf = rt_msg1(RTM_DESYNC, NULL); 305 if ((desync_mbuf != NULL) && 306 (sbappendaddr(&rp->rcb_socket->so_rcv, &route_src, 307 desync_mbuf, (struct mbuf *)NULL) != 0)) { 308 rop->flags &= ~ROUTECB_FLAG_DESYNC; 309 sorwakeup(rp->rcb_socket); 310 } else { 311 if (desync_mbuf) 312 m_freem(desync_mbuf); 313 /* Re-add timeout to try sending msg again */ 314 timeout_add(&rop->timeout, ROUTE_DESYNC_RESEND_TIMEOUT); 315 } 316 } 317 } 318 319 void 320 route_input(struct mbuf *m0, ...) 321 { 322 struct rawcb *rp; 323 struct routecb *rop; 324 struct rt_msghdr *rtm; 325 struct mbuf *m = m0; 326 int sockets = 0; 327 struct socket *last = NULL; 328 va_list ap; 329 struct sockproto *proto; 330 struct sockaddr *sosrc, *sodst; 331 332 va_start(ap, m0); 333 proto = va_arg(ap, struct sockproto *); 334 sosrc = va_arg(ap, struct sockaddr *); 335 sodst = va_arg(ap, struct sockaddr *); 336 va_end(ap); 337 338 /* ensure that we can access the rtm_type via mtod() */ 339 if (m->m_len < offsetof(struct rt_msghdr, rtm_type) + 1) { 340 m_freem(m); 341 return; 342 } 343 344 LIST_FOREACH(rp, &rawcb, rcb_list) { 345 if (rp->rcb_socket->so_state & SS_CANTRCVMORE) 346 continue; 347 if (rp->rcb_proto.sp_family != proto->sp_family) 348 continue; 349 if (rp->rcb_proto.sp_protocol && proto->sp_protocol && 350 rp->rcb_proto.sp_protocol != proto->sp_protocol) 351 continue; 352 /* 353 * We assume the lower level routines have 354 * placed the address in a canonical format 355 * suitable for a structure comparison. 356 * 357 * Note that if the lengths are not the same 358 * the comparison will fail at the first byte. 359 */ 360 #define equal(a1, a2) \ 361 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 362 if (rp->rcb_laddr && !equal(rp->rcb_laddr, sodst)) 363 continue; 364 if (rp->rcb_faddr && !equal(rp->rcb_faddr, sosrc)) 365 continue; 366 367 /* filter messages that the process does not want */ 368 rop = (struct routecb *)rp; 369 rtm = mtod(m, struct rt_msghdr *); 370 /* but RTM_DESYNC can't be filtered */ 371 if (rtm->rtm_type != RTM_DESYNC && rop->msgfilter != 0 && 372 !(rop->msgfilter & (1 << rtm->rtm_type))) 373 continue; 374 switch (rtm->rtm_type) { 375 case RTM_IFANNOUNCE: 376 case RTM_DESYNC: 377 /* no tableid */ 378 break; 379 case RTM_RESOLVE: 380 case RTM_NEWADDR: 381 case RTM_DELADDR: 382 case RTM_IFINFO: 383 /* check against rdomain id */ 384 if (rop->rtableid != RTABLE_ANY && 385 rtable_l2(rop->rtableid) != rtm->rtm_tableid) 386 continue; 387 break; 388 default: 389 /* check against rtable id */ 390 if (rop->rtableid != RTABLE_ANY && 391 rop->rtableid != rtm->rtm_tableid) 392 continue; 393 break; 394 } 395 396 /* 397 * Check to see if the flush flag is set. If so, don't queue 398 * any more messages until the flag is cleared. 399 */ 400 if ((rop->flags & ROUTECB_FLAG_FLUSH) != 0) 401 continue; 402 403 if (last) { 404 struct mbuf *n; 405 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 406 if (sbspace(&last->so_rcv) < (2 * MSIZE) || 407 sbappendaddr(&last->so_rcv, sosrc, 408 n, (struct mbuf *)NULL) == 0) { 409 /* 410 * Flag socket as desync'ed and 411 * flush required 412 */ 413 sotoroutecb(last)->flags |= 414 ROUTECB_FLAG_DESYNC | 415 ROUTECB_FLAG_FLUSH; 416 rt_senddesync((void *) sotorawcb(last)); 417 m_freem(n); 418 } else { 419 sorwakeup(last); 420 sockets++; 421 } 422 } 423 } 424 last = rp->rcb_socket; 425 } 426 if (last) { 427 if (sbspace(&last->so_rcv) < (2 * MSIZE) || 428 sbappendaddr(&last->so_rcv, sosrc, 429 m, (struct mbuf *)NULL) == 0) { 430 /* Flag socket as desync'ed and flush required */ 431 sotoroutecb(last)->flags |= 432 ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH; 433 rt_senddesync((void *) sotorawcb(last)); 434 m_freem(m); 435 } else { 436 sorwakeup(last); 437 sockets++; 438 } 439 } else 440 m_freem(m); 441 } 442 443 int 444 route_output(struct mbuf *m, ...) 445 { 446 struct rt_msghdr *rtm = NULL; 447 struct radix_node *rn = NULL; 448 struct rtentry *rt = NULL; 449 struct rtentry *saved_nrt = NULL; 450 struct radix_node_head *rnh; 451 struct rt_addrinfo info; 452 int len, newgate, error = 0; 453 struct ifnet *ifp = NULL; 454 struct ifaddr *ifa = NULL; 455 struct socket *so; 456 struct rawcb *rp = NULL; 457 struct sockaddr_rtlabel sa_rl; 458 #ifdef MPLS 459 struct sockaddr_mpls sa_mpls, *psa_mpls; 460 #endif 461 va_list ap; 462 u_int tableid; 463 u_int8_t prio; 464 u_char vers; 465 466 va_start(ap, m); 467 so = va_arg(ap, struct socket *); 468 va_end(ap); 469 470 info.rti_info[RTAX_DST] = NULL; /* for error handling (goto flush) */ 471 if (m == NULL || ((m->m_len < sizeof(int32_t)) && 472 (m = m_pullup(m, sizeof(int32_t))) == 0)) 473 return (ENOBUFS); 474 if ((m->m_flags & M_PKTHDR) == 0) 475 panic("route_output"); 476 len = m->m_pkthdr.len; 477 if (len < offsetof(struct rt_msghdr, rtm_type) + 1 || 478 len != mtod(m, struct rt_msghdr *)->rtm_msglen) { 479 error = EINVAL; 480 goto fail; 481 } 482 vers = mtod(m, struct rt_msghdr *)->rtm_version; 483 switch (vers) { 484 case RTM_VERSION: 485 if (len < sizeof(struct rt_msghdr)) { 486 error = EINVAL; 487 goto fail; 488 } 489 if (len > RTM_MAXSIZE) { 490 error = EMSGSIZE; 491 goto fail; 492 } 493 rtm = malloc(len, M_RTABLE, M_NOWAIT); 494 if (rtm == NULL) { 495 error = ENOBUFS; 496 goto fail; 497 } 498 m_copydata(m, 0, len, (caddr_t)rtm); 499 break; 500 default: 501 error = EPROTONOSUPPORT; 502 goto fail; 503 } 504 rtm->rtm_pid = curproc->p_p->ps_pid; 505 if (rtm->rtm_hdrlen == 0) /* old client */ 506 rtm->rtm_hdrlen = sizeof(struct rt_msghdr); 507 if (len < rtm->rtm_hdrlen) { 508 error = EINVAL; 509 goto fail; 510 } 511 512 /* Verify that the caller is sending an appropriate message early */ 513 switch (rtm->rtm_type) { 514 case RTM_ADD: 515 case RTM_DELETE: 516 case RTM_GET: 517 case RTM_CHANGE: 518 case RTM_LOCK: 519 break; 520 default: 521 error = EOPNOTSUPP; 522 goto fail; 523 } 524 525 /* 526 * Verify that the caller has the appropriate privilege; RTM_GET 527 * is the only operation the non-superuser is allowed. 528 */ 529 if (rtm->rtm_type != RTM_GET && suser(curproc, 0) != 0) { 530 error = EACCES; 531 goto fail; 532 } 533 534 tableid = rtm->rtm_tableid; 535 if (!rtable_exists(tableid)) { 536 if (rtm->rtm_type == RTM_ADD) { 537 if ((error = rtable_add(tableid)) != 0) 538 goto flush; 539 } else { 540 error = EINVAL; 541 goto flush; 542 } 543 } 544 545 546 /* Do not let userland play with kernel-only flags. */ 547 if ((rtm->rtm_flags & (RTF_LOCAL|RTF_BROADCAST)) != 0) { 548 error = EINVAL; 549 goto fail; 550 } 551 552 /* make sure that kernel-only bits are not set */ 553 rtm->rtm_priority &= RTP_MASK; 554 rtm->rtm_flags &= ~(RTF_DONE|RTF_CLONED); 555 rtm->rtm_fmask &= RTF_FMASK; 556 557 if (rtm->rtm_priority != 0) { 558 if (rtm->rtm_priority > RTP_MAX || 559 rtm->rtm_priority == RTP_LOCAL) { 560 error = EINVAL; 561 goto fail; 562 } 563 prio = rtm->rtm_priority; 564 } else if (rtm->rtm_type != RTM_ADD) 565 prio = RTP_ANY; 566 else if (rtm->rtm_flags & RTF_STATIC) 567 prio = 0; 568 else 569 prio = RTP_DEFAULT; 570 571 bzero(&info, sizeof(info)); 572 info.rti_addrs = rtm->rtm_addrs; 573 rt_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm, len + (caddr_t)rtm, &info); 574 info.rti_flags = rtm->rtm_flags; 575 if (info.rti_info[RTAX_DST] == NULL || 576 info.rti_info[RTAX_DST]->sa_family >= AF_MAX || 577 (info.rti_info[RTAX_GATEWAY] != NULL && 578 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX) || 579 info.rti_info[RTAX_GENMASK] != NULL) { 580 error = EINVAL; 581 goto flush; 582 } 583 #ifdef MPLS 584 info.rti_mpls = rtm->rtm_mpls; 585 #endif 586 587 if (info.rti_info[RTAX_GATEWAY] != NULL && 588 info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK && 589 (info.rti_flags & RTF_CLONING) == 0) { 590 info.rti_flags |= RTF_LLINFO; 591 } 592 593 switch (rtm->rtm_type) { 594 case RTM_ADD: 595 if (info.rti_info[RTAX_GATEWAY] == NULL) { 596 error = EINVAL; 597 goto flush; 598 } 599 error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt, 600 tableid); 601 if (error == 0 && saved_nrt) { 602 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 603 &saved_nrt->rt_rmx); 604 saved_nrt->rt_refcnt--; 605 /* write back the priority the kernel used */ 606 rtm->rtm_priority = saved_nrt->rt_priority & RTP_MASK; 607 rtm->rtm_index = saved_nrt->rt_ifp->if_index; 608 rtm->rtm_flags = saved_nrt->rt_flags; 609 } 610 break; 611 case RTM_DELETE: 612 error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt, 613 tableid); 614 if (error == 0) { 615 (rt = saved_nrt)->rt_refcnt++; 616 goto report; 617 } 618 break; 619 case RTM_GET: 620 case RTM_CHANGE: 621 case RTM_LOCK: 622 rnh = rtable_get(tableid, info.rti_info[RTAX_DST]->sa_family); 623 if (rnh == NULL) { 624 error = EAFNOSUPPORT; 625 goto flush; 626 } 627 rt = rt_lookup(info.rti_info[RTAX_DST], 628 info.rti_info[RTAX_NETMASK], tableid); 629 rn = (struct radix_node *)rt; 630 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) { 631 error = ESRCH; 632 rt = NULL; 633 goto flush; 634 } 635 #ifndef SMALL_KERNEL 636 if (rn_mpath_capable(rnh)) { 637 /* first find the right priority */ 638 rt = rt_mpath_matchgate(rt, NULL, prio); 639 if (!rt) { 640 error = ESRCH; 641 goto flush; 642 } 643 /* 644 * For RTM_CHANGE/LOCK, if we got multipath routes, 645 * a matching RTAX_GATEWAY is required. 646 * OR 647 * If a gateway is specified then RTM_GET and 648 * RTM_LOCK must match the gateway no matter 649 * what even in the non multipath case. 650 */ 651 if ((rt->rt_flags & RTF_MPATH) || 652 (info.rti_info[RTAX_GATEWAY] && rtm->rtm_type != 653 RTM_CHANGE)) { 654 rt = rt_mpath_matchgate(rt, 655 info.rti_info[RTAX_GATEWAY], prio); 656 if (!rt) { 657 error = ESRCH; 658 goto flush; 659 } 660 /* 661 * only RTM_GET may use an empty gateway 662 * on multipath routes 663 */ 664 if (!info.rti_info[RTAX_GATEWAY] && 665 rtm->rtm_type != RTM_GET) { 666 rt = NULL; 667 error = ESRCH; 668 goto flush; 669 } 670 } 671 rn = (struct radix_node *)rt; 672 } 673 #endif 674 rt->rt_refcnt++; 675 676 /* 677 * RTM_CHANGE/LOCK need a perfect match, rn_lookup() 678 * returns a perfect match in case a netmask is specified. 679 * For host routes only a longest prefix match is returned 680 * so it is necessary to compare the existence of the netmaks. 681 * If both have a netmask rn_lookup() did a perfect match and 682 * if none of them have a netmask both are host routes which is 683 * also a perfect match. 684 */ 685 if (rtm->rtm_type != RTM_GET && 686 !rt_mask(rt) != !info.rti_info[RTAX_NETMASK]) { 687 error = ESRCH; 688 goto flush; 689 } 690 691 switch (rtm->rtm_type) { 692 case RTM_GET: 693 report: 694 info.rti_info[RTAX_DST] = rt_key(rt); 695 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 696 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 697 info.rti_info[RTAX_LABEL] = 698 rtlabel_id2sa(rt->rt_labelid, &sa_rl); 699 #ifdef MPLS 700 if (rt->rt_flags & RTF_MPLS) { 701 bzero(&sa_mpls, sizeof(sa_mpls)); 702 sa_mpls.smpls_family = AF_MPLS; 703 sa_mpls.smpls_len = sizeof(sa_mpls); 704 sa_mpls.smpls_label = ((struct rt_mpls *) 705 rt->rt_llinfo)->mpls_label; 706 info.rti_info[RTAX_SRC] = 707 (struct sockaddr *)&sa_mpls; 708 info.rti_mpls = ((struct rt_mpls *) 709 rt->rt_llinfo)->mpls_operation; 710 rtm->rtm_mpls = info.rti_mpls; 711 } 712 #endif 713 info.rti_info[RTAX_IFP] = NULL; 714 info.rti_info[RTAX_IFA] = NULL; 715 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA) && 716 (ifp = rt->rt_ifp) != NULL) { 717 info.rti_info[RTAX_IFP] = 718 (struct sockaddr *)ifp->if_sadl; 719 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 720 if (ifp->if_flags & IFF_POINTOPOINT) 721 info.rti_info[RTAX_BRD] = 722 rt->rt_ifa->ifa_dstaddr; 723 else 724 info.rti_info[RTAX_BRD] = NULL; 725 rtm->rtm_index = ifp->if_index; 726 } 727 len = rt_msg2(rtm->rtm_type, RTM_VERSION, &info, NULL, 728 NULL); 729 if (len > rtm->rtm_msglen) { 730 struct rt_msghdr *new_rtm; 731 new_rtm = malloc(len, M_RTABLE, M_NOWAIT); 732 if (new_rtm == NULL) { 733 error = ENOBUFS; 734 goto flush; 735 } 736 memcpy(new_rtm, rtm, rtm->rtm_msglen); 737 free(rtm, M_RTABLE, 0); 738 rtm = new_rtm; 739 } 740 rt_msg2(rtm->rtm_type, RTM_VERSION, &info, (caddr_t)rtm, 741 NULL); 742 rtm->rtm_flags = rt->rt_flags; 743 rtm->rtm_use = 0; 744 rtm->rtm_priority = rt->rt_priority & RTP_MASK; 745 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx); 746 rtm->rtm_addrs = info.rti_addrs; 747 break; 748 749 case RTM_CHANGE: 750 newgate = 0; 751 if (info.rti_info[RTAX_GATEWAY] != NULL) 752 if (rt->rt_gateway == NULL || 753 bcmp(rt->rt_gateway, 754 info.rti_info[RTAX_GATEWAY], 755 info.rti_info[RTAX_GATEWAY]->sa_len)) { 756 newgate = 1; 757 } 758 if (info.rti_info[RTAX_GATEWAY] != NULL && 759 (error = rt_setgate(rt, info.rti_info[RTAX_GATEWAY], 760 tableid))) 761 goto flush; 762 /* 763 * new gateway could require new ifaddr, ifp; 764 * flags may also be different; ifp may be specified 765 * by ll sockaddr when protocol address is ambiguous 766 */ 767 if (newgate || info.rti_info[RTAX_IFP] != NULL || 768 info.rti_info[RTAX_IFA] != NULL) { 769 if ((error = rt_getifa(&info, tableid)) != 0) 770 goto flush; 771 ifa = info.rti_ifa; 772 } 773 if (ifa) { 774 if (rt->rt_ifa != ifa) { 775 if (rt->rt_ifa->ifa_rtrequest) 776 rt->rt_ifa->ifa_rtrequest( 777 RTM_DELETE, rt); 778 ifafree(rt->rt_ifa); 779 rt->rt_ifa = ifa; 780 ifa->ifa_refcnt++; 781 rt->rt_ifp = ifa->ifa_ifp; 782 #ifndef SMALL_KERNEL 783 /* recheck link state after ifp change*/ 784 rt_if_linkstate_change( 785 (struct radix_node *)rt, rt->rt_ifp, 786 tableid); 787 #endif 788 } 789 } 790 #ifdef MPLS 791 if ((rtm->rtm_flags & RTF_MPLS) && 792 info.rti_info[RTAX_SRC] != NULL) { 793 struct rt_mpls *rt_mpls; 794 795 psa_mpls = (struct sockaddr_mpls *) 796 info.rti_info[RTAX_SRC]; 797 798 if (rt->rt_llinfo == NULL) { 799 rt->rt_llinfo = 800 malloc(sizeof(struct rt_mpls), 801 M_TEMP, M_NOWAIT|M_ZERO); 802 } 803 if (rt->rt_llinfo == NULL) { 804 error = ENOMEM; 805 goto flush; 806 } 807 808 rt_mpls = (struct rt_mpls *)rt->rt_llinfo; 809 810 if (psa_mpls != NULL) { 811 rt_mpls->mpls_label = 812 psa_mpls->smpls_label; 813 } 814 815 rt_mpls->mpls_operation = info.rti_mpls; 816 817 /* XXX: set experimental bits */ 818 819 rt->rt_flags |= RTF_MPLS; 820 } else if (newgate || ((rtm->rtm_fmask & RTF_MPLS) && 821 !(rtm->rtm_flags & RTF_MPLS))) { 822 /* if gateway changed remove MPLS information */ 823 if (rt->rt_llinfo != NULL && 824 rt->rt_flags & RTF_MPLS) { 825 free(rt->rt_llinfo, M_TEMP, 0); 826 rt->rt_llinfo = NULL; 827 rt->rt_flags &= ~RTF_MPLS; 828 } 829 } 830 #endif 831 /* Hack to allow some flags to be toggled */ 832 if (rtm->rtm_fmask) 833 rt->rt_flags = 834 (rt->rt_flags & ~rtm->rtm_fmask) | 835 (rtm->rtm_flags & rtm->rtm_fmask); 836 837 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 838 &rt->rt_rmx); 839 rtm->rtm_index = rt->rt_ifp->if_index; 840 rtm->rtm_priority = rt->rt_priority & RTP_MASK; 841 rtm->rtm_flags = rt->rt_flags; 842 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 843 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt); 844 if (info.rti_info[RTAX_LABEL] != NULL) { 845 char *rtlabel = ((struct sockaddr_rtlabel *) 846 info.rti_info[RTAX_LABEL])->sr_label; 847 rtlabel_unref(rt->rt_labelid); 848 rt->rt_labelid = 849 rtlabel_name2id(rtlabel); 850 } 851 if_group_routechange(info.rti_info[RTAX_DST], 852 info.rti_info[RTAX_NETMASK]); 853 /* FALLTHROUGH */ 854 case RTM_LOCK: 855 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 856 rt->rt_rmx.rmx_locks |= 857 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 858 rtm->rtm_priority = rt->rt_priority & RTP_MASK; 859 break; 860 } 861 break; 862 } 863 864 flush: 865 if (rtm) { 866 if (error) 867 rtm->rtm_errno = error; 868 else { 869 rtm->rtm_flags |= RTF_DONE; 870 } 871 } 872 if (info.rti_info[RTAX_DST]) 873 route_proto.sp_protocol = info.rti_info[RTAX_DST]->sa_family; 874 if (rt) 875 rtfree(rt); 876 877 /* 878 * Check to see if we don't want our own messages. 879 */ 880 if (!(so->so_options & SO_USELOOPBACK)) { 881 if (route_cb.any_count <= 1) { 882 fail: 883 free(rtm, M_RTABLE, 0); 884 m_freem(m); 885 return (error); 886 } 887 /* There is another listener, so construct message */ 888 rp = sotorawcb(so); 889 } 890 if (rp) 891 rp->rcb_proto.sp_family = 0; /* Avoid us */ 892 if (rtm) { 893 if (m_copyback(m, 0, rtm->rtm_msglen, rtm, M_NOWAIT)) { 894 m_freem(m); 895 m = NULL; 896 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 897 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 898 free(rtm, M_RTABLE, 0); 899 } 900 if (m) 901 route_input(m, &route_proto, &route_src, &route_dst); 902 if (rp) 903 rp->rcb_proto.sp_family = PF_ROUTE; 904 905 return (error); 906 } 907 908 void 909 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_kmetrics *out) 910 { 911 if (which & RTV_MTU) 912 out->rmx_mtu = in->rmx_mtu; 913 if (which & RTV_EXPIRE) 914 out->rmx_expire = in->rmx_expire; 915 /* RTV_PRIORITY handled before */ 916 } 917 918 void 919 rt_getmetrics(struct rt_kmetrics *in, struct rt_metrics *out) 920 { 921 bzero(out, sizeof(*out)); 922 out->rmx_locks = in->rmx_locks; 923 out->rmx_mtu = in->rmx_mtu; 924 out->rmx_expire = in->rmx_expire; 925 out->rmx_pksent = in->rmx_pksent; 926 } 927 928 #define ROUNDUP(a) \ 929 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 930 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 931 932 void 933 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 934 { 935 struct sockaddr *sa; 936 int i; 937 938 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 939 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 940 if ((rtinfo->rti_addrs & (1 << i)) == 0) 941 continue; 942 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 943 ADVANCE(cp, sa); 944 } 945 } 946 947 struct mbuf * 948 rt_msg1(int type, struct rt_addrinfo *rtinfo) 949 { 950 struct rt_msghdr *rtm; 951 struct mbuf *m; 952 int i; 953 struct sockaddr *sa; 954 int len, dlen, hlen; 955 956 switch (type) { 957 case RTM_DELADDR: 958 case RTM_NEWADDR: 959 len = sizeof(struct ifa_msghdr); 960 break; 961 case RTM_IFINFO: 962 len = sizeof(struct if_msghdr); 963 break; 964 case RTM_IFANNOUNCE: 965 len = sizeof(struct if_announcemsghdr); 966 break; 967 default: 968 len = sizeof(struct rt_msghdr); 969 break; 970 } 971 if (len > MCLBYTES) 972 panic("rt_msg1"); 973 m = m_gethdr(M_DONTWAIT, MT_DATA); 974 if (m && len > MHLEN) { 975 MCLGET(m, M_DONTWAIT); 976 if ((m->m_flags & M_EXT) == 0) { 977 m_free(m); 978 m = NULL; 979 } 980 } 981 if (m == NULL) 982 return (m); 983 m->m_pkthdr.len = m->m_len = hlen = len; 984 m->m_pkthdr.rcvif = NULL; 985 rtm = mtod(m, struct rt_msghdr *); 986 bzero(rtm, len); 987 for (i = 0; i < RTAX_MAX; i++) { 988 if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL) 989 continue; 990 rtinfo->rti_addrs |= (1 << i); 991 dlen = ROUNDUP(sa->sa_len); 992 if (m_copyback(m, len, dlen, sa, M_NOWAIT)) { 993 m_freem(m); 994 return (NULL); 995 } 996 len += dlen; 997 } 998 rtm->rtm_msglen = len; 999 rtm->rtm_hdrlen = hlen; 1000 rtm->rtm_version = RTM_VERSION; 1001 rtm->rtm_type = type; 1002 return (m); 1003 } 1004 1005 int 1006 rt_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp, 1007 struct walkarg *w) 1008 { 1009 int i; 1010 int len, dlen, hlen, second_time = 0; 1011 caddr_t cp0; 1012 1013 rtinfo->rti_addrs = 0; 1014 again: 1015 switch (type) { 1016 case RTM_DELADDR: 1017 case RTM_NEWADDR: 1018 len = sizeof(struct ifa_msghdr); 1019 break; 1020 case RTM_IFINFO: 1021 len = sizeof(struct if_msghdr); 1022 break; 1023 default: 1024 len = sizeof(struct rt_msghdr); 1025 break; 1026 } 1027 hlen = len; 1028 if ((cp0 = cp) != NULL) 1029 cp += len; 1030 for (i = 0; i < RTAX_MAX; i++) { 1031 struct sockaddr *sa; 1032 1033 if ((sa = rtinfo->rti_info[i]) == NULL) 1034 continue; 1035 rtinfo->rti_addrs |= (1 << i); 1036 dlen = ROUNDUP(sa->sa_len); 1037 if (cp) { 1038 bcopy(sa, cp, (size_t)dlen); 1039 cp += dlen; 1040 } 1041 len += dlen; 1042 } 1043 /* align message length to the next natural boundary */ 1044 len = ALIGN(len); 1045 if (cp == 0 && w != NULL && !second_time) { 1046 struct walkarg *rw = w; 1047 1048 rw->w_needed += len; 1049 if (rw->w_needed <= 0 && rw->w_where) { 1050 if (rw->w_tmemsize < len) { 1051 free(rw->w_tmem, M_RTABLE, 0); 1052 rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT); 1053 if (rw->w_tmem) 1054 rw->w_tmemsize = len; 1055 } 1056 if (rw->w_tmem) { 1057 cp = rw->w_tmem; 1058 second_time = 1; 1059 goto again; 1060 } else 1061 rw->w_where = 0; 1062 } 1063 } 1064 if (cp && w) /* clear the message header */ 1065 bzero(cp0, hlen); 1066 1067 if (cp) { 1068 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 1069 1070 rtm->rtm_version = RTM_VERSION; 1071 rtm->rtm_type = type; 1072 rtm->rtm_msglen = len; 1073 rtm->rtm_hdrlen = hlen; 1074 } 1075 return (len); 1076 } 1077 1078 /* 1079 * This routine is called to generate a message from the routing 1080 * socket indicating that a redirect has occurred, a routing lookup 1081 * has failed, or that a protocol has detected timeouts to a particular 1082 * destination. 1083 */ 1084 void 1085 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, 1086 struct ifnet *ifp, int error, u_int tableid) 1087 { 1088 struct rt_msghdr *rtm; 1089 struct mbuf *m; 1090 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 1091 1092 if (route_cb.any_count == 0) 1093 return; 1094 m = rt_msg1(type, rtinfo); 1095 if (m == NULL) 1096 return; 1097 rtm = mtod(m, struct rt_msghdr *); 1098 rtm->rtm_flags = RTF_DONE | flags; 1099 rtm->rtm_errno = error; 1100 rtm->rtm_tableid = tableid; 1101 rtm->rtm_addrs = rtinfo->rti_addrs; 1102 if (ifp != NULL) 1103 rtm->rtm_index = ifp->if_index; 1104 if (sa == NULL) 1105 route_proto.sp_protocol = 0; 1106 else 1107 route_proto.sp_protocol = sa->sa_family; 1108 route_input(m, &route_proto, &route_src, &route_dst); 1109 } 1110 1111 /* 1112 * This routine is called to generate a message from the routing 1113 * socket indicating that the status of a network interface has changed. 1114 */ 1115 void 1116 rt_ifmsg(struct ifnet *ifp) 1117 { 1118 struct if_msghdr *ifm; 1119 struct mbuf *m; 1120 1121 if (route_cb.any_count == 0) 1122 return; 1123 m = rt_msg1(RTM_IFINFO, NULL); 1124 if (m == NULL) 1125 return; 1126 ifm = mtod(m, struct if_msghdr *); 1127 ifm->ifm_index = ifp->if_index; 1128 ifm->ifm_tableid = ifp->if_rdomain; 1129 ifm->ifm_flags = ifp->if_flags; 1130 ifm->ifm_xflags = ifp->if_xflags; 1131 ifm->ifm_data = ifp->if_data; 1132 ifm->ifm_addrs = 0; 1133 route_proto.sp_protocol = 0; 1134 route_input(m, &route_proto, &route_src, &route_dst); 1135 } 1136 1137 /* 1138 * This is called to generate messages from the routing socket 1139 * indicating a network interface has had addresses associated with it. 1140 * if we ever reverse the logic and replace messages TO the routing 1141 * socket indicate a request to configure interfaces, then it will 1142 * be unnecessary as the routing socket will automatically generate 1143 * copies of it. 1144 */ 1145 void 1146 rt_sendaddrmsg(struct rtentry *rt, int cmd) 1147 { 1148 struct ifaddr *ifa = rt->rt_ifa; 1149 struct ifnet *ifp = ifa->ifa_ifp; 1150 struct mbuf *m = NULL; 1151 struct rt_addrinfo info; 1152 struct ifa_msghdr *ifam; 1153 1154 if (route_cb.any_count == 0) 1155 return; 1156 1157 memset(&info, 0, sizeof(info)); 1158 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1159 info.rti_info[RTAX_IFP] = (struct sockaddr *)ifp->if_sadl; 1160 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1161 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1162 if ((m = rt_msg1(cmd, &info)) == NULL) 1163 return; 1164 ifam = mtod(m, struct ifa_msghdr *); 1165 ifam->ifam_index = ifp->if_index; 1166 ifam->ifam_metric = ifa->ifa_metric; 1167 ifam->ifam_flags = ifa->ifa_flags; 1168 ifam->ifam_addrs = info.rti_addrs; 1169 ifam->ifam_tableid = ifp->if_rdomain; 1170 1171 if (ifa->ifa_addr == NULL) 1172 route_proto.sp_protocol = 0; 1173 else 1174 route_proto.sp_protocol = ifa->ifa_addr->sa_family; 1175 route_input(m, &route_proto, &route_src, &route_dst); 1176 } 1177 1178 /* 1179 * This is called to generate routing socket messages indicating 1180 * network interface arrival and departure. 1181 */ 1182 void 1183 rt_ifannouncemsg(struct ifnet *ifp, int what) 1184 { 1185 struct if_announcemsghdr *ifan; 1186 struct mbuf *m; 1187 1188 if (route_cb.any_count == 0) 1189 return; 1190 m = rt_msg1(RTM_IFANNOUNCE, NULL); 1191 if (m == NULL) 1192 return; 1193 ifan = mtod(m, struct if_announcemsghdr *); 1194 ifan->ifan_index = ifp->if_index; 1195 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name)); 1196 ifan->ifan_what = what; 1197 route_proto.sp_protocol = 0; 1198 route_input(m, &route_proto, &route_src, &route_dst); 1199 } 1200 1201 /* 1202 * This is used in dumping the kernel table via sysctl(). 1203 */ 1204 int 1205 sysctl_dumpentry(struct radix_node *rn, void *v, u_int id) 1206 { 1207 struct walkarg *w = v; 1208 struct rtentry *rt = (struct rtentry *)rn; 1209 int error = 0, size; 1210 struct rt_addrinfo info; 1211 #ifdef MPLS 1212 struct sockaddr_mpls sa_mpls; 1213 #endif 1214 struct sockaddr_rtlabel sa_rl; 1215 1216 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 1217 return 0; 1218 bzero(&info, sizeof(info)); 1219 info.rti_info[RTAX_DST] = rt_key(rt); 1220 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1221 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1222 if (rt->rt_ifp) { 1223 info.rti_info[RTAX_IFP] = 1224 (struct sockaddr *)rt->rt_ifp->if_sadl; 1225 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 1226 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 1227 info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; 1228 } 1229 info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); 1230 #ifdef MPLS 1231 if (rt->rt_flags & RTF_MPLS) { 1232 bzero(&sa_mpls, sizeof(sa_mpls)); 1233 sa_mpls.smpls_family = AF_MPLS; 1234 sa_mpls.smpls_len = sizeof(sa_mpls); 1235 sa_mpls.smpls_label = ((struct rt_mpls *) 1236 rt->rt_llinfo)->mpls_label; 1237 info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls; 1238 info.rti_mpls = ((struct rt_mpls *) 1239 rt->rt_llinfo)->mpls_operation; 1240 } 1241 #endif 1242 1243 size = rt_msg2(RTM_GET, RTM_VERSION, &info, NULL, w); 1244 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1245 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 1246 1247 rtm->rtm_flags = rt->rt_flags; 1248 rtm->rtm_priority = rt->rt_priority & RTP_MASK; 1249 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx); 1250 rtm->rtm_rmx.rmx_refcnt = rt->rt_refcnt; 1251 rtm->rtm_index = rt->rt_ifp->if_index; 1252 rtm->rtm_addrs = info.rti_addrs; 1253 rtm->rtm_tableid = id; 1254 #ifdef MPLS 1255 rtm->rtm_mpls = info.rti_mpls; 1256 #endif 1257 if ((error = copyout(rtm, w->w_where, size)) != 0) 1258 w->w_where = NULL; 1259 else 1260 w->w_where += size; 1261 } 1262 return (error); 1263 } 1264 1265 int 1266 sysctl_iflist(int af, struct walkarg *w) 1267 { 1268 struct ifnet *ifp; 1269 struct ifaddr *ifa; 1270 struct rt_addrinfo info; 1271 int len, error = 0; 1272 1273 bzero(&info, sizeof(info)); 1274 TAILQ_FOREACH(ifp, &ifnet, if_list) { 1275 if (w->w_arg && w->w_arg != ifp->if_index) 1276 continue; 1277 /* Copy the link-layer address first */ 1278 info.rti_info[RTAX_IFP] = (struct sockaddr *)ifp->if_sadl; 1279 len = rt_msg2(RTM_IFINFO, RTM_VERSION, &info, 0, w); 1280 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1281 struct if_msghdr *ifm; 1282 1283 ifm = (struct if_msghdr *)w->w_tmem; 1284 ifm->ifm_index = ifp->if_index; 1285 ifm->ifm_tableid = ifp->if_rdomain; 1286 ifm->ifm_flags = ifp->if_flags; 1287 ifm->ifm_data = ifp->if_data; 1288 ifm->ifm_addrs = info.rti_addrs; 1289 error = copyout(ifm, w->w_where, len); 1290 if (error) 1291 return (error); 1292 w->w_where += len; 1293 } 1294 info.rti_info[RTAX_IFP] = NULL; 1295 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 1296 KASSERT(ifa->ifa_addr->sa_family != AF_LINK); 1297 if (af && af != ifa->ifa_addr->sa_family) 1298 continue; 1299 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1300 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1301 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1302 len = rt_msg2(RTM_NEWADDR, RTM_VERSION, &info, 0, w); 1303 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1304 struct ifa_msghdr *ifam; 1305 1306 ifam = (struct ifa_msghdr *)w->w_tmem; 1307 ifam->ifam_index = ifa->ifa_ifp->if_index; 1308 ifam->ifam_flags = ifa->ifa_flags; 1309 ifam->ifam_metric = ifa->ifa_metric; 1310 ifam->ifam_addrs = info.rti_addrs; 1311 error = copyout(w->w_tmem, w->w_where, len); 1312 if (error) 1313 return (error); 1314 w->w_where += len; 1315 } 1316 } 1317 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 1318 info.rti_info[RTAX_BRD] = NULL; 1319 } 1320 return (0); 1321 } 1322 1323 int 1324 sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, 1325 size_t newlen) 1326 { 1327 struct radix_node_head *rnh; 1328 int i, s, error = EINVAL; 1329 u_char af; 1330 struct walkarg w; 1331 struct rt_tableinfo tableinfo; 1332 u_int tableid = 0; 1333 1334 if (new) 1335 return (EPERM); 1336 if (namelen < 3 || namelen > 4) 1337 return (EINVAL); 1338 af = name[0]; 1339 bzero(&w, sizeof(w)); 1340 w.w_where = where; 1341 w.w_given = *given; 1342 w.w_needed = 0 - w.w_given; 1343 w.w_op = name[1]; 1344 w.w_arg = name[2]; 1345 1346 if (namelen == 4) { 1347 tableid = name[3]; 1348 if (!rtable_exists(tableid)) 1349 return (ENOENT); 1350 } else 1351 tableid = curproc->p_p->ps_rtableid; 1352 1353 s = splsoftnet(); 1354 switch (w.w_op) { 1355 1356 case NET_RT_DUMP: 1357 case NET_RT_FLAGS: 1358 for (i = 1; i <= AF_MAX; i++) 1359 if ((rnh = rtable_get(tableid, i)) != NULL && 1360 (af == 0 || af == i) && 1361 (error = (*rnh->rnh_walktree)(rnh, 1362 sysctl_dumpentry, &w))) 1363 break; 1364 break; 1365 1366 case NET_RT_IFLIST: 1367 error = sysctl_iflist(af, &w); 1368 break; 1369 1370 case NET_RT_STATS: 1371 error = sysctl_rdstruct(where, given, new, 1372 &rtstat, sizeof(rtstat)); 1373 splx(s); 1374 return (error); 1375 case NET_RT_TABLE: 1376 tableid = w.w_arg; 1377 if (!rtable_exists(tableid)) { 1378 splx(s); 1379 return (ENOENT); 1380 } 1381 tableinfo.rti_tableid = tableid; 1382 tableinfo.rti_domainid = rtable_l2(tableid); 1383 error = sysctl_rdstruct(where, given, new, 1384 &tableinfo, sizeof(tableinfo)); 1385 splx(s); 1386 return (error); 1387 } 1388 splx(s); 1389 free(w.w_tmem, M_RTABLE, 0); 1390 w.w_needed += w.w_given; 1391 if (where) { 1392 *given = w.w_where - (caddr_t)where; 1393 if (*given < w.w_needed) 1394 return (ENOMEM); 1395 } else 1396 *given = (11 * w.w_needed) / 10; 1397 1398 return (error); 1399 } 1400 1401 /* 1402 * Definitions of protocols supported in the ROUTE domain. 1403 */ 1404 1405 extern struct domain routedomain; /* or at least forward */ 1406 1407 struct protosw routesw[] = { 1408 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR|PR_WANTRCVD, 1409 route_input, route_output, raw_ctlinput, route_ctloutput, 1410 route_usrreq, 1411 raw_init, 0, 0, 0, 1412 sysctl_rtable, 1413 } 1414 }; 1415 1416 struct domain routedomain = 1417 { PF_ROUTE, "route", route_init, 0, 0, 1418 routesw, &routesw[nitems(routesw)] }; 1419