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