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