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