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