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