|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1988, 1991, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 ! 55: */ ! 56: ! 57: ! 58: #include <sys/param.h> ! 59: #include <sys/systm.h> ! 60: #include <sys/kernel.h> ! 61: #include <sys/sysctl.h> ! 62: #include <sys/proc.h> ! 63: #include <sys/malloc.h> ! 64: #include <sys/mbuf.h> ! 65: #include <sys/socket.h> ! 66: #include <sys/socketvar.h> ! 67: #include <sys/domain.h> ! 68: #include <sys/protosw.h> ! 69: ! 70: #include <net/if.h> ! 71: #include <net/route.h> ! 72: #include <net/raw_cb.h> ! 73: ! 74: MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); ! 75: ! 76: static struct sockaddr route_dst = { 2, PF_ROUTE, }; ! 77: static struct sockaddr route_src = { 2, PF_ROUTE, }; ! 78: static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, }; ! 79: static struct sockproto route_proto = { PF_ROUTE, }; ! 80: ! 81: ! 82: ! 83: struct walkarg { ! 84: int w_tmemsize; ! 85: int w_op, w_arg; ! 86: caddr_t w_tmem; ! 87: struct sysctl_req *w_req; ! 88: }; ! 89: ! 90: static struct mbuf * ! 91: rt_msg1 __P((int, struct rt_addrinfo *)); ! 92: static int rt_msg2 __P((int, ! 93: struct rt_addrinfo *, caddr_t, struct walkarg *)); ! 94: static int rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); ! 95: static int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); ! 96: static int sysctl_iflist __P((int af, struct walkarg *w)); ! 97: static int route_output __P((struct mbuf *, struct socket *)); ! 98: static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *)); ! 99: ! 100: /* Sleazy use of local variables throughout file, warning!!!! */ ! 101: #define dst info.rti_info[RTAX_DST] ! 102: #define gate info.rti_info[RTAX_GATEWAY] ! 103: #define netmask info.rti_info[RTAX_NETMASK] ! 104: #define genmask info.rti_info[RTAX_GENMASK] ! 105: #define ifpaddr info.rti_info[RTAX_IFP] ! 106: #define ifaaddr info.rti_info[RTAX_IFA] ! 107: #define brdaddr info.rti_info[RTAX_BRD] ! 108: ! 109: /* ! 110: * It really doesn't make any sense at all for this code to share much ! 111: * with raw_usrreq.c, since its functionality is so restricted. XXX ! 112: */ ! 113: static int ! 114: rts_abort(struct socket *so) ! 115: { ! 116: int s, error; ! 117: s = splnet(); ! 118: error = raw_usrreqs.pru_abort(so); ! 119: splx(s); ! 120: return error; ! 121: } ! 122: ! 123: /* pru_accept is EOPNOTSUPP */ ! 124: ! 125: static int ! 126: rts_attach(struct socket *so, int proto, struct proc *p) ! 127: { ! 128: struct rawcb *rp; ! 129: int s, error; ! 130: ! 131: if (sotorawcb(so) != 0) ! 132: return EISCONN; /* XXX panic? */ ! 133: MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */ ! 134: if (rp == 0) ! 135: return ENOBUFS; ! 136: bzero(rp, sizeof *rp); ! 137: ! 138: /* ! 139: * The splnet() is necessary to block protocols from sending ! 140: * error notifications (like RTM_REDIRECT or RTM_LOSING) while ! 141: * this PCB is extant but incompletely initialized. ! 142: * Probably we should try to do more of this work beforehand and ! 143: * eliminate the spl. ! 144: */ ! 145: s = splnet(); ! 146: so->so_pcb = (caddr_t)rp; ! 147: error = raw_usrreqs.pru_attach(so, proto, p); ! 148: rp = sotorawcb(so); ! 149: if (error) { ! 150: splx(s); ! 151: FREE(rp, M_PCB); ! 152: return error; ! 153: } ! 154: switch(rp->rcb_proto.sp_protocol) { ! 155: case AF_INET: ! 156: route_cb.ip_count++; ! 157: break; ! 158: case AF_IPX: ! 159: route_cb.ipx_count++; ! 160: break; ! 161: case AF_NS: ! 162: route_cb.ns_count++; ! 163: break; ! 164: case AF_ISO: ! 165: route_cb.iso_count++; ! 166: break; ! 167: } ! 168: rp->rcb_faddr = &route_src; ! 169: route_cb.any_count++; ! 170: soisconnected(so); ! 171: so->so_options |= SO_USELOOPBACK; ! 172: splx(s); ! 173: return 0; ! 174: } ! 175: ! 176: static int ! 177: rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p) ! 178: { ! 179: int s, error; ! 180: s = splnet(); ! 181: error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */ ! 182: splx(s); ! 183: return error; ! 184: } ! 185: ! 186: static int ! 187: rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p) ! 188: { ! 189: int s, error; ! 190: s = splnet(); ! 191: error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */ ! 192: splx(s); ! 193: return error; ! 194: } ! 195: ! 196: /* pru_connect2 is EOPNOTSUPP */ ! 197: /* pru_control is EOPNOTSUPP */ ! 198: ! 199: static int ! 200: rts_detach(struct socket *so) ! 201: { ! 202: struct rawcb *rp = sotorawcb(so); ! 203: int s, error; ! 204: ! 205: s = splnet(); ! 206: if (rp != 0) { ! 207: switch(rp->rcb_proto.sp_protocol) { ! 208: case AF_INET: ! 209: route_cb.ip_count--; ! 210: break; ! 211: case AF_IPX: ! 212: route_cb.ipx_count--; ! 213: break; ! 214: case AF_NS: ! 215: route_cb.ns_count--; ! 216: break; ! 217: case AF_ISO: ! 218: route_cb.iso_count--; ! 219: break; ! 220: } ! 221: route_cb.any_count--; ! 222: } ! 223: error = raw_usrreqs.pru_detach(so); ! 224: splx(s); ! 225: return error; ! 226: } ! 227: ! 228: static int ! 229: rts_disconnect(struct socket *so) ! 230: { ! 231: int s, error; ! 232: s = splnet(); ! 233: error = raw_usrreqs.pru_disconnect(so); ! 234: splx(s); ! 235: return error; ! 236: } ! 237: ! 238: /* pru_listen is EOPNOTSUPP */ ! 239: ! 240: static int ! 241: rts_peeraddr(struct socket *so, struct sockaddr **nam) ! 242: { ! 243: int s, error; ! 244: s = splnet(); ! 245: error = raw_usrreqs.pru_peeraddr(so, nam); ! 246: splx(s); ! 247: return error; ! 248: } ! 249: ! 250: /* pru_rcvd is EOPNOTSUPP */ ! 251: /* pru_rcvoob is EOPNOTSUPP */ ! 252: ! 253: static int ! 254: rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, ! 255: struct mbuf *control, struct proc *p) ! 256: { ! 257: int s, error; ! 258: s = splnet(); ! 259: error = raw_usrreqs.pru_send(so, flags, m, nam, control, p); ! 260: splx(s); ! 261: return error; ! 262: } ! 263: ! 264: /* pru_sense is null */ ! 265: ! 266: static int ! 267: rts_shutdown(struct socket *so) ! 268: { ! 269: int s, error; ! 270: s = splnet(); ! 271: error = raw_usrreqs.pru_shutdown(so); ! 272: splx(s); ! 273: return error; ! 274: } ! 275: ! 276: static int ! 277: rts_sockaddr(struct socket *so, struct sockaddr **nam) ! 278: { ! 279: int s, error; ! 280: s = splnet(); ! 281: error = raw_usrreqs.pru_sockaddr(so, nam); ! 282: splx(s); ! 283: return error; ! 284: } ! 285: ! 286: static struct pr_usrreqs route_usrreqs = { ! 287: rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect, ! 288: pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect, ! 289: pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, ! 290: rts_send, pru_sense_null, rts_shutdown, rts_sockaddr, ! 291: sosend, soreceive, sopoll ! 292: }; ! 293: ! 294: /*ARGSUSED*/ ! 295: static int ! 296: route_output(m, so) ! 297: register struct mbuf *m; ! 298: struct socket *so; ! 299: { ! 300: register struct rt_msghdr *rtm = 0; ! 301: register struct rtentry *rt = 0; ! 302: struct rtentry *saved_nrt = 0; ! 303: struct radix_node_head *rnh; ! 304: struct rt_addrinfo info; ! 305: int len, error = 0; ! 306: struct ifnet *ifp = 0; ! 307: struct ifaddr *ifa = 0; ! 308: struct proc *curproc = current_proc(); ! 309: ! 310: #define senderr(e) { error = e; goto flush;} ! 311: if (m == 0 || ((m->m_len < sizeof(long)) && ! 312: (m = m_pullup(m, sizeof(long))) == 0)) ! 313: return (ENOBUFS); ! 314: if ((m->m_flags & M_PKTHDR) == 0) ! 315: panic("route_output"); ! 316: len = m->m_pkthdr.len; ! 317: if (len < sizeof(*rtm) || ! 318: len != mtod(m, struct rt_msghdr *)->rtm_msglen) { ! 319: dst = 0; ! 320: senderr(EINVAL); ! 321: } ! 322: R_Malloc(rtm, struct rt_msghdr *, len); ! 323: if (rtm == 0) { ! 324: dst = 0; ! 325: senderr(ENOBUFS); ! 326: } ! 327: m_copydata(m, 0, len, (caddr_t)rtm); ! 328: if (rtm->rtm_version != RTM_VERSION) { ! 329: dst = 0; ! 330: senderr(EPROTONOSUPPORT); ! 331: } ! 332: rtm->rtm_pid = curproc->p_pid; ! 333: info.rti_addrs = rtm->rtm_addrs; ! 334: if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) { ! 335: dst = 0; ! 336: senderr(EINVAL); ! 337: } ! 338: if (dst == 0 || (dst->sa_family >= AF_MAX) ! 339: || (gate != 0 && (gate->sa_family >= AF_MAX))) ! 340: senderr(EINVAL); ! 341: if (genmask) { ! 342: struct radix_node *t; ! 343: t = rn_addmask((caddr_t)genmask, 0, 1); ! 344: if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) ! 345: genmask = (struct sockaddr *)(t->rn_key); ! 346: else ! 347: senderr(ENOBUFS); ! 348: } ! 349: switch (rtm->rtm_type) { ! 350: ! 351: case RTM_ADD: ! 352: if (gate == 0) ! 353: senderr(EINVAL); ! 354: error = rtrequest(RTM_ADD, dst, gate, netmask, ! 355: rtm->rtm_flags, &saved_nrt); ! 356: if (error == 0 && saved_nrt) { ! 357: rt_setmetrics(rtm->rtm_inits, ! 358: &rtm->rtm_rmx, &saved_nrt->rt_rmx); ! 359: saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); ! 360: saved_nrt->rt_rmx.rmx_locks |= ! 361: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); ! 362: saved_nrt->rt_refcnt--; ! 363: saved_nrt->rt_genmask = genmask; ! 364: } ! 365: break; ! 366: ! 367: case RTM_DELETE: ! 368: error = rtrequest(RTM_DELETE, dst, gate, netmask, ! 369: rtm->rtm_flags, &saved_nrt); ! 370: if (error == 0) { ! 371: if ((rt = saved_nrt)) ! 372: rt->rt_refcnt++; ! 373: goto report; ! 374: } ! 375: break; ! 376: ! 377: case RTM_GET: ! 378: case RTM_CHANGE: ! 379: case RTM_LOCK: ! 380: if ((rnh = rt_tables[dst->sa_family]) == 0) { ! 381: senderr(EAFNOSUPPORT); ! 382: } else if (rt = (struct rtentry *) ! 383: rnh->rnh_lookup(dst, netmask, rnh)) ! 384: rt->rt_refcnt++; ! 385: else ! 386: senderr(ESRCH); ! 387: switch(rtm->rtm_type) { ! 388: ! 389: case RTM_GET: ! 390: report: ! 391: dst = rt_key(rt); ! 392: gate = rt->rt_gateway; ! 393: netmask = rt_mask(rt); ! 394: genmask = rt->rt_genmask; ! 395: if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { ! 396: ifp = rt->rt_ifp; ! 397: if (ifp) { ! 398: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; ! 399: ifaaddr = rt->rt_ifa->ifa_addr; ! 400: rtm->rtm_index = ifp->if_index; ! 401: } else { ! 402: ifpaddr = 0; ! 403: ifaaddr = 0; ! 404: } ! 405: } ! 406: len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, ! 407: (struct walkarg *)0); ! 408: if (len > rtm->rtm_msglen) { ! 409: struct rt_msghdr *new_rtm; ! 410: R_Malloc(new_rtm, struct rt_msghdr *, len); ! 411: if (new_rtm == 0) ! 412: senderr(ENOBUFS); ! 413: Bcopy(rtm, new_rtm, rtm->rtm_msglen); ! 414: Free(rtm); rtm = new_rtm; ! 415: } ! 416: (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, ! 417: (struct walkarg *)0); ! 418: rtm->rtm_flags = rt->rt_flags; ! 419: rtm->rtm_rmx = rt->rt_rmx; ! 420: rtm->rtm_addrs = info.rti_addrs; ! 421: break; ! 422: ! 423: case RTM_CHANGE: ! 424: if (gate && (error = rt_setgate(rt, rt_key(rt), gate))) ! 425: senderr(error); ! 426: ! 427: /* ! 428: * If they tried to change things but didn't specify ! 429: * the required gateway, then just use the old one. ! 430: * This can happen if the user tries to change the ! 431: * flags on the default route without changing the ! 432: * default gateway. Changing flags still doesn't work. ! 433: */ ! 434: if ((rt->rt_flags & RTF_GATEWAY) && !gate) ! 435: gate = rt->rt_gateway; ! 436: ! 437: /* new gateway could require new ifaddr, ifp; ! 438: flags may also be different; ifp may be specified ! 439: by ll sockaddr when protocol address is ambiguous */ ! 440: if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && ! 441: (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) ! 442: ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, ! 443: ifp); ! 444: else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || ! 445: (gate && (ifa = ifa_ifwithroute(rt->rt_flags, ! 446: rt_key(rt), gate)))) ! 447: ifp = ifa->ifa_ifp; ! 448: if (ifa) { ! 449: register struct ifaddr *oifa = rt->rt_ifa; ! 450: if (oifa != ifa) { ! 451: if (oifa && oifa->ifa_rtrequest) ! 452: oifa->ifa_rtrequest(RTM_DELETE, ! 453: rt, gate); ! 454: IFAFREE(rt->rt_ifa); ! 455: rt->rt_ifa = ifa; ! 456: ifa->ifa_refcnt++; ! 457: rt->rt_ifp = ifp; ! 458: rt->rt_dlt = ifa->ifa_dlt; ! 459: } ! 460: } ! 461: rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, ! 462: &rt->rt_rmx); ! 463: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) ! 464: rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); ! 465: if (genmask) ! 466: rt->rt_genmask = genmask; ! 467: /* ! 468: * Fall into ! 469: */ ! 470: case RTM_LOCK: ! 471: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); ! 472: rt->rt_rmx.rmx_locks |= ! 473: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); ! 474: break; ! 475: } ! 476: break; ! 477: ! 478: default: ! 479: senderr(EOPNOTSUPP); ! 480: } ! 481: ! 482: flush: ! 483: if (rtm) { ! 484: if (error) ! 485: rtm->rtm_errno = error; ! 486: else ! 487: rtm->rtm_flags |= RTF_DONE; ! 488: } ! 489: if (rt) ! 490: rtfree(rt); ! 491: { ! 492: register struct rawcb *rp = 0; ! 493: /* ! 494: * Check to see if we don't want our own messages. ! 495: */ ! 496: if ((so->so_options & SO_USELOOPBACK) == 0) { ! 497: if (route_cb.any_count <= 1) { ! 498: if (rtm) ! 499: Free(rtm); ! 500: m_freem(m); ! 501: return (error); ! 502: } ! 503: /* There is another listener, so construct message */ ! 504: rp = sotorawcb(so); ! 505: } ! 506: if (rtm) { ! 507: m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); ! 508: Free(rtm); ! 509: } ! 510: if (rp) ! 511: rp->rcb_proto.sp_family = 0; /* Avoid us */ ! 512: if (dst) ! 513: route_proto.sp_protocol = dst->sa_family; ! 514: raw_input(m, &route_proto, &route_src, &route_dst); ! 515: if (rp) ! 516: rp->rcb_proto.sp_family = PF_ROUTE; ! 517: } ! 518: return (error); ! 519: } ! 520: ! 521: static void ! 522: rt_setmetrics(which, in, out) ! 523: u_long which; ! 524: register struct rt_metrics *in, *out; ! 525: { ! 526: #define metric(f, e) if (which & (f)) out->e = in->e; ! 527: metric(RTV_RPIPE, rmx_recvpipe); ! 528: metric(RTV_SPIPE, rmx_sendpipe); ! 529: metric(RTV_SSTHRESH, rmx_ssthresh); ! 530: metric(RTV_RTT, rmx_rtt); ! 531: metric(RTV_RTTVAR, rmx_rttvar); ! 532: metric(RTV_HOPCOUNT, rmx_hopcount); ! 533: metric(RTV_MTU, rmx_mtu); ! 534: metric(RTV_EXPIRE, rmx_expire); ! 535: #undef metric ! 536: } ! 537: ! 538: #define ROUNDUP(a) \ ! 539: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) ! 540: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) ! 541: ! 542: ! 543: /* ! 544: * Extract the addresses of the passed sockaddrs. ! 545: * Do a little sanity checking so as to avoid bad memory references. ! 546: * This data is derived straight from userland. ! 547: */ ! 548: static int ! 549: rt_xaddrs(cp, cplim, rtinfo) ! 550: register caddr_t cp, cplim; ! 551: register struct rt_addrinfo *rtinfo; ! 552: { ! 553: register struct sockaddr *sa; ! 554: register int i; ! 555: ! 556: bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); ! 557: for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { ! 558: if ((rtinfo->rti_addrs & (1 << i)) == 0) ! 559: continue; ! 560: sa = (struct sockaddr *)cp; ! 561: /* ! 562: * It won't fit. ! 563: */ ! 564: if ( (cp + sa->sa_len) > cplim ) { ! 565: return (EINVAL); ! 566: } ! 567: ! 568: /* ! 569: * there are no more.. quit now ! 570: * If there are more bits, they are in error. ! 571: * I've seen this. route(1) can evidently generate these. ! 572: * This causes kernel to core dump. ! 573: * for compatibility, If we see this, point to a safe address. ! 574: */ ! 575: if (sa->sa_len == 0) { ! 576: rtinfo->rti_info[i] = &sa_zero; ! 577: return (0); /* should be EINVAL but for compat */ ! 578: } ! 579: ! 580: /* accept it */ ! 581: rtinfo->rti_info[i] = sa; ! 582: ADVANCE(cp, sa); ! 583: } ! 584: return (0); ! 585: } ! 586: ! 587: static struct mbuf * ! 588: rt_msg1(type, rtinfo) ! 589: int type; ! 590: register struct rt_addrinfo *rtinfo; ! 591: { ! 592: register struct rt_msghdr *rtm; ! 593: register struct mbuf *m; ! 594: register int i; ! 595: register struct sockaddr *sa; ! 596: int len, dlen; ! 597: ! 598: m = m_gethdr(M_DONTWAIT, MT_DATA); ! 599: if (m == 0) ! 600: return (m); ! 601: switch (type) { ! 602: ! 603: case RTM_DELADDR: ! 604: case RTM_NEWADDR: ! 605: len = sizeof(struct ifa_msghdr); ! 606: break; ! 607: ! 608: case RTM_DELMADDR: ! 609: case RTM_NEWMADDR: ! 610: len = sizeof(struct ifma_msghdr); ! 611: break; ! 612: ! 613: case RTM_IFINFO: ! 614: len = sizeof(struct if_msghdr); ! 615: break; ! 616: ! 617: default: ! 618: len = sizeof(struct rt_msghdr); ! 619: } ! 620: if (len > MHLEN) ! 621: panic("rt_msg1"); ! 622: m->m_pkthdr.len = m->m_len = len; ! 623: m->m_pkthdr.rcvif = 0; ! 624: rtm = mtod(m, struct rt_msghdr *); ! 625: bzero((caddr_t)rtm, len); ! 626: for (i = 0; i < RTAX_MAX; i++) { ! 627: if ((sa = rtinfo->rti_info[i]) == NULL) ! 628: continue; ! 629: rtinfo->rti_addrs |= (1 << i); ! 630: dlen = ROUNDUP(sa->sa_len); ! 631: m_copyback(m, len, dlen, (caddr_t)sa); ! 632: len += dlen; ! 633: } ! 634: if (m->m_pkthdr.len != len) { ! 635: m_freem(m); ! 636: return (NULL); ! 637: } ! 638: rtm->rtm_msglen = len; ! 639: rtm->rtm_version = RTM_VERSION; ! 640: rtm->rtm_type = type; ! 641: return (m); ! 642: } ! 643: ! 644: static int ! 645: rt_msg2(type, rtinfo, cp, w) ! 646: int type; ! 647: register struct rt_addrinfo *rtinfo; ! 648: caddr_t cp; ! 649: struct walkarg *w; ! 650: { ! 651: register int i; ! 652: int len, dlen, second_time = 0; ! 653: caddr_t cp0; ! 654: ! 655: rtinfo->rti_addrs = 0; ! 656: again: ! 657: switch (type) { ! 658: ! 659: case RTM_DELADDR: ! 660: case RTM_NEWADDR: ! 661: len = sizeof(struct ifa_msghdr); ! 662: break; ! 663: ! 664: case RTM_IFINFO: ! 665: len = sizeof(struct if_msghdr); ! 666: break; ! 667: ! 668: default: ! 669: len = sizeof(struct rt_msghdr); ! 670: } ! 671: cp0 = cp; ! 672: if (cp0) ! 673: cp += len; ! 674: for (i = 0; i < RTAX_MAX; i++) { ! 675: register struct sockaddr *sa; ! 676: ! 677: if ((sa = rtinfo->rti_info[i]) == 0) ! 678: continue; ! 679: rtinfo->rti_addrs |= (1 << i); ! 680: dlen = ROUNDUP(sa->sa_len); ! 681: if (cp) { ! 682: bcopy((caddr_t)sa, cp, (unsigned)dlen); ! 683: cp += dlen; ! 684: } ! 685: len += dlen; ! 686: } ! 687: if (cp == 0 && w != NULL && !second_time) { ! 688: register struct walkarg *rw = w; ! 689: ! 690: if (rw->w_req) { ! 691: if (rw->w_tmemsize < len) { ! 692: if (rw->w_tmem) ! 693: FREE(rw->w_tmem, M_RTABLE); ! 694: rw->w_tmem = (caddr_t) ! 695: _MALLOC(len, M_RTABLE, M_NOWAIT); ! 696: if (rw->w_tmem) ! 697: rw->w_tmemsize = len; ! 698: } ! 699: if (rw->w_tmem) { ! 700: cp = rw->w_tmem; ! 701: second_time = 1; ! 702: goto again; ! 703: } ! 704: } ! 705: } ! 706: if (cp) { ! 707: register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; ! 708: ! 709: rtm->rtm_version = RTM_VERSION; ! 710: rtm->rtm_type = type; ! 711: rtm->rtm_msglen = len; ! 712: } ! 713: return (len); ! 714: } ! 715: ! 716: /* ! 717: * This routine is called to generate a message from the routing ! 718: * socket indicating that a redirect has occured, a routing lookup ! 719: * has failed, or that a protocol has detected timeouts to a particular ! 720: * destination. ! 721: */ ! 722: void ! 723: rt_missmsg(type, rtinfo, flags, error) ! 724: int type, flags, error; ! 725: register struct rt_addrinfo *rtinfo; ! 726: { ! 727: register struct rt_msghdr *rtm; ! 728: register struct mbuf *m; ! 729: struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; ! 730: ! 731: if (route_cb.any_count == 0) ! 732: return; ! 733: m = rt_msg1(type, rtinfo); ! 734: if (m == 0) ! 735: return; ! 736: rtm = mtod(m, struct rt_msghdr *); ! 737: rtm->rtm_flags = RTF_DONE | flags; ! 738: rtm->rtm_errno = error; ! 739: rtm->rtm_addrs = rtinfo->rti_addrs; ! 740: route_proto.sp_protocol = sa ? sa->sa_family : 0; ! 741: raw_input(m, &route_proto, &route_src, &route_dst); ! 742: } ! 743: ! 744: /* ! 745: * This routine is called to generate a message from the routing ! 746: * socket indicating that the status of a network interface has changed. ! 747: */ ! 748: void ! 749: rt_ifmsg(ifp) ! 750: register struct ifnet *ifp; ! 751: { ! 752: register struct if_msghdr *ifm; ! 753: struct mbuf *m; ! 754: struct rt_addrinfo info; ! 755: ! 756: if (route_cb.any_count == 0) ! 757: return; ! 758: bzero((caddr_t)&info, sizeof(info)); ! 759: m = rt_msg1(RTM_IFINFO, &info); ! 760: if (m == 0) ! 761: return; ! 762: ifm = mtod(m, struct if_msghdr *); ! 763: ifm->ifm_index = ifp->if_index; ! 764: ifm->ifm_flags = (u_short)ifp->if_flags; ! 765: ifm->ifm_data = ifp->if_data; ! 766: ifm->ifm_addrs = 0; ! 767: route_proto.sp_protocol = 0; ! 768: raw_input(m, &route_proto, &route_src, &route_dst); ! 769: } ! 770: ! 771: /* ! 772: * This is called to generate messages from the routing socket ! 773: * indicating a network interface has had addresses associated with it. ! 774: * if we ever reverse the logic and replace messages TO the routing ! 775: * socket indicate a request to configure interfaces, then it will ! 776: * be unnecessary as the routing socket will automatically generate ! 777: * copies of it. ! 778: */ ! 779: void ! 780: rt_newaddrmsg(cmd, ifa, error, rt) ! 781: int cmd, error; ! 782: register struct ifaddr *ifa; ! 783: register struct rtentry *rt; ! 784: { ! 785: struct rt_addrinfo info; ! 786: struct sockaddr *sa = 0; ! 787: int pass; ! 788: struct mbuf *m = 0; ! 789: struct ifnet *ifp = ifa->ifa_ifp; ! 790: ! 791: if (route_cb.any_count == 0) ! 792: return; ! 793: for (pass = 1; pass < 3; pass++) { ! 794: bzero((caddr_t)&info, sizeof(info)); ! 795: if ((cmd == RTM_ADD && pass == 1) || ! 796: (cmd == RTM_DELETE && pass == 2)) { ! 797: register struct ifa_msghdr *ifam; ! 798: int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; ! 799: ! 800: ifaaddr = sa = ifa->ifa_addr; ! 801: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; ! 802: netmask = ifa->ifa_netmask; ! 803: brdaddr = ifa->ifa_dstaddr; ! 804: if ((m = rt_msg1(ncmd, &info)) == NULL) ! 805: continue; ! 806: ifam = mtod(m, struct ifa_msghdr *); ! 807: ifam->ifam_index = ifp->if_index; ! 808: ifam->ifam_metric = ifa->ifa_metric; ! 809: ifam->ifam_flags = ifa->ifa_flags; ! 810: ifam->ifam_addrs = info.rti_addrs; ! 811: } ! 812: if ((cmd == RTM_ADD && pass == 2) || ! 813: (cmd == RTM_DELETE && pass == 1)) { ! 814: register struct rt_msghdr *rtm; ! 815: ! 816: if (rt == 0) ! 817: continue; ! 818: netmask = rt_mask(rt); ! 819: dst = sa = rt_key(rt); ! 820: gate = rt->rt_gateway; ! 821: if ((m = rt_msg1(cmd, &info)) == NULL) ! 822: continue; ! 823: rtm = mtod(m, struct rt_msghdr *); ! 824: rtm->rtm_index = ifp->if_index; ! 825: rtm->rtm_flags |= rt->rt_flags; ! 826: rtm->rtm_errno = error; ! 827: rtm->rtm_addrs = info.rti_addrs; ! 828: } ! 829: route_proto.sp_protocol = sa ? sa->sa_family : 0; ! 830: raw_input(m, &route_proto, &route_src, &route_dst); ! 831: } ! 832: } ! 833: ! 834: /* ! 835: * This is the analogue to the rt_newaddrmsg which performs the same ! 836: * function but for multicast group memberhips. This is easier since ! 837: * there is no route state to worry about. ! 838: */ ! 839: void ! 840: rt_newmaddrmsg(cmd, ifma) ! 841: int cmd; ! 842: struct ifmultiaddr *ifma; ! 843: { ! 844: struct rt_addrinfo info; ! 845: struct mbuf *m = 0; ! 846: struct ifnet *ifp = ifma->ifma_ifp; ! 847: struct ifma_msghdr *ifmam; ! 848: ! 849: if (route_cb.any_count == 0) ! 850: return; ! 851: ! 852: bzero((caddr_t)&info, sizeof(info)); ! 853: ifaaddr = ifma->ifma_addr; ! 854: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; ! 855: /* ! 856: * If a link-layer address is present, present it as a ``gateway'' ! 857: * (similarly to how ARP entries, e.g., are presented). ! 858: */ ! 859: gate = ifma->ifma_lladdr; ! 860: if ((m = rt_msg1(cmd, &info)) == NULL) ! 861: return; ! 862: ifmam = mtod(m, struct ifma_msghdr *); ! 863: ifmam->ifmam_index = ifp->if_index; ! 864: ifmam->ifmam_addrs = info.rti_addrs; ! 865: route_proto.sp_protocol = ifma->ifma_addr->sa_family; ! 866: raw_input(m, &route_proto, &route_src, &route_dst); ! 867: } ! 868: ! 869: /* ! 870: * This is used in dumping the kernel table via sysctl(). ! 871: */ ! 872: int ! 873: sysctl_dumpentry(rn, vw) ! 874: struct radix_node *rn; ! 875: void *vw; ! 876: { ! 877: register struct walkarg *w = vw; ! 878: register struct rtentry *rt = (struct rtentry *)rn; ! 879: int error = 0, size; ! 880: struct rt_addrinfo info; ! 881: ! 882: if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) ! 883: return 0; ! 884: bzero((caddr_t)&info, sizeof(info)); ! 885: dst = rt_key(rt); ! 886: gate = rt->rt_gateway; ! 887: netmask = rt_mask(rt); ! 888: genmask = rt->rt_genmask; ! 889: size = rt_msg2(RTM_GET, &info, 0, w); ! 890: if (w->w_req && w->w_tmem) { ! 891: register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; ! 892: ! 893: rtm->rtm_flags = rt->rt_flags; ! 894: rtm->rtm_use = rt->rt_use; ! 895: rtm->rtm_rmx = rt->rt_rmx; ! 896: rtm->rtm_index = rt->rt_ifp->if_index; ! 897: rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; ! 898: rtm->rtm_addrs = info.rti_addrs; ! 899: error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); ! 900: return (error); ! 901: } ! 902: return (error); ! 903: } ! 904: ! 905: int ! 906: sysctl_iflist(af, w) ! 907: int af; ! 908: register struct walkarg *w; ! 909: { ! 910: register struct ifnet *ifp; ! 911: register struct ifaddr *ifa; ! 912: struct rt_addrinfo info; ! 913: int len, error = 0; ! 914: ! 915: bzero((caddr_t)&info, sizeof(info)); ! 916: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { ! 917: if (w->w_arg && w->w_arg != ifp->if_index) ! 918: continue; ! 919: ifa = ifp->if_addrhead.tqh_first; ! 920: ifpaddr = ifa->ifa_addr; ! 921: len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); ! 922: ifpaddr = 0; ! 923: if (w->w_req && w->w_tmem) { ! 924: register struct if_msghdr *ifm; ! 925: ! 926: ifm = (struct if_msghdr *)w->w_tmem; ! 927: ifm->ifm_index = ifp->if_index; ! 928: ifm->ifm_flags = (u_short)ifp->if_flags; ! 929: ifm->ifm_data = ifp->if_data; ! 930: ifm->ifm_addrs = info.rti_addrs; ! 931: error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len); ! 932: if (error) ! 933: return (error); ! 934: } ! 935: while ((ifa = ifa->ifa_link.tqe_next) != 0) { ! 936: if (af && af != ifa->ifa_addr->sa_family) ! 937: continue; ! 938: ifaaddr = ifa->ifa_addr; ! 939: netmask = ifa->ifa_netmask; ! 940: brdaddr = ifa->ifa_dstaddr; ! 941: len = rt_msg2(RTM_NEWADDR, &info, 0, w); ! 942: if (w->w_req && w->w_tmem) { ! 943: register struct ifa_msghdr *ifam; ! 944: ! 945: ifam = (struct ifa_msghdr *)w->w_tmem; ! 946: ifam->ifam_index = ifa->ifa_ifp->if_index; ! 947: ifam->ifam_flags = ifa->ifa_flags; ! 948: ifam->ifam_metric = ifa->ifa_metric; ! 949: ifam->ifam_addrs = info.rti_addrs; ! 950: error = SYSCTL_OUT(w->w_req, w->w_tmem, len); ! 951: if (error) ! 952: return (error); ! 953: } ! 954: } ! 955: ifaaddr = netmask = brdaddr = 0; ! 956: } ! 957: return (0); ! 958: } ! 959: ! 960: ! 961: static int ! 962: sysctl_rtsock SYSCTL_HANDLER_ARGS ! 963: { ! 964: int *name = (int *)arg1; ! 965: u_int namelen = arg2; ! 966: register struct radix_node_head *rnh; ! 967: int i, s, error = EINVAL; ! 968: u_char af; ! 969: struct walkarg w; ! 970: ! 971: name ++; ! 972: namelen--; ! 973: if (req->newptr) ! 974: return (EPERM); ! 975: if (namelen != 3) ! 976: return (EINVAL); ! 977: af = name[0]; ! 978: Bzero(&w, sizeof(w)); ! 979: w.w_op = name[1]; ! 980: w.w_arg = name[2]; ! 981: w.w_req = req; ! 982: ! 983: s = splnet(); ! 984: switch (w.w_op) { ! 985: ! 986: case NET_RT_DUMP: ! 987: case NET_RT_FLAGS: ! 988: for (i = 1; i <= AF_MAX; i++) ! 989: if ((rnh = rt_tables[i]) && (af == 0 || af == i) && ! 990: (error = rnh->rnh_walktree(rnh, ! 991: sysctl_dumpentry, &w))) ! 992: break; ! 993: break; ! 994: ! 995: case NET_RT_IFLIST: ! 996: error = sysctl_iflist(af, &w); ! 997: } ! 998: splx(s); ! 999: if (w.w_tmem) ! 1000: FREE(w.w_tmem, M_RTABLE); ! 1001: return (error); ! 1002: } ! 1003: ! 1004: SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, ""); ! 1005: ! 1006: ! 1007: ! 1008: /* ! 1009: * Definitions of protocols supported in the ROUTE domain. ! 1010: */ ! 1011: ! 1012: struct domain routedomain; /* or at least forward */ ! 1013: ! 1014: ! 1015: static struct protosw routesw[] = { ! 1016: { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, ! 1017: 0, route_output, raw_ctlinput, 0, ! 1018: 0, ! 1019: raw_init, 0, 0, 0, ! 1020: 0, &route_usrreqs, 0, 0 ! 1021: } ! 1022: }; ! 1023: ! 1024: struct domain routedomain = ! 1025: { PF_ROUTE, "route", route_init, 0, 0, ! 1026: routesw}; ! 1027: ! 1028: DOMAIN_SET(route);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.