|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1988, 1991, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)rtsock.c 8.6 (Berkeley) 2/11/95 ! 59: */ ! 60: ! 61: #include <sys/param.h> ! 62: #include <sys/systm.h> ! 63: #include <sys/proc.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: #include <sys/malloc.h> ! 70: ! 71: #include <net/if.h> ! 72: #include <net/route.h> ! 73: #include <net/raw_cb.h> ! 74: ! 75: struct route_cb route_cb; ! 76: struct sockaddr route_dst = { 2, PF_ROUTE, }; ! 77: struct sockaddr route_src = { 2, PF_ROUTE, }; ! 78: struct sockproto route_proto = { PF_ROUTE, }; ! 79: ! 80: struct walkarg { ! 81: int w_op, w_arg, w_given, w_needed, w_tmemsize; ! 82: caddr_t w_where, w_tmem; ! 83: }; ! 84: ! 85: static struct mbuf * ! 86: rt_msg1 __P((int, struct rt_addrinfo *)); ! 87: static int rt_msg2 __P((int, ! 88: struct rt_addrinfo *, caddr_t, struct walkarg *)); ! 89: static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); ! 90: ! 91: /* Sleazy use of local variables throughout file, warning!!!! */ ! 92: #define dst info.rti_info[RTAX_DST] ! 93: #define gate info.rti_info[RTAX_GATEWAY] ! 94: #define netmask info.rti_info[RTAX_NETMASK] ! 95: #define genmask info.rti_info[RTAX_GENMASK] ! 96: #define ifpaddr info.rti_info[RTAX_IFP] ! 97: #define ifaaddr info.rti_info[RTAX_IFA] ! 98: #define brdaddr info.rti_info[RTAX_BRD] ! 99: ! 100: /*ARGSUSED*/ ! 101: int ! 102: route_usrreq(so, req, m, nam, control) ! 103: register struct socket *so; ! 104: int req; ! 105: struct mbuf *m, *nam, *control; ! 106: { ! 107: register int error = 0; ! 108: register struct rawcb *rp = sotorawcb(so); ! 109: int s; ! 110: ! 111: if (req == PRU_ATTACH) { ! 112: MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); ! 113: if (so->so_pcb = (caddr_t)rp) ! 114: bzero(so->so_pcb, sizeof(*rp)); ! 115: ! 116: } ! 117: if (req == PRU_DETACH && rp) { ! 118: int af = rp->rcb_proto.sp_protocol; ! 119: if (af == AF_INET) ! 120: route_cb.ip_count--; ! 121: else if (af == AF_NS) ! 122: route_cb.ns_count--; ! 123: else if (af == AF_ISO) ! 124: route_cb.iso_count--; ! 125: route_cb.any_count--; ! 126: } ! 127: s = splnet(); ! 128: error = raw_usrreq(so, req, m, nam, control); ! 129: rp = sotorawcb(so); ! 130: if (req == PRU_ATTACH && rp) { ! 131: int af = rp->rcb_proto.sp_protocol; ! 132: if (error) { ! 133: _FREE((caddr_t)rp, M_PCB); ! 134: splx(s); ! 135: return (error); ! 136: } ! 137: if (af == AF_INET) ! 138: route_cb.ip_count++; ! 139: else if (af == AF_NS) ! 140: route_cb.ns_count++; ! 141: else if (af == AF_ISO) ! 142: route_cb.iso_count++; ! 143: rp->rcb_faddr = &route_src; ! 144: route_cb.any_count++; ! 145: soisconnected(so); ! 146: so->so_options |= SO_USELOOPBACK; ! 147: } ! 148: splx(s); ! 149: return (error); ! 150: } ! 151: ! 152: void m_copyback(struct mbuf *, int, int, caddr_t); ! 153: ! 154: /*ARGSUSED*/ ! 155: int ! 156: route_output(m, so) ! 157: register struct mbuf *m; ! 158: struct socket *so; ! 159: { ! 160: register struct rt_msghdr *rtm = 0; ! 161: register struct rtentry *rt = 0; ! 162: struct rtentry *saved_nrt = 0; ! 163: struct radix_node_head *rnh; ! 164: struct rt_addrinfo info; ! 165: int len, error = 0; ! 166: struct ifnet *ifp = 0; ! 167: struct ifaddr *ifa = 0; ! 168: ! 169: #define senderr(e) { error = e; goto flush;} ! 170: if (m == 0 || ((m->m_len < sizeof(int32_t)) && ! 171: (m = m_pullup(m, sizeof(int32_t))) == 0)) ! 172: return (ENOBUFS); ! 173: if ((m->m_flags & M_PKTHDR) == 0) ! 174: panic("route_output"); ! 175: len = m->m_pkthdr.len; ! 176: if (len < sizeof(*rtm) || ! 177: len != mtod(m, struct rt_msghdr *)->rtm_msglen) { ! 178: dst = 0; ! 179: senderr(EINVAL); ! 180: } ! 181: R_Malloc(rtm, struct rt_msghdr *, len); ! 182: if (rtm == 0) { ! 183: dst = 0; ! 184: senderr(ENOBUFS); ! 185: } ! 186: m_copydata(m, 0, len, (caddr_t)rtm); ! 187: if (rtm->rtm_version != RTM_VERSION) { ! 188: dst = 0; ! 189: senderr(EPROTONOSUPPORT); ! 190: } ! 191: rtm->rtm_pid = current_proc()->p_pid; ! 192: info.rti_addrs = rtm->rtm_addrs; ! 193: rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); ! 194: if (dst == 0) ! 195: senderr(EINVAL); ! 196: if (genmask) { ! 197: struct radix_node *t; ! 198: t = rn_addmask((caddr_t)genmask, 0, 1); ! 199: if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) ! 200: genmask = (struct sockaddr *)(t->rn_key); ! 201: else ! 202: senderr(ENOBUFS); ! 203: } ! 204: switch (rtm->rtm_type) { ! 205: ! 206: case RTM_ADD: ! 207: if (gate == 0) ! 208: senderr(EINVAL); ! 209: error = rtrequest(RTM_ADD, dst, gate, netmask, ! 210: rtm->rtm_flags, &saved_nrt); ! 211: if (error == 0 && saved_nrt) { ! 212: rt_setmetrics(rtm->rtm_inits, ! 213: &rtm->rtm_rmx, &saved_nrt->rt_rmx); ! 214: saved_nrt->rt_refcnt--; ! 215: saved_nrt->rt_genmask = genmask; ! 216: } ! 217: break; ! 218: ! 219: case RTM_DELETE: ! 220: error = rtrequest(RTM_DELETE, dst, gate, netmask, ! 221: rtm->rtm_flags, &saved_nrt); ! 222: if (error == 0) { ! 223: (rt = saved_nrt)->rt_refcnt++; ! 224: goto report; ! 225: } ! 226: break; ! 227: ! 228: case RTM_GET: ! 229: case RTM_CHANGE: ! 230: case RTM_LOCK: ! 231: if ((rnh = rt_tables[dst->sa_family]) == 0) { ! 232: senderr(EAFNOSUPPORT); ! 233: } else if (rt = (struct rtentry *) ! 234: rnh->rnh_lookup(dst, netmask, rnh)) ! 235: rt->rt_refcnt++; ! 236: else ! 237: senderr(ESRCH); ! 238: switch(rtm->rtm_type) { ! 239: ! 240: case RTM_GET: ! 241: report: ! 242: dst = rt_key(rt); ! 243: gate = rt->rt_gateway; ! 244: netmask = rt_mask(rt); ! 245: genmask = rt->rt_genmask; ! 246: if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { ! 247: if (ifp = rt->rt_ifp) { ! 248: ifpaddr = ifp->if_addrlist->ifa_addr; ! 249: ifaaddr = rt->rt_ifa->ifa_addr; ! 250: if (ifp->if_flags & IFF_POINTOPOINT) ! 251: brdaddr = rt->rt_ifa->ifa_dstaddr; ! 252: else ! 253: brdaddr = 0; ! 254: rtm->rtm_index = ifp->if_index; ! 255: } else { ! 256: ifpaddr = 0; ! 257: ifaaddr = 0; ! 258: } ! 259: } ! 260: len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, ! 261: (struct walkarg *)0); ! 262: if (len > rtm->rtm_msglen) { ! 263: struct rt_msghdr *new_rtm; ! 264: R_Malloc(new_rtm, struct rt_msghdr *, len); ! 265: if (new_rtm == 0) ! 266: senderr(ENOBUFS); ! 267: Bcopy(rtm, new_rtm, rtm->rtm_msglen); ! 268: Free(rtm); rtm = new_rtm; ! 269: } ! 270: (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, ! 271: (struct walkarg *)0); ! 272: rtm->rtm_flags = rt->rt_flags; ! 273: rtm->rtm_rmx = rt->rt_rmx; ! 274: rtm->rtm_addrs = info.rti_addrs; ! 275: break; ! 276: ! 277: case RTM_CHANGE: ! 278: if (gate && rt_setgate(rt, rt_key(rt), gate)) ! 279: senderr(EDQUOT); ! 280: /* new gateway could require new ifaddr, ifp; ! 281: flags may also be different; ifp may be specified ! 282: by ll sockaddr when protocol address is ambiguous */ ! 283: if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && ! 284: (ifp = ifa->ifa_ifp)) ! 285: ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, ! 286: ifp); ! 287: else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || ! 288: (ifa = ifa_ifwithroute(rt->rt_flags, ! 289: rt_key(rt), gate))) ! 290: ifp = ifa->ifa_ifp; ! 291: if (ifa) { ! 292: register struct ifaddr *oifa = rt->rt_ifa; ! 293: if (oifa != ifa) { ! 294: if (oifa && oifa->ifa_rtrequest) ! 295: oifa->ifa_rtrequest(RTM_DELETE, ! 296: rt, gate); ! 297: IFAFREE(rt->rt_ifa); ! 298: rt->rt_ifa = ifa; ! 299: ifa->ifa_refcnt++; ! 300: rt->rt_ifp = ifp; ! 301: } ! 302: } ! 303: rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, ! 304: &rt->rt_rmx); ! 305: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) ! 306: rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); ! 307: if (genmask) ! 308: rt->rt_genmask = genmask; ! 309: /* ! 310: * Fall into ! 311: */ ! 312: case RTM_LOCK: ! 313: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); ! 314: rt->rt_rmx.rmx_locks |= ! 315: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); ! 316: break; ! 317: } ! 318: break; ! 319: ! 320: default: ! 321: senderr(EOPNOTSUPP); ! 322: } ! 323: ! 324: flush: ! 325: if (rtm) { ! 326: if (error) ! 327: rtm->rtm_errno = error; ! 328: else ! 329: rtm->rtm_flags |= RTF_DONE; ! 330: } ! 331: if (rt) ! 332: rtfree(rt); ! 333: { ! 334: register struct rawcb *rp = 0; ! 335: /* ! 336: * Check to see if we don't want our own messages. ! 337: */ ! 338: if ((so->so_options & SO_USELOOPBACK) == 0) { ! 339: if (route_cb.any_count <= 1) { ! 340: if (rtm) ! 341: Free(rtm); ! 342: m_freem(m); ! 343: return (error); ! 344: } ! 345: /* There is another listener, so construct message */ ! 346: rp = sotorawcb(so); ! 347: } ! 348: if (rtm) { ! 349: m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); ! 350: Free(rtm); ! 351: } ! 352: if (rp) ! 353: rp->rcb_proto.sp_family = 0; /* Avoid us */ ! 354: if (dst) ! 355: route_proto.sp_protocol = dst->sa_family; ! 356: raw_input(m, &route_proto, &route_src, &route_dst); ! 357: if (rp) ! 358: rp->rcb_proto.sp_family = PF_ROUTE; ! 359: } ! 360: return (error); ! 361: } ! 362: ! 363: void ! 364: rt_setmetrics(which, in, out) ! 365: u_long which; ! 366: register struct rt_metrics *in, *out; ! 367: { ! 368: #define metric(f, e) if (which & (f)) out->e = in->e; ! 369: metric(RTV_RPIPE, rmx_recvpipe); ! 370: metric(RTV_SPIPE, rmx_sendpipe); ! 371: metric(RTV_SSTHRESH, rmx_ssthresh); ! 372: metric(RTV_RTT, rmx_rtt); ! 373: metric(RTV_RTTVAR, rmx_rttvar); ! 374: metric(RTV_HOPCOUNT, rmx_hopcount); ! 375: metric(RTV_MTU, rmx_mtu); ! 376: metric(RTV_EXPIRE, rmx_expire); ! 377: #undef metric ! 378: } ! 379: ! 380: #define ROUNDUP(a) \ ! 381: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) ! 382: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) ! 383: ! 384: static void ! 385: rt_xaddrs(cp, cplim, rtinfo) ! 386: register caddr_t cp, cplim; ! 387: register struct rt_addrinfo *rtinfo; ! 388: { ! 389: register struct sockaddr *sa; ! 390: register int i; ! 391: ! 392: bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); ! 393: for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { ! 394: if ((rtinfo->rti_addrs & (1 << i)) == 0) ! 395: continue; ! 396: rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; ! 397: ADVANCE(cp, sa); ! 398: } ! 399: } ! 400: ! 401: /* ! 402: * Copy data from a buffer back into the indicated mbuf chain, ! 403: * starting "off" bytes from the beginning, extending the mbuf ! 404: * chain if necessary. ! 405: */ ! 406: void ! 407: m_copyback(m0, off, len, cp) ! 408: struct mbuf *m0; ! 409: register int off; ! 410: register int len; ! 411: caddr_t cp; ! 412: { ! 413: register int mlen; ! 414: register struct mbuf *m = m0, *n; ! 415: int totlen = 0; ! 416: ! 417: if (m0 == 0) ! 418: return; ! 419: while (off > (mlen = m->m_len)) { ! 420: off -= mlen; ! 421: totlen += mlen; ! 422: if (m->m_next == 0) { ! 423: n = m_getclr(M_DONTWAIT, m->m_type); ! 424: if (n == 0) ! 425: goto out; ! 426: n->m_len = min(MLEN, len + off); ! 427: m->m_next = n; ! 428: } ! 429: m = m->m_next; ! 430: } ! 431: while (len > 0) { ! 432: mlen = min (m->m_len - off, len); ! 433: bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); ! 434: cp += mlen; ! 435: len -= mlen; ! 436: mlen += off; ! 437: off = 0; ! 438: totlen += mlen; ! 439: if (len == 0) ! 440: break; ! 441: if (m->m_next == 0) { ! 442: n = m_get(M_DONTWAIT, m->m_type); ! 443: if (n == 0) ! 444: break; ! 445: n->m_len = min(MLEN, len); ! 446: m->m_next = n; ! 447: } ! 448: m = m->m_next; ! 449: } ! 450: out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) ! 451: m->m_pkthdr.len = totlen; ! 452: } ! 453: ! 454: static struct mbuf * ! 455: rt_msg1(type, rtinfo) ! 456: int type; ! 457: register struct rt_addrinfo *rtinfo; ! 458: { ! 459: register struct rt_msghdr *rtm; ! 460: register struct mbuf *m; ! 461: register int i; ! 462: register struct sockaddr *sa; ! 463: int len, dlen; ! 464: ! 465: m = m_gethdr(M_DONTWAIT, MT_DATA); ! 466: if (m == 0) ! 467: return (m); ! 468: switch (type) { ! 469: ! 470: case RTM_DELADDR: ! 471: case RTM_NEWADDR: ! 472: len = sizeof(struct ifa_msghdr); ! 473: break; ! 474: ! 475: case RTM_IFINFO: ! 476: len = sizeof(struct if_msghdr); ! 477: break; ! 478: ! 479: default: ! 480: len = sizeof(struct rt_msghdr); ! 481: } ! 482: if (len > MHLEN) ! 483: panic("rt_msg1"); ! 484: m->m_pkthdr.len = m->m_len = len; ! 485: m->m_pkthdr.rcvif = 0; ! 486: rtm = mtod(m, struct rt_msghdr *); ! 487: bzero((caddr_t)rtm, len); ! 488: for (i = 0; i < RTAX_MAX; i++) { ! 489: if ((sa = rtinfo->rti_info[i]) == NULL) ! 490: continue; ! 491: rtinfo->rti_addrs |= (1 << i); ! 492: dlen = ROUNDUP(sa->sa_len); ! 493: m_copyback(m, len, dlen, (caddr_t)sa); ! 494: len += dlen; ! 495: } ! 496: if (m->m_pkthdr.len != len) { ! 497: m_freem(m); ! 498: return (NULL); ! 499: } ! 500: rtm->rtm_msglen = len; ! 501: rtm->rtm_version = RTM_VERSION; ! 502: rtm->rtm_type = type; ! 503: return (m); ! 504: } ! 505: ! 506: static int ! 507: rt_msg2(type, rtinfo, cp, w) ! 508: int type; ! 509: register struct rt_addrinfo *rtinfo; ! 510: caddr_t cp; ! 511: struct walkarg *w; ! 512: { ! 513: register int i; ! 514: int len, dlen, second_time = 0; ! 515: caddr_t cp0; ! 516: ! 517: rtinfo->rti_addrs = 0; ! 518: again: ! 519: switch (type) { ! 520: ! 521: case RTM_DELADDR: ! 522: case RTM_NEWADDR: ! 523: len = sizeof(struct ifa_msghdr); ! 524: break; ! 525: ! 526: case RTM_IFINFO: ! 527: len = sizeof(struct if_msghdr); ! 528: break; ! 529: ! 530: default: ! 531: len = sizeof(struct rt_msghdr); ! 532: } ! 533: if (cp0 = cp) ! 534: cp += len; ! 535: for (i = 0; i < RTAX_MAX; i++) { ! 536: register struct sockaddr *sa; ! 537: ! 538: if ((sa = rtinfo->rti_info[i]) == 0) ! 539: continue; ! 540: rtinfo->rti_addrs |= (1 << i); ! 541: dlen = ROUNDUP(sa->sa_len); ! 542: if (cp) { ! 543: bcopy((caddr_t)sa, cp, (unsigned)dlen); ! 544: cp += dlen; ! 545: } ! 546: len += dlen; ! 547: } ! 548: if (cp == 0 && w != NULL && !second_time) { ! 549: register struct walkarg *rw = w; ! 550: ! 551: rw->w_needed += len; ! 552: if (rw->w_needed <= 0 && rw->w_where) { ! 553: if (rw->w_tmemsize < len) { ! 554: if (rw->w_tmem) ! 555: _FREE(rw->w_tmem, M_RTABLE); ! 556: if (rw->w_tmem = (caddr_t) ! 557: _MALLOC(len, M_RTABLE, M_NOWAIT)) ! 558: rw->w_tmemsize = len; ! 559: } ! 560: if (rw->w_tmem) { ! 561: cp = rw->w_tmem; ! 562: second_time = 1; ! 563: goto again; ! 564: } else ! 565: rw->w_where = 0; ! 566: } ! 567: } ! 568: if (cp) { ! 569: register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; ! 570: ! 571: rtm->rtm_version = RTM_VERSION; ! 572: rtm->rtm_type = type; ! 573: rtm->rtm_msglen = len; ! 574: } ! 575: return (len); ! 576: } ! 577: ! 578: /* ! 579: * This routine is called to generate a message from the routing ! 580: * socket indicating that a redirect has occured, a routing lookup ! 581: * has failed, or that a protocol has detected timeouts to a particular ! 582: * destination. ! 583: */ ! 584: void ! 585: rt_missmsg(type, rtinfo, flags, error) ! 586: int type, flags, error; ! 587: register struct rt_addrinfo *rtinfo; ! 588: { ! 589: register struct rt_msghdr *rtm; ! 590: register struct mbuf *m; ! 591: struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; ! 592: ! 593: if (route_cb.any_count == 0) ! 594: return; ! 595: m = rt_msg1(type, rtinfo); ! 596: if (m == 0) ! 597: return; ! 598: rtm = mtod(m, struct rt_msghdr *); ! 599: rtm->rtm_flags = RTF_DONE | flags; ! 600: rtm->rtm_errno = error; ! 601: rtm->rtm_addrs = rtinfo->rti_addrs; ! 602: route_proto.sp_protocol = sa ? sa->sa_family : 0; ! 603: raw_input(m, &route_proto, &route_src, &route_dst); ! 604: } ! 605: ! 606: /* ! 607: * This routine is called to generate a message from the routing ! 608: * socket indicating that the status of a network interface has changed. ! 609: */ ! 610: void ! 611: rt_ifmsg(ifp) ! 612: register struct ifnet *ifp; ! 613: { ! 614: register struct if_msghdr *ifm; ! 615: struct mbuf *m; ! 616: struct rt_addrinfo info; ! 617: ! 618: if (route_cb.any_count == 0) ! 619: return; ! 620: bzero((caddr_t)&info, sizeof(info)); ! 621: m = rt_msg1(RTM_IFINFO, &info); ! 622: if (m == 0) ! 623: return; ! 624: ifm = mtod(m, struct if_msghdr *); ! 625: ifm->ifm_index = ifp->if_index; ! 626: ifm->ifm_flags = ifp->if_flags; ! 627: ifm->ifm_data = ifp->if_data; ! 628: ifm->ifm_addrs = 0; ! 629: route_proto.sp_protocol = 0; ! 630: raw_input(m, &route_proto, &route_src, &route_dst); ! 631: } ! 632: ! 633: /* ! 634: * This is called to generate messages from the routing socket ! 635: * indicating a network interface has had addresses associated with it. ! 636: * if we ever reverse the logic and replace messages TO the routing ! 637: * socket indicate a request to configure interfaces, then it will ! 638: * be unnecessary as the routing socket will automatically generate ! 639: * copies of it. ! 640: */ ! 641: void ! 642: rt_newaddrmsg(cmd, ifa, error, rt) ! 643: int cmd, error; ! 644: register struct ifaddr *ifa; ! 645: register struct rtentry *rt; ! 646: { ! 647: struct rt_addrinfo info; ! 648: struct sockaddr *sa; ! 649: int pass; ! 650: struct mbuf *m; ! 651: struct ifnet *ifp = ifa->ifa_ifp; ! 652: ! 653: if (route_cb.any_count == 0) ! 654: return; ! 655: for (pass = 1; pass < 3; pass++) { ! 656: bzero((caddr_t)&info, sizeof(info)); ! 657: if ((cmd == RTM_ADD && pass == 1) || ! 658: (cmd == RTM_DELETE && pass == 2)) { ! 659: register struct ifa_msghdr *ifam; ! 660: int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; ! 661: ! 662: ifaaddr = sa = ifa->ifa_addr; ! 663: ifpaddr = ifp->if_addrlist->ifa_addr; ! 664: netmask = ifa->ifa_netmask; ! 665: brdaddr = ifa->ifa_dstaddr; ! 666: if ((m = rt_msg1(ncmd, &info)) == NULL) ! 667: continue; ! 668: ifam = mtod(m, struct ifa_msghdr *); ! 669: ifam->ifam_index = ifp->if_index; ! 670: ifam->ifam_metric = ifa->ifa_metric; ! 671: ifam->ifam_flags = ifa->ifa_flags; ! 672: ifam->ifam_addrs = info.rti_addrs; ! 673: } ! 674: if ((cmd == RTM_ADD && pass == 2) || ! 675: (cmd == RTM_DELETE && pass == 1)) { ! 676: register struct rt_msghdr *rtm; ! 677: ! 678: if (rt == 0) ! 679: continue; ! 680: netmask = rt_mask(rt); ! 681: dst = sa = rt_key(rt); ! 682: gate = rt->rt_gateway; ! 683: if ((m = rt_msg1(cmd, &info)) == NULL) ! 684: continue; ! 685: rtm = mtod(m, struct rt_msghdr *); ! 686: rtm->rtm_index = ifp->if_index; ! 687: rtm->rtm_flags |= rt->rt_flags; ! 688: rtm->rtm_errno = error; ! 689: rtm->rtm_addrs = info.rti_addrs; ! 690: } ! 691: route_proto.sp_protocol = sa ? sa->sa_family : 0; ! 692: raw_input(m, &route_proto, &route_src, &route_dst); ! 693: } ! 694: } ! 695: ! 696: /* ! 697: * This is used in dumping the kernel table via sysctl(). ! 698: */ ! 699: int ! 700: sysctl_dumpentry(rn, w) ! 701: struct radix_node *rn; ! 702: register struct walkarg *w; ! 703: { ! 704: register struct rtentry *rt = (struct rtentry *)rn; ! 705: int error = 0, size; ! 706: struct rt_addrinfo info; ! 707: ! 708: if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) ! 709: return 0; ! 710: bzero((caddr_t)&info, sizeof(info)); ! 711: dst = rt_key(rt); ! 712: gate = rt->rt_gateway; ! 713: netmask = rt_mask(rt); ! 714: genmask = rt->rt_genmask; ! 715: if (rt->rt_ifp) { ! 716: ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr; ! 717: ifaaddr = rt->rt_ifa->ifa_addr; ! 718: if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) ! 719: brdaddr = rt->rt_ifa->ifa_dstaddr; ! 720: } ! 721: size = rt_msg2(RTM_GET, &info, 0, w); ! 722: if (w->w_where && w->w_tmem) { ! 723: register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; ! 724: ! 725: rtm->rtm_flags = rt->rt_flags; ! 726: rtm->rtm_use = rt->rt_use; ! 727: rtm->rtm_rmx = rt->rt_rmx; ! 728: rtm->rtm_index = rt->rt_ifp->if_index; ! 729: rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; ! 730: rtm->rtm_addrs = info.rti_addrs; ! 731: if (error = copyout((caddr_t)rtm, w->w_where, size)) ! 732: w->w_where = NULL; ! 733: else ! 734: w->w_where += size; ! 735: } ! 736: return (error); ! 737: } ! 738: ! 739: int ! 740: sysctl_iflist(af, w) ! 741: int af; ! 742: register struct walkarg *w; ! 743: { ! 744: register struct ifnet *ifp; ! 745: register struct ifaddr *ifa; ! 746: struct rt_addrinfo info; ! 747: int len, error = 0; ! 748: ! 749: bzero((caddr_t)&info, sizeof(info)); ! 750: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 751: if (w->w_arg && w->w_arg != ifp->if_index) ! 752: continue; ! 753: ifa = ifp->if_addrlist; ! 754: ifpaddr = ifa->ifa_addr; ! 755: len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); ! 756: ifpaddr = 0; ! 757: if (w->w_where && w->w_tmem) { ! 758: register struct if_msghdr *ifm; ! 759: ! 760: ifm = (struct if_msghdr *)w->w_tmem; ! 761: ifm->ifm_index = ifp->if_index; ! 762: ifm->ifm_flags = ifp->if_flags; ! 763: ifm->ifm_data = ifp->if_data; ! 764: ifm->ifm_addrs = info.rti_addrs; ! 765: if (error = copyout((caddr_t)ifm, w->w_where, len)) ! 766: return (error); ! 767: w->w_where += len; ! 768: } ! 769: while (ifa = ifa->ifa_next) { ! 770: if (af && af != ifa->ifa_addr->sa_family) ! 771: continue; ! 772: ifaaddr = ifa->ifa_addr; ! 773: netmask = ifa->ifa_netmask; ! 774: brdaddr = ifa->ifa_dstaddr; ! 775: len = rt_msg2(RTM_NEWADDR, &info, 0, w); ! 776: if (w->w_where && w->w_tmem) { ! 777: register struct ifa_msghdr *ifam; ! 778: ! 779: ifam = (struct ifa_msghdr *)w->w_tmem; ! 780: ifam->ifam_index = ifa->ifa_ifp->if_index; ! 781: ifam->ifam_flags = ifa->ifa_flags; ! 782: ifam->ifam_metric = ifa->ifa_metric; ! 783: ifam->ifam_addrs = info.rti_addrs; ! 784: if (error = copyout(w->w_tmem, w->w_where, len)) ! 785: return (error); ! 786: w->w_where += len; ! 787: } ! 788: } ! 789: ifaaddr = netmask = brdaddr = 0; ! 790: } ! 791: return (0); ! 792: } ! 793: ! 794: int ! 795: sysctl_rtable(name, namelen, where, given, new, newlen) ! 796: int *name; ! 797: int namelen; ! 798: caddr_t where; ! 799: size_t *given; ! 800: caddr_t *new; ! 801: size_t newlen; ! 802: { ! 803: register struct radix_node_head *rnh; ! 804: int i, s, error = EINVAL; ! 805: u_char af; ! 806: struct walkarg w; ! 807: ! 808: if (new) ! 809: return (EPERM); ! 810: if (namelen != 3) ! 811: return (EINVAL); ! 812: af = name[0]; ! 813: Bzero(&w, sizeof(w)); ! 814: w.w_where = where; ! 815: w.w_given = *given; ! 816: w.w_needed = 0 - w.w_given; ! 817: w.w_op = name[1]; ! 818: w.w_arg = name[2]; ! 819: ! 820: s = splnet(); ! 821: switch (w.w_op) { ! 822: ! 823: case NET_RT_DUMP: ! 824: case NET_RT_FLAGS: ! 825: for (i = 1; i <= AF_MAX; i++) ! 826: if ((rnh = rt_tables[i]) && (af == 0 || af == i) && ! 827: (error = rnh->rnh_walktree(rnh, ! 828: sysctl_dumpentry, &w))) ! 829: break; ! 830: break; ! 831: ! 832: case NET_RT_IFLIST: ! 833: error = sysctl_iflist(af, &w); ! 834: } ! 835: splx(s); ! 836: if (w.w_tmem) ! 837: _FREE(w.w_tmem, M_RTABLE); ! 838: w.w_needed += w.w_given; ! 839: if (where) { ! 840: *given = w.w_where - where; ! 841: if (*given < w.w_needed) ! 842: return (ENOMEM); ! 843: } else { ! 844: *given = (11 * w.w_needed) / 10; ! 845: } ! 846: return (error); ! 847: } ! 848: ! 849: /* ! 850: * Definitions of protocols supported in the ROUTE domain. ! 851: */ ! 852: ! 853: extern struct domain routedomain; /* or at least forward */ ! 854: ! 855: struct protosw routesw[] = { ! 856: { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, ! 857: raw_input, route_output, raw_ctlinput, 0, ! 858: route_usrreq, ! 859: raw_init, 0, 0, 0, ! 860: sysctl_rtable, ! 861: } ! 862: }; ! 863: ! 864: struct domain routedomain = ! 865: { PF_ROUTE, "route", route_init, 0, 0, ! 866: routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.