/* * Berkely Socket interface for UTAH-C on TOPS-20 * Philip L. Budne @ BU/DSG */ # include "mon_files.h" # include "mon_networks.h" # include "stdio.h" # include # include "tops20.h" # include "socket.h" # include "in.h" # include "dn.h" extern errno; int socket(af, type, protocol) int af, type, protocol; { int s; register _SOCKSTR *sp; if( protocol != PF_UNSPEC ) { return( -1 ); } /* protocol set!? */ switch( af ) { case AF_INET: s = inet_socket(af, type, protocol); break; case AF_DECnet: s = dnet_socket(af, type, protocol); break; default: return( -1 ); } /* switch on af */ if( s == -1 ) return( -1 ); /* pass error */ sp = _fotab[s]._sock; /* get sockstr */ sp->_af = af; /* save address family */ sp->_type = type; /* save socket type */ sp->_proto = protocol; /* save protocol? */ return( s ); /* return socket */ } /* socket */ static int nuljfn(dev) unsigned int dev; { int jfn; register _SOCKSTR *s; jfn = _gtjfn("NUL:", Value(GJ_sht) ); /* get dummy JFN now */ if( jfn < 0 ) return( -1 ); s = (_SOCKSTR *) malloc( sizeof( _SOCKSTR ) ); if( s == NULL ) { _rljfn( jfn ); return( -1 ); } _fotab[jfn]._flg |= _FOSOCKET; /* mark as socket */ _fotab[jfn]._sock = s; /* give pointer to sockstr */ s->_dev = dev; /* set device type */ s->_backlog = -1; /* set bogus backlog */ return( jfn ); } /* nuljfn */ static int inet_socket(af, type, protocol) /* create socket for AF_INET */ int af, type, protocol; { switch( type ) { case SOCK_STREAM: return( nuljfn( D_TCP ) ); case SOCK_DGRAM: return( nuljfn( D_UDP ) ); default: return( -1 ); } /* not stream */ } /* inet_socket */ static int dnet_socket(af, type, protocol) /* create socket for AF_DNET */ int af, type, protocol; { switch( af ) { case SOCK_STREAM: return( nuljfn( D_DCN ) ); default: return( -1 ); } /* not stream */ } /* dnet_socket */ static int checksock(s) int s; { if( s < 0 || s >= NJFN ) { return( -1 ); } /* bad file number */ if( ! ISSOCK( s ) ) { return( -1 ); } /* not a socket */ return( 0 ); } /* checksock */ int bind(s, name, namelen) /* passive naming bind */ int s; struct sockaddr *name; int namelen; { int status; register _SOCKSTR *sp; if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); switch( _fotab[s]._sock->_dev ) { case D_UDP: status = bind_UDP(s, name, namelen); break; } /* device switch */ if( status == -1 ) return( -1 ); sp = _fotab[s]._sock; sp->_name = *name; sp->_namel = namelen; return( status ); } /* bind */ static int Zbind(s, name, namelen) /* passive naming bind */ int s; struct sockaddr *name; int namelen; { int status; if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); switch( _fotab[s]._sock->_dev ) { case D_TCP: status = bind_TCP(s, name, namelen); break; case D_DCN: status = bind_DCN(s, name, namelen); break; } /* device switch */ return( status ); } /* Zbind */ static int bind_TCP(s, name, namelen) /* TCP passive naming bind */ int s; struct sockaddr_in *name; int namelen; { char string[100]; int gjblk[012]; /* GTJFN block */ int acs[5]; /* accumulator block */ if( name->sin_addr.S_un.S_addr != 0L ) { sprintf(string, "TCP:%ld-%d\026#.;CONNECT:PASSIVE", name->sin_addr.S_un.S_addr, name->sin_port ); } else sprintf(string, "TCP:%d\026#.;CONNECT:PASSIVE", name->sin_port ); _rljfn(s); /* release NUL: jfn */ bzero(gjblk, sizeof( gjblk )); gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ ac1 = (int) gjblk; ac2 = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr ) { _seterr(); return( -1 ); } /* gtjfn failed */ _fotab[s]._flg |= _FOBOUND; /* Mark as bound */ return( 0 ); } /* bind_TCP */ static int bind_UDP(s, name, namelen) /* UDP passive naming bind */ int s; struct sockaddr_in *name; int namelen; { char string[100]; int gjblk[012]; int acs[5]; sprintf(string, "UDP:%ld-%d.", name->sin_addr.S_un.S_addr, name->sin_port ); _rljfn(s); /* release NUL: jfn */ gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ acs[1] = (int) gjblk; acs[2] = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr) { _seterr(); return( -1 ); } /* gtjfn failed */ /* open now, since listen and accept are illegal */ acs[1] = s; /* jfn */ acs[2] = makefield(OF_bsz,8) + Value(OF_rd) + Value(OF_wr); if( JSYS(JSopenf, acs) == JSerr ) { _seterr(); return( -1 ); } /* openf failed */ _fotab[s]._flg |= _FOBOUND; /* Mark as bound */ return( 0 ); } /* bind_UDP */ static int bind_DCN(s, name, namelen) /* DECnet passive naming bind */ int s; struct sockaddr_dn *name; int namelen; { char string[100]; int gjblk[012]; int acs[5]; if( name->sdn_objnum == 0 ) /* task? */ sprintf(string, "SRV:.%s", name->sdn_objname ); else /* no, numeric object */ sprintf(string, "SRV:%d.", name->sdn_objnum ); _rljfn(s); /* release NUL: jfn */ gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ acs[1] = (int) gjblk; acs[2] = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr ) { _seterr(); return( -1 ); } /* gtjfn failed */ _fotab[s]._flg |= _FOBOUND; /* Mark as bound */ return( 0 ); } /* bind_DCN */ int listen(s, backlog) int s, backlog; { if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); switch( _fotab[s]._sock->_dev ) { case D_TCP: return( list_TCP(s, backlog) ); case D_UDP: return( -1 ); case D_DCN: return( list_DCN(s, backlog) ); } /* device switch */ } /* listen */ static int list_TCP(s, backlog) int s, backlog; { _fotab[s]._sock->_backlog = backlog; return( s ); } /* list_TCP */ static int list_DCN(s, backlog) int s, backlog; { _fotab[s]._sock->_backlog = backlog; return( s ); } /* list_DCN */ int accept(s, addr, addrlen) int s; struct sockaddr *addr; int *addrlen; { if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); if( ! (_fotab[s]._flg & _FOBOUND ) ) { return( -1 ); } /* socket was never bound */ switch( _fotab[s]._sock->_dev ) { case D_TCP: return( acep_TCP(s, addr, addrlen) ); case D_UDP: return( -1 ); case D_DCN: return( acep_DCN(s, addr, addrlen) ); } /* device switch */ } /* accept */ static acep_TCP(s, addr, addrlen) int s; struct sockaddr_in *addr; int *addrlen; { register _SOCKSTR *sp; int ns; sp = _fotab[s]._sock; /* get old sockstr */ ns = socket( sp->_af, sp->_type, sp->_proto); /* create new socket */ if( ns == -1 ) return( -1 ); /* quit now if we can't */ if( Zbind( ns, &(sp->_name), sp->_namel ) == -1 ) { /* close( ns ); */ return( -1 ); } /* bind failed */ /* DO LISTEN? */ acs[1] = ns; /* jfn */ acs[2] = makefield(OF_bsz,8) + Value(OF_rd) + Value(OF_wr) + makefield(OF_mod, TCmwi); if( JSYS(JSopenf, acs) == JSerr ) { _seterr(); /* close( ns ); */ return( -1 ); } /* openf failed */ if( JSYS(JSgdsts, acs) == JSerr ) { _seterr(); /* close( ns ); */ return( -1 ); } /* gdsts failed */ addr->sin_family = AF_INET; addr->sin_port = acs[4]; /* foreign port */ addr->sin_addr.S_un.S_addr = acs[3]; /* foreign addr */ *addrlen = sizeof( struct sockaddr_in ); return( ns ); } /* acep_TCP */ static acep_DCN(s, addr, addrlen) int s; struct sockaddr_dn *addr; int *addrlen; { fprintf( stderr, "No accept code for DECnet (yet!)\n" ); return( -1 ); } /* acep_DCN */ int connect(s, name, namelen) /* create active socket */ int s; struct sockaddr *name; int namelen; { if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); _fotab[s]._flg |= _FOBOUND; /* mark as bound (use another flag?) */ switch( _fotab[s]._sock->_dev ) { case D_TCP: return( conn_TCP(s, name, namelen) ); case D_UDP: return( conn_UDP(s, name, namelen) ); case D_DCN: return( conn_DCN(s, name, namelen) ); } /* device switch */ } /* connect */ static int conn_TCP(s, name, namelen) /* Connect TCP active task */ int s; struct sockaddr_in *name; int namelen; { char string[100]; int gjblk[012], acs[5], local; _rljfn(s); /* release NUL: jfn */ /* if( _fotab[s]._flg & _FORESVD ) /* want reserved port? */ /* local = IPPORT_RESERVED - 1; /* yes, start search */ /* else /* local = -1; */ if( _fotab[s]._flg & _FOBOUND ) { /* bound first? */ register struct sockaddr_in *sp; sp = (struct sockaddr_in *) &(_fotab[s]._sock->_name); local = sp->sin_port; } else local = -1; /* no, create local */ /* do { */ if( local < 0 ) { sprintf(string, "TCP:.%lo-%d;CONNECT:ACTIVE", name->sin_addr.S_un.S_addr, name->sin_port ); } /* no local port specified */ else { sprintf(string, "TCP:%d\026#.%lo-%d;CONNECT:ACTIVE", local, name->sin_addr.S_un.S_addr, name->sin_port ); } /* specifiy local port */ printf("connect: %s\n", string); gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ acs[1] = (int) gjblk; acs[2] = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr ) { _seterr(); if( errno != TCPx31 ) /* expected error? */ return( -1 ); /* no! fail now */ } /* gtjfn failed */ /* else break; */ /* if( --local == 0 ) /* return( -1 ); /* search ran out */ /* } while( local > 0 ); */ acs[1] = s; /* jfn */ acs[2] = makefield(OF_bsz,8) + Value(OF_rd) + Value(OF_wr) + makefield(OF_mod, TCmwi); if( JSYS(JSopenf, acs) == JSerr ) { _seterr(); return( -1 ); } /* openf failed */ return( 0 ); } /* conn_TCP */ static int conn_UDP(s, name, namelen) /* connect UDP active task */ int s; struct sockaddr_in *name; int namelen; { char string[100]; int gjblk[012]; int acs[5]; sprintf(string, "UDP:.%ld-%d", name->sin_addr.S_un.S_addr, name->sin_port ); _rljfn(s); /* release NUL: jfn */ gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ acs[1] = (int) gjblk; acs[2] = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr ) { _seterr(); return( -1 ); } /* gtjfn failed */ acs[1] = s; /* jfn */ acs[2] = makefield(OF_bsz,8) + Value(OF_rd) + Value(OF_wr); if( JSYS(JSopenf, acs) == JSerr ) { _seterr(); return( -1 ); } /* openf failed */ return( 0 ); } /* conn_UDP */ static int conn_DCN(s, name, namelen) /* Connect DECnet active task */ int s; struct sockaddr_dn *name; int namelen; { char string[100]; int gjblk[012], acs[5], timeout; if( name->sdn_objnum == 0 ) /* task? */ sprintf(string, "DCN:%s-TASK-%s", name->sdn_nodename, name->sdn_objname ); else /* no, numeric object */ sprintf(string, "DCN:%s-%d.", name->sdn_nodename, name->sdn_objnum ); _rljfn(s); /* release NUL: jfn */ gjblk[GJgen] = makefield(GJ_jfn, GJerr); /* use supplied jfn number */ gjblk[GJsrc] = makeword( NUlio, NUlio ); gjblk[GJjfn] = s; /* here it is! */ acs[1] = (int) gjblk; acs[2] = POINT(string); if( JSYS(JSgtjfn, acs) == JSerr ) { _seterr(); return( -1 ); } /* gtjfn failed */ acs[1] = s; /* jfn */ acs[2] = makefield(OF_bsz,8) + Value(OF_rd) + Value(OF_wr); if( JSYS(JSopenf, acs) == JSerr ) { _seterr(); return( -1 ); } /* openf failed */ JSYS(JStime, acs); /* get uptime */ timeout = acs[1] + 60 * acs[2]; /* plus 60 seconds */ for( ; ; ) { register unsigned state; acs[1] = s; /* socket */ acs[2] = MOrls; /* read link state */ if( JSYS(JSmtopr, acs) == JSerr ) { _seterr(); return( -1 ); } /* mtopr failed */ state = acs[3]; /* get state bits */ if( state & Value(MO_con) ) /* connected? */ return( 0 ); /* YES!! */ if( state & (Value(MO_abt) | Value(MO_syn)) ) { return( -1 ); /* abort or sync disconnect */ } /* rejected */ JSYS(JStime, acs); /* get uptime */ if( acs[1] > timeout ) { return( -1 ); } /* timed out */ acs[1] = 500; /* half a sec */ JSYS(JSdisms, acs); } /* forever */ } /* conn_DCN */ /* * recv(2) call */ # ifdef NOTDEF int recv(s, msg, len, flgs) int s; char *msg; int len, flgs; { if( checksock(s) == -1 ) return( -1 ); s = jfnof(s); switch( _fotab[s]._sock->_dev ) { case D_TCP: return( recv_TCP(s, msg, len, flgs) ); case D_UDP: return( recv_UDP(s, msg, len, flgs) ); case D_DCN: return( recv_DCN(s, msg, len, flgs) ); } /* device switch */ } /* recv */ /* recv_TCP recv_UDP recv_DCN recvfrom */ # endif /* * select(2) */ int select(nfds, readfds, wrtfds, exceptfds, timeout) int nfds, *readfds, *wrtfds, *exceptfds; { register int i; int count, ready; int acs[5]; if( exceptfds != NULL ) /* **** NO SUPPORT YET **** */ *exceptfds = 0; count = 0; for( i = 0; i < nfds; i++ ) { ready = 0; /* not ready */ if( readfds != NULL && ((*readfds) & (1< 0 ) ready = 1; else *readfds &= ~(1<