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