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