|
|
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: /* ! 26: * Copyright (c) 1984, 1985, 1986, 1987, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)ns_pcb.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: #include <sys/param.h> ! 61: #include <sys/systm.h> ! 62: #include <sys/mbuf.h> ! 63: #include <sys/errno.h> ! 64: #include <sys/socket.h> ! 65: #include <sys/socketvar.h> ! 66: #include <sys/protosw.h> ! 67: ! 68: #include <net/if.h> ! 69: #include <net/route.h> ! 70: ! 71: #include <netns/ns.h> ! 72: #include <netns/ns_if.h> ! 73: #include <netns/ns_pcb.h> ! 74: ! 75: struct ns_addr zerons_addr; ! 76: ! 77: ns_pcballoc(so, head) ! 78: struct socket *so; ! 79: struct nspcb *head; ! 80: { ! 81: struct mbuf *m; ! 82: register struct nspcb *nsp; ! 83: ! 84: m = m_getclr(M_DONTWAIT, MT_PCB); ! 85: if (m == NULL) ! 86: return (ENOBUFS); ! 87: nsp = mtod(m, struct nspcb *); ! 88: nsp->nsp_socket = so; ! 89: insque(nsp, head); ! 90: so->so_pcb = (caddr_t)nsp; ! 91: return (0); ! 92: } ! 93: ! 94: ns_pcbbind(nsp, nam) ! 95: register struct nspcb *nsp; ! 96: struct mbuf *nam; ! 97: { ! 98: register struct sockaddr_ns *sns; ! 99: u_short lport = 0; ! 100: ! 101: if (nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr)) ! 102: return (EINVAL); ! 103: if (nam == 0) ! 104: goto noname; ! 105: sns = mtod(nam, struct sockaddr_ns *); ! 106: if (nam->m_len != sizeof (*sns)) ! 107: return (EINVAL); ! 108: if (!ns_nullhost(sns->sns_addr)) { ! 109: int tport = sns->sns_port; ! 110: ! 111: sns->sns_port = 0; /* yech... */ ! 112: if (ifa_ifwithaddr((struct sockaddr *)sns) == 0) ! 113: return (EADDRNOTAVAIL); ! 114: sns->sns_port = tport; ! 115: } ! 116: lport = sns->sns_port; ! 117: if (lport) { ! 118: u_short aport = ntohs(lport); ! 119: ! 120: if (aport < NSPORT_RESERVED && ! 121: (nsp->nsp_socket->so_state & SS_PRIV) == 0) ! 122: return (EACCES); ! 123: if (ns_pcblookup(&zerons_addr, lport, 0)) ! 124: return (EADDRINUSE); ! 125: } ! 126: nsp->nsp_laddr = sns->sns_addr; ! 127: noname: ! 128: if (lport == 0) ! 129: do { ! 130: if (nspcb.nsp_lport++ < NSPORT_RESERVED) ! 131: nspcb.nsp_lport = NSPORT_RESERVED; ! 132: lport = htons(nspcb.nsp_lport); ! 133: } while (ns_pcblookup(&zerons_addr, lport, 0)); ! 134: nsp->nsp_lport = lport; ! 135: return (0); ! 136: } ! 137: ! 138: /* ! 139: * Connect from a socket to a specified address. ! 140: * Both address and port must be specified in argument sns. ! 141: * If don't have a local address for this socket yet, ! 142: * then pick one. ! 143: */ ! 144: ns_pcbconnect(nsp, nam) ! 145: struct nspcb *nsp; ! 146: struct mbuf *nam; ! 147: { ! 148: struct ns_ifaddr *ia; ! 149: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); ! 150: register struct ns_addr *dst; ! 151: register struct route *ro; ! 152: struct ifnet *ifp; ! 153: ! 154: if (nam->m_len != sizeof (*sns)) ! 155: return (EINVAL); ! 156: if (sns->sns_family != AF_NS) ! 157: return (EAFNOSUPPORT); ! 158: if (sns->sns_port==0 || ns_nullhost(sns->sns_addr)) ! 159: return (EADDRNOTAVAIL); ! 160: /* ! 161: * If we haven't bound which network number to use as ours, ! 162: * we will use the number of the outgoing interface. ! 163: * This depends on having done a routing lookup, which ! 164: * we will probably have to do anyway, so we might ! 165: * as well do it now. On the other hand if we are ! 166: * sending to multiple destinations we may have already ! 167: * done the lookup, so see if we can use the route ! 168: * from before. In any case, we only ! 169: * chose a port number once, even if sending to multiple ! 170: * destinations. ! 171: */ ! 172: ro = &nsp->nsp_route; ! 173: dst = &satons_addr(ro->ro_dst); ! 174: if (nsp->nsp_socket->so_options & SO_DONTROUTE) ! 175: goto flush; ! 176: if (!ns_neteq(nsp->nsp_lastdst, sns->sns_addr)) ! 177: goto flush; ! 178: if (!ns_hosteq(nsp->nsp_lastdst, sns->sns_addr)) { ! 179: if (ro->ro_rt && ! (ro->ro_rt->rt_flags & RTF_HOST)) { ! 180: /* can patch route to avoid rtalloc */ ! 181: *dst = sns->sns_addr; ! 182: } else { ! 183: flush: ! 184: if (ro->ro_rt) ! 185: RTFREE(ro->ro_rt); ! 186: ro->ro_rt = (struct rtentry *)0; ! 187: nsp->nsp_laddr.x_net = ns_zeronet; ! 188: } ! 189: }/* else cached route is ok; do nothing */ ! 190: nsp->nsp_lastdst = sns->sns_addr; ! 191: if ((nsp->nsp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ ! 192: (ro->ro_rt == (struct rtentry *)0 || ! 193: ro->ro_rt->rt_ifp == (struct ifnet *)0)) { ! 194: /* No route yet, so try to acquire one */ ! 195: ro->ro_dst.sa_family = AF_NS; ! 196: ro->ro_dst.sa_len = sizeof(ro->ro_dst); ! 197: *dst = sns->sns_addr; ! 198: dst->x_port = 0; ! 199: rtalloc(ro); ! 200: } ! 201: if (ns_neteqnn(nsp->nsp_laddr.x_net, ns_zeronet)) { ! 202: /* ! 203: * If route is known or can be allocated now, ! 204: * our src addr is taken from the i/f, else punt. ! 205: */ ! 206: ! 207: ia = (struct ns_ifaddr *)0; ! 208: /* ! 209: * If we found a route, use the address ! 210: * corresponding to the outgoing interface ! 211: */ ! 212: if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp)) ! 213: for (ia = ns_ifaddr; ia; ia = ia->ia_next) ! 214: if (ia->ia_ifp == ifp) ! 215: break; ! 216: if (ia == 0) { ! 217: u_short fport = sns->sns_addr.x_port; ! 218: sns->sns_addr.x_port = 0; ! 219: ia = (struct ns_ifaddr *) ! 220: ifa_ifwithdstaddr((struct sockaddr *)sns); ! 221: sns->sns_addr.x_port = fport; ! 222: if (ia == 0) ! 223: ia = ns_iaonnetof(&sns->sns_addr); ! 224: if (ia == 0) ! 225: ia = ns_ifaddr; ! 226: if (ia == 0) ! 227: return (EADDRNOTAVAIL); ! 228: } ! 229: nsp->nsp_laddr.x_net = satons_addr(ia->ia_addr).x_net; ! 230: } ! 231: if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0)) ! 232: return (EADDRINUSE); ! 233: if (ns_nullhost(nsp->nsp_laddr)) { ! 234: if (nsp->nsp_lport == 0) ! 235: (void) ns_pcbbind(nsp, (struct mbuf *)0); ! 236: nsp->nsp_laddr.x_host = ns_thishost; ! 237: } ! 238: nsp->nsp_faddr = sns->sns_addr; ! 239: /* Includes nsp->nsp_fport = sns->sns_port; */ ! 240: return (0); ! 241: } ! 242: ! 243: ns_pcbdisconnect(nsp) ! 244: struct nspcb *nsp; ! 245: { ! 246: ! 247: nsp->nsp_faddr = zerons_addr; ! 248: if (nsp->nsp_socket->so_state & SS_NOFDREF) ! 249: ns_pcbdetach(nsp); ! 250: } ! 251: ! 252: ns_pcbdetach(nsp) ! 253: struct nspcb *nsp; ! 254: { ! 255: struct socket *so = nsp->nsp_socket; ! 256: ! 257: so->so_pcb = 0; ! 258: sofree(so); ! 259: if (nsp->nsp_route.ro_rt) ! 260: rtfree(nsp->nsp_route.ro_rt); ! 261: remque(nsp); ! 262: (void) m_free(dtom(nsp)); ! 263: } ! 264: ! 265: ns_setsockaddr(nsp, nam) ! 266: register struct nspcb *nsp; ! 267: struct mbuf *nam; ! 268: { ! 269: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); ! 270: ! 271: nam->m_len = sizeof (*sns); ! 272: sns = mtod(nam, struct sockaddr_ns *); ! 273: bzero((caddr_t)sns, sizeof (*sns)); ! 274: sns->sns_len = sizeof(*sns); ! 275: sns->sns_family = AF_NS; ! 276: sns->sns_addr = nsp->nsp_laddr; ! 277: } ! 278: ! 279: ns_setpeeraddr(nsp, nam) ! 280: register struct nspcb *nsp; ! 281: struct mbuf *nam; ! 282: { ! 283: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); ! 284: ! 285: nam->m_len = sizeof (*sns); ! 286: sns = mtod(nam, struct sockaddr_ns *); ! 287: bzero((caddr_t)sns, sizeof (*sns)); ! 288: sns->sns_len = sizeof(*sns); ! 289: sns->sns_family = AF_NS; ! 290: sns->sns_addr = nsp->nsp_faddr; ! 291: } ! 292: ! 293: /* ! 294: * Pass some notification to all connections of a protocol ! 295: * associated with address dst. Call the ! 296: * protocol specific routine to handle each connection. ! 297: * Also pass an extra paramter via the nspcb. (which may in fact ! 298: * be a parameter list!) ! 299: */ ! 300: ns_pcbnotify(dst, errno, notify, param) ! 301: register struct ns_addr *dst; ! 302: long param; ! 303: int errno, (*notify)(); ! 304: { ! 305: register struct nspcb *nsp, *oinp; ! 306: int s = splimp(); ! 307: ! 308: for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) { ! 309: if (!ns_hosteq(*dst,nsp->nsp_faddr)) { ! 310: next: ! 311: nsp = nsp->nsp_next; ! 312: continue; ! 313: } ! 314: if (nsp->nsp_socket == 0) ! 315: goto next; ! 316: if (errno) ! 317: nsp->nsp_socket->so_error = errno; ! 318: oinp = nsp; ! 319: nsp = nsp->nsp_next; ! 320: oinp->nsp_notify_param = param; ! 321: (*notify)(oinp); ! 322: } ! 323: splx(s); ! 324: } ! 325: ! 326: #ifdef notdef ! 327: /* ! 328: * After a routing change, flush old routing ! 329: * and allocate a (hopefully) better one. ! 330: */ ! 331: ns_rtchange(nsp) ! 332: struct nspcb *nsp; ! 333: { ! 334: if (nsp->nsp_route.ro_rt) { ! 335: rtfree(nsp->nsp_route.ro_rt); ! 336: nsp->nsp_route.ro_rt = 0; ! 337: /* ! 338: * A new route can be allocated the next time ! 339: * output is attempted. ! 340: */ ! 341: } ! 342: /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ ! 343: } ! 344: #endif ! 345: ! 346: struct nspcb * ! 347: ns_pcblookup(faddr, lport, wildp) ! 348: struct ns_addr *faddr; ! 349: u_short lport; ! 350: { ! 351: register struct nspcb *nsp, *match = 0; ! 352: int matchwild = 3, wildcard; ! 353: u_short fport; ! 354: ! 355: fport = faddr->x_port; ! 356: for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) { ! 357: if (nsp->nsp_lport != lport) ! 358: continue; ! 359: wildcard = 0; ! 360: if (ns_nullhost(nsp->nsp_faddr)) { ! 361: if (!ns_nullhost(*faddr)) ! 362: wildcard++; ! 363: } else { ! 364: if (ns_nullhost(*faddr)) ! 365: wildcard++; ! 366: else { ! 367: if (!ns_hosteq(nsp->nsp_faddr, *faddr)) ! 368: continue; ! 369: if (nsp->nsp_fport != fport) { ! 370: if (nsp->nsp_fport != 0) ! 371: continue; ! 372: else ! 373: wildcard++; ! 374: } ! 375: } ! 376: } ! 377: if (wildcard && wildp==0) ! 378: continue; ! 379: if (wildcard < matchwild) { ! 380: match = nsp; ! 381: matchwild = wildcard; ! 382: if (wildcard == 0) ! 383: break; ! 384: } ! 385: } ! 386: return (match); ! 387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.