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

Defined functions

ns_pcbbind defined in line 43; used 5 times
ns_pcbdetach defined in line 194; used 4 times
ns_pcbdisconnect defined in line 185; used 4 times
ns_rtchange defined in line 271; never used

Defined variables

zerons_addr defined in line 24; used 3 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1337
Valid CSS Valid XHTML 1.0 Strict