int ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr) { struct sonode *so; int rval; /* All Solaris components should pass a cred for this operation. */ ASSERT(cr != NULL); if (!KSOCKET_VALID(ks)) return (ENOTSOCK); so = KSTOSO(ks); switch (cmd) { default: /* STREAM iotcls are not supported */ if ((cmd & 0xffffff00U) == STR) { rval = EOPNOTSUPP; } else { rval = socket_ioctl(so, cmd, arg, KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp); } break; case FIOASYNC: case SIOCSPGRP: case FIOSETOWN: case SIOCGPGRP: case FIOGETOWN: rval = EOPNOTSUPP; break; } return (rval); }
/* * OSI function to control blocking/non-blocking I/O */ static int setNonBlock(SOCKET fd, int nonBlockFlag) { #if defined(vxWorks) int flags; flags = nonBlockFlag; if (ioctl(fd, FIONBIO, (int)&flags) < 0) return -1; #elif defined(_WIN32) unsigned long int flags; flags = nonBlockFlag; if (socket_ioctl(fd, FIONBIO, &flags) < 0) return -1; #else int flags; if ((flags = fcntl(fd, F_GETFL, 0)) < 0) return -1; if (nonBlockFlag) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) return -1; #endif return 0; }
/*ARGSUSED4*/ static int socket_vop_ioctl(struct vnode *vp, int cmd, intptr_t arg, int mode, struct cred *cr, int32_t *rvalp, caller_context_t *ct) { struct sonode *so = VTOSO(vp); ASSERT(vp->v_type == VSOCK); return (socket_ioctl(so, cmd, arg, mode, cr, rvalp)); }
SOCKET shCreateSocket(int domain, int type, int protocol) { SOCKET sd = epicsSocketCreate(domain, type, protocol); int ret; osiSockIoctl_t flag; if(sd==INVALID_SOCKET) return sd; /* set non-blocking IO */ flag = 1; ret = socket_ioctl(sd, FIONBIO, &flag); if(ret) { epicsSocketDestroy(sd); sd = INVALID_SOCKET; } return sd; }
/* ARGSUSED */ static int socket_vop_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr, caller_context_t *ct) { struct sonode *so = VTOSO(vp); int error = 0; ASSERT(vp->v_type == VSOCK); mutex_enter(&so->so_lock); if (nflags & FNDELAY) so->so_state |= SS_NDELAY; else so->so_state &= ~SS_NDELAY; if (nflags & FNONBLOCK) so->so_state |= SS_NONBLOCK; else so->so_state &= ~SS_NONBLOCK; mutex_exit(&so->so_lock); if (so->so_state & SS_ASYNC) oflags |= FASYNC; /* * Sets/clears the SS_ASYNC flag based on the presence/absence * of the FASYNC flag passed to fcntl(F_SETFL). * This exists solely for BSD fcntl() FASYNC compatibility. */ if ((oflags ^ nflags) & FASYNC && so->so_version != SOV_STREAM) { int async = nflags & FASYNC; int32_t rv; /* * For non-TPI sockets all we have to do is set/remove the * SS_ASYNC bit, but for TPI it is more involved. For that * reason we delegate the job to the protocol's ioctl handler. */ error = socket_ioctl(so, FIOASYNC, (intptr_t)&async, FKIOCTL, cr, &rv); } return (error); }
/* * * main() * */ int main(void) { struct sockaddr_in serverAddr; /* server's address */ struct timeval timeout; int status; struct ioc_log_server *pserver; osiSockIoctl_t optval; status = getConfig(); if (status<0) { fprintf(stderr, "iocLogServer: EPICS environment underspecified\n"); fprintf(stderr, "iocLogServer: failed to initialize\n"); return IOCLS_ERROR; } pserver = (struct ioc_log_server *) calloc(1, sizeof *pserver); if (!pserver) { fprintf(stderr, "iocLogServer: %s\n", strerror(errno)); return IOCLS_ERROR; } pserver->pfdctx = (void *) fdmgr_init(); if (!pserver->pfdctx) { fprintf(stderr, "iocLogServer: %s\n", strerror(errno)); return IOCLS_ERROR; } /* * Open the socket. Use ARPA Internet address format and stream * sockets. Format described in <sys/socket.h>. */ pserver->sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0); if (pserver->sock == INVALID_SOCKET) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf(stderr, "iocLogServer: sock create err: %s\n", sockErrBuf); free(pserver); return IOCLS_ERROR; } epicsSocketEnableAddressReuseDuringTimeWaitState ( pserver->sock ); /* Zero the sock_addr structure */ memset((void *)&serverAddr, 0, sizeof serverAddr); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(ioc_log_port); /* get server's Internet address */ status = bind ( pserver->sock, (struct sockaddr *)&serverAddr, sizeof (serverAddr) ); if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf(stderr, "iocLogServer: bind err: %s\n", sockErrBuf ); fprintf (stderr, "iocLogServer: a server is already installed on port %u?\n", (unsigned)ioc_log_port); return IOCLS_ERROR; } /* listen and accept new connections */ status = listen(pserver->sock, 10); if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf(stderr, "iocLogServer: listen err %s\n", sockErrBuf); return IOCLS_ERROR; } /* * Set non blocking IO * to prevent dead locks */ optval = TRUE; status = socket_ioctl( pserver->sock, FIONBIO, &optval); if (status < 0){ char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf(stderr, "iocLogServer: ioctl FIONBIO err %s\n", sockErrBuf); return IOCLS_ERROR; } # ifdef UNIX status = setupSIGHUP(pserver); if (status < 0) { return IOCLS_ERROR; } # endif status = openLogFile(pserver); if (status < 0) { fprintf(stderr, "File access problems to `%s' because `%s'\n", ioc_log_file_name, strerror(errno)); return IOCLS_ERROR; } status = fdmgr_add_callback( pserver->pfdctx, pserver->sock, fdi_read, acceptNewClient, pserver); if (status < 0) { fprintf(stderr, "iocLogServer: failed to add read callback\n"); return IOCLS_ERROR; } while (TRUE) { timeout.tv_sec = 60; /* 1 min */ timeout.tv_usec = 0; fdmgr_pend_event(pserver->pfdctx, &timeout); fflush(pserver->poutfile); } }
/* * acceptNewClient() * */ static void acceptNewClient ( void *pParam ) { struct ioc_log_server *pserver = (struct ioc_log_server *) pParam; struct iocLogClient *pclient; osiSocklen_t addrSize; struct sockaddr_in addr; int status; osiSockIoctl_t optval; pclient = ( struct iocLogClient * ) malloc ( sizeof ( *pclient ) ); if ( ! pclient ) { return; } addrSize = sizeof ( addr ); pclient->insock = epicsSocketAccept ( pserver->sock, (struct sockaddr *)&addr, &addrSize ); if ( pclient->insock==INVALID_SOCKET || addrSize < sizeof (addr) ) { static unsigned acceptErrCount; static int lastErrno; int thisErrno; free ( pclient ); if ( SOCKERRNO == SOCK_EWOULDBLOCK || SOCKERRNO == SOCK_EINTR ) { return; } thisErrno = SOCKERRNO; if ( acceptErrCount % 1000 || lastErrno != thisErrno ) { fprintf ( stderr, "Accept Error %d\n", SOCKERRNO ); } acceptErrCount++; lastErrno = thisErrno; return; } /* * Set non blocking IO * to prevent dead locks */ optval = TRUE; status = socket_ioctl( pclient->insock, FIONBIO, &optval); if(status<0){ char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf(stderr, "%s:%d ioctl FBIO client er %s\n", __FILE__, __LINE__, sockErrBuf); epicsSocketDestroy ( pclient->insock ); free(pclient); return; } pclient->pserver = pserver; pclient->nChar = 0u; ipAddrToA (&addr, pclient->name, sizeof(pclient->name)); logTime(pclient); #if 0 status = fprintf( pclient->pserver->poutfile, "%s %s ----- Client Connect -----\n", pclient->name, pclient->ascii_time); if(status<0){ handleLogFileError(); } #endif /* * turn on KEEPALIVE so if the client crashes * this task will find out and exit */ { long true = 1; status = setsockopt( pclient->insock, SOL_SOCKET, SO_KEEPALIVE, (char *)&true, sizeof(true) ); if(status<0){ fprintf(stderr, "Keepalive option set failed\n"); } } status = shutdown(pclient->insock, SHUT_WR); if(status<0){ char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); fprintf (stderr, "%s:%d shutdown err %s\n", __FILE__, __LINE__, sockErrBuf); epicsSocketDestroy ( pclient->insock ); free(pclient); return; } status = fdmgr_add_callback( pserver->pfdctx, pclient->insock, fdi_read, readFromClient, pclient); if (status<0) { epicsSocketDestroy ( pclient->insock ); free(pclient); fprintf(stderr, "%s:%d client fdmgr_add_callback() failed\n", __FILE__, __LINE__); return; } }
/* * CAST_SERVER * * service UDP messages * */ void cast_server(void *pParm) { struct sockaddr_in sin; int status; int count=0; struct sockaddr_in new_recv_addr; osiSocklen_t recv_addr_size; unsigned short port; osiSockIoctl_t nchars; if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } recv_addr_size = sizeof(new_recv_addr); if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) { epicsSocketDestroy ( IOC_cast_sock ); } /* * Open the socket. * Use ARPA Internet address format and datagram socket. */ if ( ( IOC_cast_sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0) ) == INVALID_SOCKET ) { epicsPrintf ("CAS: cast socket creation error\n"); epicsThreadSuspendSelf (); } /* * some concern that vxWorks will run out of mBuf's * if this change is made * * joh 11-10-98 */ #if 0 { /* * * this allows for faster connects by queuing * additional incomming UDP search frames * * this allocates a 32k buffer * (uses a power of two) */ int size = 1u<<15u; status = setsockopt (IOC_cast_sock, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)); if (status<0) { epicsPrintf ("CAS: unable to set cast socket size\n"); } } #endif epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock ); /* Zero the sock_addr structure */ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(port); /* get server's Internet address */ if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){ char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsPrintf ("CAS: UDP server port bind error was \"%s\"\n", sockErrBuf ); epicsSocketDestroy ( IOC_cast_sock ); epicsThreadSuspendSelf (); } /* * setup new client structure but reuse old structure if * possible * */ while ( TRUE ) { prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP ); if ( prsrv_cast_client ) { break; } epicsThreadSleep(300.0); } casAttachThreadToClient ( prsrv_cast_client ); /* * add placeholder for the first version message should it be needed */ rsrv_version_reply ( prsrv_cast_client ); epicsEventSignal(casudp_startStopEvent); while (TRUE) { status = recvfrom ( IOC_cast_sock, prsrv_cast_client->recv.buf, prsrv_cast_client->recv.maxstk, 0, (struct sockaddr *)&new_recv_addr, &recv_addr_size); if (status < 0) { if (SOCKERRNO != SOCK_EINTR) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsPrintf ("CAS: UDP recv error (errno=%s)\n", sockErrBuf); epicsThreadSleep(1.0); } } else if (casudp_ctl == ctlRun) { prsrv_cast_client->recv.cnt = (unsigned) status; prsrv_cast_client->recv.stk = 0ul; epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv); prsrv_cast_client->minor_version_number = 0; prsrv_cast_client->seqNoOfReq = 0; /* * If we are talking to a new client flush to the old one * in case we are holding UDP messages waiting to * see if the next message is for this same client. */ if (prsrv_cast_client->send.stk>sizeof(caHdr)) { status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size); if(status){ /* * if the address is different */ cas_send_dg_msg(prsrv_cast_client); prsrv_cast_client->addr = new_recv_addr; } } else { prsrv_cast_client->addr = new_recv_addr; } if (CASDEBUG>1) { char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); errlogPrintf ("CAS: cast server msg of %d bytes from addr %s\n", prsrv_cast_client->recv.cnt, buf); } if (CASDEBUG>2) count = ellCount (&prsrv_cast_client->chanList); status = camessage ( prsrv_cast_client ); if(status == RSRV_OK){ if(prsrv_cast_client->recv.cnt != prsrv_cast_client->recv.stk){ char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n", prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf); } } else { char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf); } if (CASDEBUG>2) { if ( ellCount (&prsrv_cast_client->chanList) ) { errlogPrintf ("CAS: Fnd %d name matches (%d tot)\n", ellCount(&prsrv_cast_client->chanList)-count, ellCount(&prsrv_cast_client->chanList)); } } } /* * allow messages to batch up if more are comming */ nchars = 0; /* supress purify warning */ status = socket_ioctl(IOC_cast_sock, FIONREAD, &nchars); if (status<0) { errlogPrintf ("CA cast server: Unable to fetch N characters pending\n"); cas_send_dg_msg (prsrv_cast_client); clean_addrq (); } else if (nchars == 0) { cas_send_dg_msg (prsrv_cast_client); clean_addrq (); } } }
int socketpair_compat(int af, int st, int p, SOCKET sd[2]) { SOCKET listener; int ret = -1; osiSockAddr ep[2]; osiSocklen_t slen = sizeof(ep[0]); if(st!=SOCK_STREAM) { SOCKERRNOSET(SOCK_EINVAL); return -1; } listener = epicsSocketCreate(AF_INET, SOCK_STREAM, 0); sd[0] = INVALID_SOCKET; sd[1] = shCreateSocket(AF_INET, SOCK_STREAM, 0); if(listener==INVALID_SOCKET || sd[1]==INVALID_SOCKET) { SOCKERRNOSET(SOCK_EMFILE); goto fail; } memset(ep, 0, sizeof(ep)); ep[0].ia.sin_family = AF_INET; ep[0].ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if(bind(listener, &ep[0].sa, sizeof(ep[0]))) goto fail; if(getsockname(listener, &ep[0].sa, &slen)) goto fail; if(listen(listener, 2)) goto fail; /* we can't possibly succeed immediately */ if(connect(sd[1], &ep[0].sa, sizeof(ep[0]))!=-1) goto fail; if(SOCKERRNO!=SOCK_EINPROGRESS) goto fail; while(1) { int err; shSocket atemp; SOCKET temp; osiSocklen_t olen = sizeof(err); slen = sizeof(ep[1]); temp = epicsSocketAccept(listener, &ep[1].sa, &slen); if(temp==INVALID_SOCKET) { if(SOCKERRNO==SOCK_EINTR) continue; goto fail; } shSocketInit(&atemp); atemp.sd = sd[1]; if(shWaitFor(&atemp, SH_CANTX, 0)) { /* someone raced us and won... */ epicsSocketDestroy(temp); continue; } if(getsockopt(sd[1], SOL_SOCKET, SO_ERROR, (char*)&err, &olen)) goto fail; if(err) { SOCKERRNOSET(err); goto fail; } sd[0] = temp; break; } { /* restore blocking IO */ osiSockIoctl_t flag = 0; if(socket_ioctl(sd[1], FIONBIO, &flag)) goto fail; } epicsSocketDestroy(listener); return 0; fail: if(listener!=INVALID_SOCKET) epicsSocketDestroy(sd[0]); if(listener!=INVALID_SOCKET) epicsSocketDestroy(sd[0]); if(sd[1]!=INVALID_SOCKET) epicsSocketDestroy(sd[1]); return ret; }