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