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