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