1 /* $NetBSD: rtsock.c,v 1.85 2006/05/27 23:08:11 elad Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1988, 1991, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.85 2006/05/27 23:08:11 elad Exp $"); 65 66 #include "opt_inet.h" 67 68 #include <sys/param.h> 69 #include <sys/systm.h> 70 #include <sys/proc.h> 71 #include <sys/mbuf.h> 72 #include <sys/socket.h> 73 #include <sys/socketvar.h> 74 #include <sys/domain.h> 75 #include <sys/protosw.h> 76 #include <sys/sysctl.h> 77 #include <sys/kauth.h> 78 79 #include <net/if.h> 80 #include <net/route.h> 81 #include <net/raw_cb.h> 82 83 #include <machine/stdarg.h> 84 85 DOMAIN_DEFINE(routedomain); /* forward declare and add to link set */ 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; 93 int w_arg; 94 int w_given; 95 int w_needed; 96 caddr_t w_where; 97 int w_tmemsize; 98 int w_tmemneeded; 99 caddr_t w_tmem; 100 }; 101 102 static struct mbuf *rt_msg1(int, struct rt_addrinfo *, caddr_t, int); 103 static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *, int *); 104 static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *); 105 static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int, 106 struct rt_addrinfo *); 107 static int sysctl_dumpentry(struct radix_node *, void *); 108 static int sysctl_iflist(int, struct walkarg *, int); 109 static int sysctl_rtable(SYSCTLFN_PROTO); 110 static inline void rt_adjustcount(int, int); 111 112 /* Sleazy use of local variables throughout file, warning!!!! */ 113 #define dst info.rti_info[RTAX_DST] 114 #define gate info.rti_info[RTAX_GATEWAY] 115 #define netmask info.rti_info[RTAX_NETMASK] 116 #define genmask info.rti_info[RTAX_GENMASK] 117 #define ifpaddr info.rti_info[RTAX_IFP] 118 #define ifaaddr info.rti_info[RTAX_IFA] 119 #define brdaddr info.rti_info[RTAX_BRD] 120 121 static inline void 122 rt_adjustcount(int af, int cnt) 123 { 124 route_cb.any_count += cnt; 125 switch (af) { 126 case AF_INET: 127 route_cb.ip_count += cnt; 128 return; 129 #ifdef INET6 130 case AF_INET6: 131 route_cb.ip6_count += cnt; 132 return; 133 #endif 134 case AF_IPX: 135 route_cb.ipx_count += cnt; 136 return; 137 case AF_NS: 138 route_cb.ns_count += cnt; 139 return; 140 case AF_ISO: 141 route_cb.iso_count += cnt; 142 return; 143 } 144 } 145 146 /*ARGSUSED*/ 147 int 148 route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 149 struct mbuf *control, struct lwp *l) 150 { 151 int error = 0; 152 struct rawcb *rp = sotorawcb(so); 153 int s; 154 155 if (req == PRU_ATTACH) { 156 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 157 if ((so->so_pcb = rp) != NULL) 158 memset(so->so_pcb, 0, sizeof(*rp)); 159 160 } 161 if (req == PRU_DETACH && rp) 162 rt_adjustcount(rp->rcb_proto.sp_protocol, -1); 163 s = splsoftnet(); 164 165 /* 166 * Don't call raw_usrreq() in the attach case, because 167 * we want to allow non-privileged processes to listen on 168 * and send "safe" commands to the routing socket. 169 */ 170 if (req == PRU_ATTACH) { 171 if (l == 0) 172 error = EACCES; 173 else 174 error = raw_attach(so, (int)(long)nam); 175 } else 176 error = raw_usrreq(so, req, m, nam, control, l); 177 178 rp = sotorawcb(so); 179 if (req == PRU_ATTACH && rp) { 180 if (error) { 181 free((caddr_t)rp, M_PCB); 182 splx(s); 183 return (error); 184 } 185 rt_adjustcount(rp->rcb_proto.sp_protocol, 1); 186 rp->rcb_laddr = &route_src; 187 rp->rcb_faddr = &route_dst; 188 soisconnected(so); 189 so->so_options |= SO_USELOOPBACK; 190 } 191 splx(s); 192 return (error); 193 } 194 195 /*ARGSUSED*/ 196 int 197 route_output(struct mbuf *m, ...) 198 { 199 struct rt_msghdr *rtm = 0; 200 struct radix_node *rn = 0; 201 struct rtentry *rt = 0; 202 struct rtentry *saved_nrt = 0; 203 struct radix_node_head *rnh; 204 struct rt_addrinfo info; 205 int len, error = 0; 206 struct ifnet *ifp = 0; 207 struct ifaddr *ifa = 0; 208 struct socket *so; 209 va_list ap; 210 sa_family_t family; 211 212 va_start(ap, m); 213 so = va_arg(ap, struct socket *); 214 va_end(ap); 215 216 #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0) 217 if (m == 0 || ((m->m_len < sizeof(int32_t)) && 218 (m = m_pullup(m, sizeof(int32_t))) == 0)) 219 return (ENOBUFS); 220 if ((m->m_flags & M_PKTHDR) == 0) 221 panic("route_output"); 222 len = m->m_pkthdr.len; 223 if (len < sizeof(*rtm) || 224 len != mtod(m, struct rt_msghdr *)->rtm_msglen) { 225 dst = 0; 226 senderr(EINVAL); 227 } 228 R_Malloc(rtm, struct rt_msghdr *, len); 229 if (rtm == 0) { 230 dst = 0; 231 senderr(ENOBUFS); 232 } 233 m_copydata(m, 0, len, (caddr_t)rtm); 234 if (rtm->rtm_version != RTM_VERSION) { 235 dst = 0; 236 senderr(EPROTONOSUPPORT); 237 } 238 rtm->rtm_pid = curproc->p_pid; 239 memset(&info, 0, sizeof(info)); 240 info.rti_addrs = rtm->rtm_addrs; 241 if (rt_xaddrs(rtm->rtm_type, (caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) 242 senderr(EINVAL); 243 info.rti_flags = rtm->rtm_flags; 244 if (dst == 0 || (dst->sa_family >= AF_MAX)) 245 senderr(EINVAL); 246 if (gate != 0 && (gate->sa_family >= AF_MAX)) 247 senderr(EINVAL); 248 if (genmask) { 249 struct radix_node *t; 250 t = rn_addmask(genmask, 0, 1); 251 if (t && genmask->sa_len >= ((const struct sockaddr *)t->rn_key)->sa_len && 252 Bcmp((const char *const *)genmask + 1, (const char *const *)t->rn_key + 1, 253 ((const struct sockaddr *)t->rn_key)->sa_len) - 1) 254 genmask = (const struct sockaddr *)(t->rn_key); 255 else 256 senderr(ENOBUFS); 257 } 258 259 /* 260 * Verify that the caller has the appropriate privilege; RTM_GET 261 * is the only operation the non-superuser is allowed. 262 */ 263 if (rtm->rtm_type != RTM_GET && 264 kauth_authorize_generic(curproc->p_cred, KAUTH_GENERIC_ISSUSER, &curproc->p_acflag) != 0) 265 senderr(EACCES); 266 267 switch (rtm->rtm_type) { 268 269 case RTM_ADD: 270 if (gate == 0) 271 senderr(EINVAL); 272 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 273 if (error == 0 && saved_nrt) { 274 rt_setmetrics(rtm->rtm_inits, 275 &rtm->rtm_rmx, &saved_nrt->rt_rmx); 276 saved_nrt->rt_refcnt--; 277 saved_nrt->rt_genmask = genmask; 278 } 279 break; 280 281 case RTM_DELETE: 282 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 283 if (error == 0) { 284 (rt = saved_nrt)->rt_refcnt++; 285 goto report; 286 } 287 break; 288 289 case RTM_GET: 290 case RTM_CHANGE: 291 case RTM_LOCK: 292 if ((rnh = rt_tables[dst->sa_family]) == 0) { 293 senderr(EAFNOSUPPORT); 294 } 295 rn = rnh->rnh_lookup(dst, netmask, rnh); 296 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) { 297 senderr(ESRCH); 298 } 299 rt = (struct rtentry *)rn; 300 rt->rt_refcnt++; 301 if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */ 302 struct radix_node *rnn; 303 extern struct radix_node_head *mask_rnhead; 304 305 if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0) 306 senderr(ESRCH); 307 if (netmask && (rnn = rn_search(netmask, 308 mask_rnhead->rnh_treetop))) 309 netmask = (const struct sockaddr *)rnn->rn_key; 310 for (rnn = rt->rt_nodes; rnn; rnn = rnn->rn_dupedkey) 311 if (netmask == (const struct sockaddr *)rnn->rn_mask) 312 break; 313 if (rnn == 0) 314 senderr(ETOOMANYREFS); 315 rt = (struct rtentry *)rnn; 316 } 317 318 switch (rtm->rtm_type) { 319 case RTM_GET: 320 report: 321 dst = rt_key(rt); 322 gate = rt->rt_gateway; 323 netmask = rt_mask(rt); 324 genmask = rt->rt_genmask; 325 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 326 if ((ifp = rt->rt_ifp) != NULL) { 327 ifpaddr = TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr; 328 ifaaddr = rt->rt_ifa->ifa_addr; 329 if (ifp->if_flags & IFF_POINTOPOINT) 330 brdaddr = rt->rt_ifa->ifa_dstaddr; 331 else 332 brdaddr = 0; 333 rtm->rtm_index = ifp->if_index; 334 } else { 335 ifpaddr = 0; 336 ifaaddr = 0; 337 } 338 } 339 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)0, 340 (struct walkarg *)0, &len); 341 if (len > rtm->rtm_msglen) { 342 struct rt_msghdr *new_rtm; 343 R_Malloc(new_rtm, struct rt_msghdr *, len); 344 if (new_rtm == 0) 345 senderr(ENOBUFS); 346 Bcopy(rtm, new_rtm, rtm->rtm_msglen); 347 Free(rtm); rtm = new_rtm; 348 } 349 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, 350 (struct walkarg *)0, 0); 351 rtm->rtm_flags = rt->rt_flags; 352 rtm->rtm_rmx = rt->rt_rmx; 353 rtm->rtm_addrs = info.rti_addrs; 354 break; 355 356 case RTM_CHANGE: 357 /* 358 * new gateway could require new ifaddr, ifp; 359 * flags may also be different; ifp may be specified 360 * by ll sockaddr when protocol address is ambiguous 361 */ 362 if ((error = rt_getifa(&info)) != 0) 363 senderr(error); 364 if (gate && rt_setgate(rt, rt_key(rt), gate)) 365 senderr(EDQUOT); 366 /* new gateway could require new ifaddr, ifp; 367 flags may also be different; ifp may be specified 368 by ll sockaddr when protocol address is ambiguous */ 369 if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && 370 (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) 371 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, 372 ifp); 373 else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || 374 (gate && (ifa = ifa_ifwithroute(rt->rt_flags, 375 rt_key(rt), gate)))) 376 ifp = ifa->ifa_ifp; 377 if (ifa) { 378 struct ifaddr *oifa = rt->rt_ifa; 379 if (oifa != ifa) { 380 if (oifa && oifa->ifa_rtrequest) 381 oifa->ifa_rtrequest(RTM_DELETE, rt, 382 &info); 383 IFAFREE(rt->rt_ifa); 384 rt->rt_ifa = ifa; 385 IFAREF(rt->rt_ifa); 386 rt->rt_ifp = ifp; 387 } 388 } 389 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 390 &rt->rt_rmx); 391 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 392 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 393 if (genmask) 394 rt->rt_genmask = genmask; 395 /* 396 * Fall into 397 */ 398 case RTM_LOCK: 399 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 400 rt->rt_rmx.rmx_locks |= 401 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 402 break; 403 } 404 break; 405 406 default: 407 senderr(EOPNOTSUPP); 408 } 409 410 flush: 411 if (rtm) { 412 if (error) 413 rtm->rtm_errno = error; 414 else 415 rtm->rtm_flags |= RTF_DONE; 416 } 417 family = dst ? dst->sa_family : 0; 418 if (rt) 419 rtfree(rt); 420 { 421 struct rawcb *rp = 0; 422 /* 423 * Check to see if we don't want our own messages. 424 */ 425 if ((so->so_options & SO_USELOOPBACK) == 0) { 426 if (route_cb.any_count <= 1) { 427 if (rtm) 428 Free(rtm); 429 m_freem(m); 430 return (error); 431 } 432 /* There is another listener, so construct message */ 433 rp = sotorawcb(so); 434 } 435 if (rtm) { 436 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 437 if (m->m_pkthdr.len < rtm->rtm_msglen) { 438 m_freem(m); 439 m = NULL; 440 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 441 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 442 Free(rtm); 443 } 444 if (rp) 445 rp->rcb_proto.sp_family = 0; /* Avoid us */ 446 if (family) 447 route_proto.sp_protocol = family; 448 if (m) 449 raw_input(m, &route_proto, &route_src, &route_dst); 450 if (rp) 451 rp->rcb_proto.sp_family = PF_ROUTE; 452 } 453 return (error); 454 } 455 456 void 457 rt_setmetrics(u_long which, const struct rt_metrics *in, struct rt_metrics *out) 458 { 459 #define metric(f, e) if (which & (f)) out->e = in->e; 460 metric(RTV_RPIPE, rmx_recvpipe); 461 metric(RTV_SPIPE, rmx_sendpipe); 462 metric(RTV_SSTHRESH, rmx_ssthresh); 463 metric(RTV_RTT, rmx_rtt); 464 metric(RTV_RTTVAR, rmx_rttvar); 465 metric(RTV_HOPCOUNT, rmx_hopcount); 466 metric(RTV_MTU, rmx_mtu); 467 metric(RTV_EXPIRE, rmx_expire); 468 #undef metric 469 } 470 471 #define ROUNDUP(a) \ 472 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 473 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 474 475 static int 476 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, struct rt_addrinfo *rtinfo) 477 { 478 const struct sockaddr *sa = NULL; /* Quell compiler warning */ 479 int i; 480 481 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 482 if ((rtinfo->rti_addrs & (1 << i)) == 0) 483 continue; 484 rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; 485 ADVANCE(cp, sa); 486 } 487 488 /* Check for extra addresses specified, except RTM_GET asking for interface info. */ 489 if (rtmtype == RTM_GET) { 490 if (((rtinfo->rti_addrs & (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0) 491 return (1); 492 } else { 493 if ((rtinfo->rti_addrs & (~0 << i)) != 0) 494 return (1); 495 } 496 /* Check for bad data length. */ 497 if (cp != cplim) { 498 if (i == RTAX_NETMASK + 1 && sa && 499 cp - ROUNDUP(sa->sa_len) + sa->sa_len == cplim) 500 /* 501 * The last sockaddr was netmask. 502 * We accept this for now for the sake of old 503 * binaries or third party softwares. 504 */ 505 ; 506 else 507 return (1); 508 } 509 return (0); 510 } 511 512 static struct mbuf * 513 rt_msg1(int type, struct rt_addrinfo *rtinfo, caddr_t data, int datalen) 514 { 515 struct rt_msghdr *rtm; 516 struct mbuf *m; 517 int i; 518 const struct sockaddr *sa; 519 int len, dlen; 520 521 m = m_gethdr(M_DONTWAIT, MT_DATA); 522 if (m == 0) 523 return (m); 524 MCLAIM(m, &routedomain.dom_mowner); 525 switch (type) { 526 527 case RTM_DELADDR: 528 case RTM_NEWADDR: 529 len = sizeof(struct ifa_msghdr); 530 break; 531 532 #ifdef COMPAT_14 533 case RTM_OIFINFO: 534 len = sizeof(struct if_msghdr14); 535 break; 536 #endif 537 538 case RTM_IFINFO: 539 len = sizeof(struct if_msghdr); 540 break; 541 542 case RTM_IFANNOUNCE: 543 case RTM_IEEE80211: 544 len = sizeof(struct if_announcemsghdr); 545 break; 546 547 default: 548 len = sizeof(struct rt_msghdr); 549 } 550 if (len > MHLEN + MLEN) 551 panic("rt_msg1: message too long"); 552 else if (len > MHLEN) { 553 m->m_next = m_get(M_DONTWAIT, MT_DATA); 554 if (m->m_next == NULL) { 555 m_freem(m); 556 return (NULL); 557 } 558 MCLAIM(m->m_next, m->m_owner); 559 m->m_pkthdr.len = len; 560 m->m_len = MHLEN; 561 m->m_next->m_len = len - MHLEN; 562 } else { 563 m->m_pkthdr.len = m->m_len = len; 564 } 565 m->m_pkthdr.rcvif = 0; 566 m_copyback(m, 0, datalen, data); 567 rtm = mtod(m, struct rt_msghdr *); 568 for (i = 0; i < RTAX_MAX; i++) { 569 if ((sa = rtinfo->rti_info[i]) == NULL) 570 continue; 571 rtinfo->rti_addrs |= (1 << i); 572 dlen = ROUNDUP(sa->sa_len); 573 m_copyback(m, len, dlen, sa); 574 len += dlen; 575 } 576 if (m->m_pkthdr.len != len) { 577 m_freem(m); 578 return (NULL); 579 } 580 rtm->rtm_msglen = len; 581 rtm->rtm_version = RTM_VERSION; 582 rtm->rtm_type = type; 583 return (m); 584 } 585 586 /* 587 * rt_msg2 588 * 589 * fills 'cp' or 'w'.w_tmem with the routing socket message and 590 * returns the length of the message in 'lenp'. 591 * 592 * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold 593 * the message 594 * otherwise walkarg's w_needed is updated and if the user buffer is 595 * specified and w_needed indicates space exists the information is copied 596 * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, 597 * if the allocation fails ENOBUFS is returned. 598 */ 599 static int 600 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w, 601 int *lenp) 602 { 603 int i; 604 int len, dlen, second_time = 0; 605 caddr_t cp0; 606 607 rtinfo->rti_addrs = 0; 608 again: 609 switch (type) { 610 611 case RTM_DELADDR: 612 case RTM_NEWADDR: 613 len = sizeof(struct ifa_msghdr); 614 break; 615 #ifdef COMPAT_14 616 case RTM_OIFINFO: 617 len = sizeof(struct if_msghdr14); 618 break; 619 #endif 620 621 case RTM_IFINFO: 622 len = sizeof(struct if_msghdr); 623 break; 624 625 default: 626 len = sizeof(struct rt_msghdr); 627 } 628 if ((cp0 = cp) != NULL) 629 cp += len; 630 for (i = 0; i < RTAX_MAX; i++) { 631 const struct sockaddr *sa; 632 633 if ((sa = rtinfo->rti_info[i]) == 0) 634 continue; 635 rtinfo->rti_addrs |= (1 << i); 636 dlen = ROUNDUP(sa->sa_len); 637 if (cp) { 638 bcopy(sa, cp, (unsigned)dlen); 639 cp += dlen; 640 } 641 len += dlen; 642 } 643 if (cp == 0 && w != NULL && !second_time) { 644 struct walkarg *rw = w; 645 646 rw->w_needed += len; 647 if (rw->w_needed <= 0 && rw->w_where) { 648 if (rw->w_tmemsize < len) { 649 if (rw->w_tmem) 650 free(rw->w_tmem, M_RTABLE); 651 rw->w_tmem = (caddr_t) malloc(len, M_RTABLE, 652 M_NOWAIT); 653 if (rw->w_tmem) 654 rw->w_tmemsize = len; 655 } 656 if (rw->w_tmem) { 657 cp = rw->w_tmem; 658 second_time = 1; 659 goto again; 660 } else { 661 rw->w_tmemneeded = len; 662 return (ENOBUFS); 663 } 664 } 665 } 666 if (cp) { 667 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 668 669 rtm->rtm_version = RTM_VERSION; 670 rtm->rtm_type = type; 671 rtm->rtm_msglen = len; 672 } 673 if (lenp) 674 *lenp = len; 675 return (0); 676 } 677 678 /* 679 * This routine is called to generate a message from the routing 680 * socket indicating that a redirect has occurred, a routing lookup 681 * has failed, or that a protocol has detected timeouts to a particular 682 * destination. 683 */ 684 void 685 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error) 686 { 687 struct rt_msghdr rtm; 688 struct mbuf *m; 689 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 690 691 if (route_cb.any_count == 0) 692 return; 693 memset(&rtm, 0, sizeof(rtm)); 694 rtm.rtm_flags = RTF_DONE | flags; 695 rtm.rtm_errno = error; 696 m = rt_msg1(type, rtinfo, (caddr_t)&rtm, sizeof(rtm)); 697 if (m == 0) 698 return; 699 mtod(m, struct rt_msghdr *)->rtm_addrs = rtinfo->rti_addrs; 700 route_proto.sp_protocol = sa ? sa->sa_family : 0; 701 raw_input(m, &route_proto, &route_src, &route_dst); 702 } 703 704 /* 705 * This routine is called to generate a message from the routing 706 * socket indicating that the status of a network interface has changed. 707 */ 708 void 709 rt_ifmsg(struct ifnet *ifp) 710 { 711 struct if_msghdr ifm; 712 #ifdef COMPAT_14 713 struct if_msghdr14 oifm; 714 #endif 715 struct mbuf *m; 716 struct rt_addrinfo info; 717 718 if (route_cb.any_count == 0) 719 return; 720 memset(&info, 0, sizeof(info)); 721 memset(&ifm, 0, sizeof(ifm)); 722 ifm.ifm_index = ifp->if_index; 723 ifm.ifm_flags = ifp->if_flags; 724 ifm.ifm_data = ifp->if_data; 725 ifm.ifm_addrs = 0; 726 m = rt_msg1(RTM_IFINFO, &info, (caddr_t)&ifm, sizeof(ifm)); 727 if (m == 0) 728 return; 729 route_proto.sp_protocol = 0; 730 raw_input(m, &route_proto, &route_src, &route_dst); 731 #ifdef COMPAT_14 732 memset(&info, 0, sizeof(info)); 733 memset(&oifm, 0, sizeof(oifm)); 734 oifm.ifm_index = ifp->if_index; 735 oifm.ifm_flags = ifp->if_flags; 736 oifm.ifm_data.ifi_type = ifp->if_data.ifi_type; 737 oifm.ifm_data.ifi_addrlen = ifp->if_data.ifi_addrlen; 738 oifm.ifm_data.ifi_hdrlen = ifp->if_data.ifi_hdrlen; 739 oifm.ifm_data.ifi_mtu = ifp->if_data.ifi_mtu; 740 oifm.ifm_data.ifi_metric = ifp->if_data.ifi_metric; 741 oifm.ifm_data.ifi_baudrate = ifp->if_data.ifi_baudrate; 742 oifm.ifm_data.ifi_ipackets = ifp->if_data.ifi_ipackets; 743 oifm.ifm_data.ifi_ierrors = ifp->if_data.ifi_ierrors; 744 oifm.ifm_data.ifi_opackets = ifp->if_data.ifi_opackets; 745 oifm.ifm_data.ifi_oerrors = ifp->if_data.ifi_oerrors; 746 oifm.ifm_data.ifi_collisions = ifp->if_data.ifi_collisions; 747 oifm.ifm_data.ifi_ibytes = ifp->if_data.ifi_ibytes; 748 oifm.ifm_data.ifi_obytes = ifp->if_data.ifi_obytes; 749 oifm.ifm_data.ifi_imcasts = ifp->if_data.ifi_imcasts; 750 oifm.ifm_data.ifi_omcasts = ifp->if_data.ifi_omcasts; 751 oifm.ifm_data.ifi_iqdrops = ifp->if_data.ifi_iqdrops; 752 oifm.ifm_data.ifi_noproto = ifp->if_data.ifi_noproto; 753 oifm.ifm_data.ifi_lastchange = ifp->if_data.ifi_lastchange; 754 oifm.ifm_addrs = 0; 755 m = rt_msg1(RTM_OIFINFO, &info, (caddr_t)&oifm, sizeof(oifm)); 756 if (m == 0) 757 return; 758 route_proto.sp_protocol = 0; 759 raw_input(m, &route_proto, &route_src, &route_dst); 760 #endif 761 } 762 763 /* 764 * This is called to generate messages from the routing socket 765 * indicating a network interface has had addresses associated with it. 766 * if we ever reverse the logic and replace messages TO the routing 767 * socket indicate a request to configure interfaces, then it will 768 * be unnecessary as the routing socket will automatically generate 769 * copies of it. 770 */ 771 void 772 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) 773 { 774 struct rt_addrinfo info; 775 struct sockaddr *sa = NULL; 776 int pass; 777 struct mbuf *m = NULL; 778 struct ifnet *ifp = ifa->ifa_ifp; 779 780 if (route_cb.any_count == 0) 781 return; 782 for (pass = 1; pass < 3; pass++) { 783 memset(&info, 0, sizeof(info)); 784 if ((cmd == RTM_ADD && pass == 1) || 785 (cmd == RTM_DELETE && pass == 2)) { 786 struct ifa_msghdr ifam; 787 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 788 789 ifaaddr = sa = ifa->ifa_addr; 790 ifpaddr = TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr; 791 netmask = ifa->ifa_netmask; 792 brdaddr = ifa->ifa_dstaddr; 793 memset(&ifam, 0, sizeof(ifam)); 794 ifam.ifam_index = ifp->if_index; 795 ifam.ifam_metric = ifa->ifa_metric; 796 ifam.ifam_flags = ifa->ifa_flags; 797 m = rt_msg1(ncmd, &info, (caddr_t)&ifam, sizeof(ifam)); 798 if (m == NULL) 799 continue; 800 mtod(m, struct ifa_msghdr *)->ifam_addrs = 801 info.rti_addrs; 802 } 803 if ((cmd == RTM_ADD && pass == 2) || 804 (cmd == RTM_DELETE && pass == 1)) { 805 struct rt_msghdr rtm; 806 807 if (rt == 0) 808 continue; 809 netmask = rt_mask(rt); 810 dst = sa = rt_key(rt); 811 gate = rt->rt_gateway; 812 memset(&rtm, 0, sizeof(rtm)); 813 rtm.rtm_index = ifp->if_index; 814 rtm.rtm_flags |= rt->rt_flags; 815 rtm.rtm_errno = error; 816 m = rt_msg1(cmd, &info, (caddr_t)&rtm, sizeof(rtm)); 817 if (m == NULL) 818 continue; 819 mtod(m, struct rt_msghdr *)->rtm_addrs = info.rti_addrs; 820 } 821 route_proto.sp_protocol = sa ? sa->sa_family : 0; 822 raw_input(m, &route_proto, &route_src, &route_dst); 823 } 824 } 825 826 static struct mbuf * 827 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, 828 struct rt_addrinfo *info) 829 { 830 struct if_announcemsghdr ifan; 831 832 memset(info, 0, sizeof(*info)); 833 memset(&ifan, 0, sizeof(ifan)); 834 ifan.ifan_index = ifp->if_index; 835 strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); 836 ifan.ifan_what = what; 837 return rt_msg1(type, info, (caddr_t)&ifan, sizeof(ifan)); 838 } 839 840 /* 841 * This is called to generate routing socket messages indicating 842 * network interface arrival and departure. 843 */ 844 void 845 rt_ifannouncemsg(struct ifnet *ifp, int what) 846 { 847 struct mbuf *m; 848 struct rt_addrinfo info; 849 850 if (route_cb.any_count == 0) 851 return; 852 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info); 853 if (m == NULL) 854 return; 855 route_proto.sp_protocol = 0; 856 raw_input(m, &route_proto, &route_src, &route_dst); 857 } 858 859 /* 860 * This is called to generate routing socket messages indicating 861 * IEEE80211 wireless events. 862 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way. 863 */ 864 void 865 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len) 866 { 867 struct mbuf *m; 868 struct rt_addrinfo info; 869 870 if (route_cb.any_count == 0) 871 return; 872 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info); 873 if (m == NULL) 874 return; 875 /* 876 * Append the ieee80211 data. Try to stick it in the 877 * mbuf containing the ifannounce msg; otherwise allocate 878 * a new mbuf and append. 879 * 880 * NB: we assume m is a single mbuf. 881 */ 882 if (data_len > M_TRAILINGSPACE(m)) { 883 struct mbuf *n = m_get(M_NOWAIT, MT_DATA); 884 if (n == NULL) { 885 m_freem(m); 886 return; 887 } 888 (void)memcpy(mtod(n, void *), data, data_len); 889 n->m_len = data_len; 890 m->m_next = n; 891 } else if (data_len > 0) { 892 (void)memcpy(mtod(m, u_int8_t *) + m->m_len, data, data_len); 893 m->m_len += data_len; 894 } 895 if (m->m_flags & M_PKTHDR) 896 m->m_pkthdr.len += data_len; 897 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len; 898 route_proto.sp_protocol = 0; 899 raw_input(m, &route_proto, &route_src, &route_dst); 900 } 901 902 /* 903 * This is used in dumping the kernel table via sysctl(). 904 */ 905 static int 906 sysctl_dumpentry(struct radix_node *rn, void *v) 907 { 908 struct walkarg *w = v; 909 struct rtentry *rt = (struct rtentry *)rn; 910 int error = 0, size; 911 struct rt_addrinfo info; 912 913 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 914 return 0; 915 memset(&info, 0, sizeof(info)); 916 dst = rt_key(rt); 917 gate = rt->rt_gateway; 918 netmask = rt_mask(rt); 919 genmask = rt->rt_genmask; 920 if (rt->rt_ifp) { 921 ifpaddr = TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr; 922 ifaaddr = rt->rt_ifa->ifa_addr; 923 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 924 brdaddr = rt->rt_ifa->ifa_dstaddr; 925 } 926 if ((error = rt_msg2(RTM_GET, &info, 0, w, &size))) 927 return (error); 928 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 929 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 930 931 rtm->rtm_flags = rt->rt_flags; 932 rtm->rtm_use = rt->rt_use; 933 rtm->rtm_rmx = rt->rt_rmx; 934 KASSERT(rt->rt_ifp != NULL); 935 rtm->rtm_index = rt->rt_ifp->if_index; 936 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 937 rtm->rtm_addrs = info.rti_addrs; 938 if ((error = copyout(rtm, w->w_where, size)) != 0) 939 w->w_where = NULL; 940 else 941 w->w_where += size; 942 } 943 return (error); 944 } 945 946 static int 947 sysctl_iflist(int af, struct walkarg *w, int type) 948 { 949 struct ifnet *ifp; 950 struct ifaddr *ifa; 951 struct rt_addrinfo info; 952 int len, error = 0; 953 954 memset(&info, 0, sizeof(info)); 955 IFNET_FOREACH(ifp) { 956 if (w->w_arg && w->w_arg != ifp->if_index) 957 continue; 958 ifa = TAILQ_FIRST(&ifp->if_addrlist); 959 if (ifa == NULL) 960 continue; 961 ifpaddr = ifa->ifa_addr; 962 switch (type) { 963 case NET_RT_IFLIST: 964 error = 965 rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w, &len); 966 break; 967 #ifdef COMPAT_14 968 case NET_RT_OIFLIST: 969 error = 970 rt_msg2(RTM_OIFINFO, &info, (caddr_t)0, w, &len); 971 break; 972 #endif 973 default: 974 panic("sysctl_iflist(1)"); 975 } 976 if (error) 977 return (error); 978 ifpaddr = 0; 979 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 980 switch (type) { 981 case NET_RT_IFLIST: { 982 struct if_msghdr *ifm; 983 984 ifm = (struct if_msghdr *)w->w_tmem; 985 ifm->ifm_index = ifp->if_index; 986 ifm->ifm_flags = ifp->if_flags; 987 ifm->ifm_data = ifp->if_data; 988 ifm->ifm_addrs = info.rti_addrs; 989 error = copyout(ifm, w->w_where, len); 990 if (error) 991 return (error); 992 w->w_where += len; 993 break; 994 } 995 996 #ifdef COMPAT_14 997 case NET_RT_OIFLIST: { 998 struct if_msghdr14 *ifm; 999 1000 ifm = (struct if_msghdr14 *)w->w_tmem; 1001 ifm->ifm_index = ifp->if_index; 1002 ifm->ifm_flags = ifp->if_flags; 1003 ifm->ifm_data.ifi_type = ifp->if_data.ifi_type; 1004 ifm->ifm_data.ifi_addrlen = 1005 ifp->if_data.ifi_addrlen; 1006 ifm->ifm_data.ifi_hdrlen = 1007 ifp->if_data.ifi_hdrlen; 1008 ifm->ifm_data.ifi_mtu = ifp->if_data.ifi_mtu; 1009 ifm->ifm_data.ifi_metric = 1010 ifp->if_data.ifi_metric; 1011 ifm->ifm_data.ifi_baudrate = 1012 ifp->if_data.ifi_baudrate; 1013 ifm->ifm_data.ifi_ipackets = 1014 ifp->if_data.ifi_ipackets; 1015 ifm->ifm_data.ifi_ierrors = 1016 ifp->if_data.ifi_ierrors; 1017 ifm->ifm_data.ifi_opackets = 1018 ifp->if_data.ifi_opackets; 1019 ifm->ifm_data.ifi_oerrors = 1020 ifp->if_data.ifi_oerrors; 1021 ifm->ifm_data.ifi_collisions = 1022 ifp->if_data.ifi_collisions; 1023 ifm->ifm_data.ifi_ibytes = 1024 ifp->if_data.ifi_ibytes; 1025 ifm->ifm_data.ifi_obytes = 1026 ifp->if_data.ifi_obytes; 1027 ifm->ifm_data.ifi_imcasts = 1028 ifp->if_data.ifi_imcasts; 1029 ifm->ifm_data.ifi_omcasts = 1030 ifp->if_data.ifi_omcasts; 1031 ifm->ifm_data.ifi_iqdrops = 1032 ifp->if_data.ifi_iqdrops; 1033 ifm->ifm_data.ifi_noproto = 1034 ifp->if_data.ifi_noproto; 1035 ifm->ifm_data.ifi_lastchange = 1036 ifp->if_data.ifi_lastchange; 1037 ifm->ifm_addrs = info.rti_addrs; 1038 error = copyout(ifm, w->w_where, len); 1039 if (error) 1040 return (error); 1041 w->w_where += len; 1042 break; 1043 } 1044 #endif 1045 default: 1046 panic("sysctl_iflist(2)"); 1047 } 1048 } 1049 while ((ifa = TAILQ_NEXT(ifa, ifa_list)) != NULL) { 1050 if (af && af != ifa->ifa_addr->sa_family) 1051 continue; 1052 ifaaddr = ifa->ifa_addr; 1053 netmask = ifa->ifa_netmask; 1054 brdaddr = ifa->ifa_dstaddr; 1055 if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len))) 1056 return (error); 1057 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1058 struct ifa_msghdr *ifam; 1059 1060 ifam = (struct ifa_msghdr *)w->w_tmem; 1061 ifam->ifam_index = ifa->ifa_ifp->if_index; 1062 ifam->ifam_flags = ifa->ifa_flags; 1063 ifam->ifam_metric = ifa->ifa_metric; 1064 ifam->ifam_addrs = info.rti_addrs; 1065 error = copyout(w->w_tmem, w->w_where, len); 1066 if (error) 1067 return (error); 1068 w->w_where += len; 1069 } 1070 } 1071 ifaaddr = netmask = brdaddr = 0; 1072 } 1073 return (0); 1074 } 1075 1076 static int 1077 sysctl_rtable(SYSCTLFN_ARGS) 1078 { 1079 void *where = oldp; 1080 size_t *given = oldlenp; 1081 const void *new = newp; 1082 struct radix_node_head *rnh; 1083 int i, s, error = EINVAL; 1084 u_char af; 1085 struct walkarg w; 1086 1087 if (namelen == 1 && name[0] == CTL_QUERY) 1088 return (sysctl_query(SYSCTLFN_CALL(rnode))); 1089 1090 if (new) 1091 return (EPERM); 1092 if (namelen != 3) 1093 return (EINVAL); 1094 af = name[0]; 1095 w.w_tmemneeded = 0; 1096 w.w_tmemsize = 0; 1097 w.w_tmem = NULL; 1098 again: 1099 /* we may return here if a later [re]alloc of the t_mem buffer fails */ 1100 if (w.w_tmemneeded) { 1101 w.w_tmem = (caddr_t) malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK); 1102 w.w_tmemsize = w.w_tmemneeded; 1103 w.w_tmemneeded = 0; 1104 } 1105 w.w_op = name[1]; 1106 w.w_arg = name[2]; 1107 w.w_given = *given; 1108 w.w_needed = 0 - w.w_given; 1109 w.w_where = where; 1110 1111 s = splsoftnet(); 1112 switch (w.w_op) { 1113 1114 case NET_RT_DUMP: 1115 case NET_RT_FLAGS: 1116 for (i = 1; i <= AF_MAX; i++) 1117 if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 1118 (error = (*rnh->rnh_walktree)(rnh, 1119 sysctl_dumpentry, &w))) 1120 break; 1121 break; 1122 1123 #ifdef COMPAT_14 1124 case NET_RT_OIFLIST: 1125 error = sysctl_iflist(af, &w, w.w_op); 1126 break; 1127 #endif 1128 1129 case NET_RT_IFLIST: 1130 error = sysctl_iflist(af, &w, w.w_op); 1131 } 1132 splx(s); 1133 1134 /* check to see if we couldn't allocate memory with NOWAIT */ 1135 if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded) 1136 goto again; 1137 1138 if (w.w_tmem) 1139 free(w.w_tmem, M_RTABLE); 1140 w.w_needed += w.w_given; 1141 if (where) { 1142 *given = w.w_where - (caddr_t) where; 1143 if (*given < w.w_needed) 1144 return (ENOMEM); 1145 } else { 1146 *given = (11 * w.w_needed) / 10; 1147 } 1148 return (error); 1149 } 1150 1151 /* 1152 * Definitions of protocols supported in the ROUTE domain. 1153 */ 1154 1155 const struct protosw routesw[] = { 1156 { 1157 SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 1158 raw_input, route_output, raw_ctlinput, 0, 1159 route_usrreq, 1160 raw_init, 0, 0, 0, 1161 } }; 1162 1163 struct domain routedomain = { 1164 PF_ROUTE, "route", route_init, 0, 0, 1165 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] 1166 }; 1167 1168 SYSCTL_SETUP(sysctl_net_route_setup, "sysctl net.route subtree setup") 1169 { 1170 const struct sysctlnode *rnode = NULL; 1171 1172 sysctl_createv(clog, 0, NULL, NULL, 1173 CTLFLAG_PERMANENT, 1174 CTLTYPE_NODE, "net", NULL, 1175 NULL, 0, NULL, 0, 1176 CTL_NET, CTL_EOL); 1177 1178 sysctl_createv(clog, 0, NULL, &rnode, 1179 CTLFLAG_PERMANENT, 1180 CTLTYPE_NODE, "route", 1181 SYSCTL_DESCR("PF_ROUTE information"), 1182 NULL, 0, NULL, 0, 1183 CTL_NET, PF_ROUTE, CTL_EOL); 1184 sysctl_createv(clog, 0, NULL, NULL, 1185 CTLFLAG_PERMANENT, 1186 CTLTYPE_NODE, "rtable", 1187 SYSCTL_DESCR("Routing table information"), 1188 sysctl_rtable, 0, NULL, 0, 1189 CTL_NET, PF_ROUTE, 0 /* any protocol */, CTL_EOL); 1190 sysctl_createv(clog, 0, &rnode, NULL, 1191 CTLFLAG_PERMANENT, 1192 CTLTYPE_STRUCT, "stats", 1193 SYSCTL_DESCR("Routing statistics"), 1194 NULL, 0, &rtstat, sizeof(rtstat), 1195 CTL_CREATE, CTL_EOL); 1196 } 1197