Beispiel #1
0
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);
}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
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));
}
Beispiel #4
0
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;
}
Beispiel #5
0
/* 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);
}
Beispiel #6
0
/*
 *
 * 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);
    }
}
Beispiel #7
0
/*
 *	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;
	}
}
Beispiel #8
0
/*
 * 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 ();
        }
    }
}
Beispiel #9
0
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;
}