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