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

Defined functions

ns_pcballoc defined in line 32; never used
ns_pcbbind defined in line 49; used 1 times
ns_pcbconnect defined in line 98; never used
ns_pcbdetach defined in line 188; used 1 times
ns_pcbdisconnect defined in line 179; never used
ns_pcblookup defined in line 280; used 3 times
ns_pcbnotify defined in line 234; never used
ns_rtchange defined in line 265; never used
ns_setpeeraddr defined in line 214; never used
ns_setsockaddr defined in line 201; never used

Defined variables

zerons_addr defined in line 30; used 3 times
Last modified: 1988-04-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3978
Valid CSS Valid XHTML 1.0 Strict