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