Beispiel #1
0
/**
 * Sockwatch Module Handler
 * If you use Sockwatch Module, this should run in the main loop
 * @ingroup sockwatch_module
 */
void sockwatch_run(void)
{
#define WCF_HANDLE(item_v, ret_v) \
do { \
	BITCLR(watch_sock[i], item_v); \
	watch_cb[i](i, item_v, ret_v); \
} while(0)

	uint8_t i;
	int32_t ret;

	S2E_Packet *value = get_S2E_Packet_pointer();
	MQTTPacket_connectData mqttConnectData = MQTTPacket_connectData_initializer;

	for(i=0; i<TOTAL_SOCK_NUM; i++) {
		if(watch_sock[i] == 0) continue;
		if(atci.mqtt_run == 1) {
			ret = MQTTYield(&mqttClient, mqttConnectData.keepAliveInterval);
#ifdef __ATC_MODE_MQTT_DEBUG__
			if(ret != SUCCESSS) {
				printf("MQTT yield error - ret : %d\r\n", ret);
			}
#endif
		}
		if(watch_sock[i] & WATCH_SOCK_RECV) {	// checked every time when 'connected' state
			getsockopt(i, SO_RECVBUF, (uint16_t*)&ret);
			if((uint16_t)ret > 0) WCF_HANDLE(WATCH_SOCK_RECV, RET_OK);
		}
		if(watch_sock[i] & WATCH_SOCK_CLS_EVT) {	// checked every time when 'connected' state
			getsockopt(i, SO_STATUS, (uint8_t*)&ret);
			switch((uint8_t)ret) {
			case SOCK_CLOSED:
				WCF_HANDLE(WATCH_SOCK_CLS_EVT, RET_OK);
				break;
			case SOCK_CLOSE_WAIT:
				disconnect(i);
				//close(i);
				break;
			default:
				break;
			}
		}
		if(watch_sock[i] & WATCH_SOCK_CONN_EVT) {	// checked every time when 'listen' state
			getsockopt(i, SO_STATUS, (uint8_t*)&ret);
			switch((uint8_t)ret) {
			case SOCK_ESTABLISHED:
				WCF_HANDLE(WATCH_SOCK_CONN_EVT, RET_OK);
				break;
			default:
				break;
			}
		}
		if((watch_sock[i] & WATCH_SOCK_MASK_LOW) == 0) continue;	// things which occurs occasionally will be checked all together
		if(watch_sock[i] & WATCH_SOCK_CLS_TRY) {
			getsockopt(i, SO_STATUS, (uint8_t*)&ret);
			switch((uint8_t)ret) {
			case SOCK_LISTEN:
				close(i);
			case SOCK_CLOSED:
				WCF_HANDLE(WATCH_SOCK_CLS_TRY, RET_OK);
				break;
			case SOCK_FIN_WAIT:
				close(i);	
				break;
			default:
				ctlsocket(i, CS_GET_INTERRUPT, (uint8_t*)&ret);
				if((uint8_t)ret & Sn_IR_TIMEOUT){
					//ctlsocket(i, CS_CLR_INTERRUPT, (uint8_t*)&ret);
					close(i);
					WCF_HANDLE(WATCH_SOCK_CLS_TRY, SOCKERR_TIMEOUT);
				}
				disconnect(i);
				//close(i);
				break;
			}
		}
		if(watch_sock[i] & WATCH_SOCK_CONN_TRY) {
			getsockopt(i, SO_STATUS, (uint8_t*)&ret);
			switch((uint8_t)ret) {
			case SOCK_ESTABLISHED:
				WCF_HANDLE(WATCH_SOCK_CONN_TRY, RET_OK);
				if(atci.mqtt_con == 1) {
					if(getSn_IR(i) & Sn_IR_CON) {
						setSn_IR(i,Sn_IR_CON);

						mqttConnectData.MQTTVersion			= 4;
						mqttConnectData.clientID.cstring 	= value->module_name;
						mqttConnectData.username.cstring 	= value->options.mqtt_user;
						mqttConnectData.password.cstring 	= value->options.mqtt_pw;
						mqttConnectData.willFlag 			= 0;
						mqttConnectData.keepAliveInterval   = 60;
						mqttConnectData.cleansession        = 1;

						ret = MQTTConnect(&mqttClient, &mqttConnectData);
#ifdef __ATC_MODE_MQTT_DEBUG__
						if(ret != SUCCESSS) {
							printf("MQTT connect error - ret : %d\r\n", ret);
						}
#endif
						atci.mqtt_con = 0;
						atci.mqtt_run = 1;
					}
				}
				break;
			default:
				ctlsocket(i, CS_GET_INTERRUPT, (uint8_t*)&ret);
				if((uint8_t)ret & Sn_IR_TIMEOUT){
					//ctlsocket(i, CS_CLR_INTERRUPT, (uint8_t*)&ret);
					close(i);
					WCF_HANDLE(WATCH_SOCK_CONN_TRY, SOCKERR_TIMEOUT);
				}
				break;
			}
		}
		if(watch_sock[i] & WATCH_SOCK_TCP_SEND) {
			// 블로킹 모드로만 동작함 그러므로 Watch할 필요가 없음
		}
		if(watch_sock[i] & WATCH_SOCK_UDP_SEND) {
			if(checkAtcUdpSendStatus < 0) {
				WCF_HANDLE(WATCH_SOCK_UDP_SEND, RET_NOK);
			}
			else {
				WCF_HANDLE(WATCH_SOCK_UDP_SEND, RET_OK);
			}
		}
	}

	// ToDo: not socket part
	
}
Beispiel #2
0
//扫描指定ip的指定port
void do_scan(struct sockaddr_in *des_add){
	int sock_fd;
	int result;
	socklen_t len;
	struct hostent *hptr;

	//printf("%s\n",inet_ntoa(des_add->sin_addr));
	if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
		perror("error: socket\n");
		return;
	}
	//设置为非阻塞模式
	int flags = fcntl(sock_fd,F_GETFL,0);
	fcntl(sock_fd,F_SETFL,flags|O_NONBLOCK);
	//建立连接
	len = sizeof(*des_add);
	result = connect(sock_fd,(struct sockaddr*)des_add,len);
	if(result && errno != EINPROGRESS){
		close(sock_fd);
		return;
	}
	if(result == 0){
		//connect连接成功,恢复套接字阻塞状态
		fcntl(sock_fd,F_SETFL,flags);
		hptr = gethostbyaddr(&(des_add->sin_addr),4,AF_INET);
		printf("ip:%s\thostname:%s\tport:%d\n",inet_ntoa(des_add->sin_addr),hptr->h_name,ntohs(des_add->sin_port));
		close(sock_fd);
		return;
	}
	//连接失败,设置等待或者超时
	fd_set rd,wd,ed;
	FD_ZERO(&rd);
	FD_SET(sock_fd,&rd);
	wd = rd;
	ed = rd;
	int maxfd = sock_fd;
	struct timeval tv = {0,3000};
	int ret = select(maxfd+1,&rd,&wd,&ed,&tv);
	int val;
	if(ret <= 0){
		close(sock_fd);
		return;
	}else{
		if(!FD_ISSET(sock_fd,&rd)&&!FD_ISSET(sock_fd,&wd)){
			close(sock_fd);
			return;
		}
		if(getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,&val,&len)<0){
			close(sock_fd);
			return;
		}
		if(val!=0){
			close(sock_fd);
			return;
		}
		//connect正确返回,恢复阻塞状态
		fcntl(sock_fd,F_SETFL,flags);
		hptr = gethostbyaddr(&(des_add->sin_addr),4,AF_INET);
		if(hptr == NULL)	printf("\t\t\t\t\tip:%s\thostname:unkown\tport:%d\n",inet_ntoa(des_add->sin_addr),ntohs(des_add->sin_port));
		else	printf("\t\t\t\t\tip:%s\thostname:%s\tport:%d\n",inet_ntoa(des_add->sin_addr),hptr->h_name,ntohs(des_add->sin_port));
		close(sock_fd);
	}
}
Beispiel #3
0
Connection* ConnectionInit(Connection* connection) {
    ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER;

#ifndef AIO4C_WIN32
    if ((connection->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        code.error = errno;
#else /* AIO4C_WIN32 */
    if ((connection->socket = socket(PF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
        code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_SOCKET_ERROR, &code);
    }

#ifndef AIO4C_WIN32
    if (fcntl(connection->socket, F_SETFL, O_NONBLOCK) == -1) {
        code.error = errno;
#else /* AIO4C_WIN32 */
    unsigned long ioctl = 1;
    if (ioctlsocket(connection->socket, FIONBIO, &ioctl) == SOCKET_ERROR) {
        code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_FCNTL_ERROR, &code);
    }

    ConnectionState(connection, AIO4C_CONNECTION_STATE_INITIALIZED);

    return connection;
}

Connection* ConnectionConnect(Connection* connection) {
    ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER;
    ConnectionState newState = AIO4C_CONNECTION_STATE_CONNECTING;

    if (connection->state != AIO4C_CONNECTION_STATE_INITIALIZED) {
        code.expected = AIO4C_CONNECTION_STATE_INITIALIZED;
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_DEBUG, AIO4C_CONNECTION_STATE_ERROR, &code);
    }

    if (connect(connection->socket, AddressGetAddr(connection->address), AddressGetAddrSize(connection->address)) == -1) {
#ifndef AIO4C_WIN32
        code.error = errno;
        if (errno == EINPROGRESS) {
#else /* AIO4C_WIN32 */
        int error = WSAGetLastError();
        code.source = AIO4C_ERRNO_SOURCE_WSA;
        if (error == WSAEINPROGRESS || error == WSAEALREADY || error == WSAEWOULDBLOCK) {
#endif /* AIO4C_WIN32 */
            newState = AIO4C_CONNECTION_STATE_CONNECTING;
        } else {
            return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_CONNECT_ERROR, &code);
        }
    } else {
        newState = AIO4C_CONNECTION_STATE_CONNECTED;
    }

    ConnectionState(connection, newState);

    return connection;
}

Connection* ConnectionFinishConnect(Connection* connection) {
    ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER;
    int soError = 0;
    socklen_t soSize = sizeof(int);

#ifdef AIO4C_HAVE_POLL
    aio4c_poll_t polls[1] = { { .fd = connection->socket, .events = POLLOUT, .revents = 0 } };

#ifndef AIO4C_WIN32
    if (poll(polls, 1, -1) == -1) {
        code.error = errno;
#else /* AIO4C_WIN32 */
    if (WSAPoll(polls, 1, -1) == SOCKET_ERROR) {
        code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_POLL_ERROR, &code);
    }

    if (polls[0].revents > 0) {
#else /* AIO4C_HAVE_POLL */
    fd_set writeSet;
    fd_set errorSet;

    FD_ZERO(&writeSet);
    FD_ZERO(&errorSet);
    FD_SET(connection->socket, &writeSet);
    FD_SET(connection->socket, &errorSet);

#ifndef AIO4C_WIN32
    if (select(connection->socket + 1, NULL, &writeSet, &errorSet, NULL) == -1) {
        code.error = errno;
#else /* AIO4C_WIN32 */
    if (select(connection->socket + 1, NULL, &writeSet, &errorSet, NULL) == SOCKET_ERROR) {
        code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_SELECT_ERROR, &code);
    }

    if (FD_ISSET(connection->socket, &writeSet) || FD_ISSET(connection->socket, &errorSet)) {
#endif /* AIO4C_HAVE_POLL */

#ifndef AIO4C_WIN32
        if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, &soError, &soSize) != 0) {
            code.error = errno;
#else /* AI4OC_WIN32 */
        if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, (char*)&soError, &soSize) == SOCKET_ERROR) {
            code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
            return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_GETSOCKOPT_ERROR, &code);
        }

        if (soError != 0) {
#ifndef AIO4C_WIN32
            code.error = soError;
#else /* AIO4C_WIN32 */
            code.source = AIO4C_ERRNO_SOURCE_SOE;
            code.soError = soError;
#endif /* AIO4C_WIN32 */
            return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_FINISH_CONNECT_ERROR, &code);
        }
    }

    return connection;
}

Connection* ConnectionRead(Connection* connection) {
    Buffer* buffer = NULL;
    ssize_t nbRead = 0;
    ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER;
    aio4c_byte_t* data = NULL;

    buffer = connection->readBuffer;

    if (!BufferHasRemaining(buffer)) {
        code.buffer = buffer;
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_BUFFER_OVERFLOW_ERROR, &code);
    }

    data = BufferGetBytes(buffer);
    if ((nbRead = recv(connection->socket, (void*)&data[BufferGetPosition(buffer)], BufferRemaining(buffer), 0)) < 0) {
#ifndef AIO4C_WIN32
        code.error = errno;
#else /* AIO4C_WIN32 */
        code.source = AIO4C_ERRNO_SOURCE_WSA;
#endif /* AIO4C_WIN32 */
        return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_READ_ERROR, &code);
    }

    ProbeSize(AIO4C_PROBE_NETWORK_READ_SIZE, nbRead);

    if (nbRead == 0) {
        if (connection->state == AIO4C_CONNECTION_STATE_PENDING_CLOSE) {
            ConnectionState(connection, AIO4C_CONNECTION_STATE_CLOSED);
            return connection;
        } else {
            return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_INFO, AIO4C_CONNECTION_DISCONNECTED, &code);
        }
    }

    if (!connection->canRead) {
        Log(AIO4C_LOG_LEVEL_WARN, "received data on connection %s when reading is not allowed", connection->string);
        BufferReset(buffer);
        return connection;
    }

    BufferPosition(buffer, BufferGetPosition(buffer) + nbRead);

    _ConnectionEventHandle(connection, AIO4C_INBOUND_DATA_EVENT);

    return connection;
}
Beispiel #4
0
static SOCKET
xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
{
#ifndef HAVE_POLL_H
    fd_set wfd;
#ifdef _WINSOCKAPI_
    fd_set xfd;
#endif
    struct timeval tv;
#else /* !HAVE_POLL_H */
    struct pollfd p;
#endif /* !HAVE_POLL_H */
    int status;

    int addrlen;

    SOCKET s;

#ifdef SUPPORT_IP6
    if (addr->sa_family == AF_INET6) {
        s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
        addrlen = sizeof(struct sockaddr_in6);
    } else
#endif
    {
        s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        addrlen = sizeof(struct sockaddr_in);
    }
    if (s == INVALID_SOCKET) {
#ifdef DEBUG_HTTP
        perror("socket");
#endif
        __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
        return INVALID_SOCKET;
    }
#ifdef _WINSOCKAPI_
    {
        u_long one = 1;

        status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
    }
#else /* _WINSOCKAPI_ */
#if defined(VMS)
    {
        int enable = 1;

        status = ioctl(s, FIONBIO, &enable);
    }
#else /* VMS */
#if defined(__BEOS__) && !defined(__HAIKU__)
    {
        bool noblock = true;

        status =
            setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock,
                       sizeof(noblock));
    }
#else /* __BEOS__ */
    if ((status = fcntl(s, F_GETFL, 0)) != -1) {
#ifdef O_NONBLOCK
        status |= O_NONBLOCK;
#else /* O_NONBLOCK */
#ifdef F_NDELAY
        status |= F_NDELAY;
#endif /* F_NDELAY */
#endif /* !O_NONBLOCK */
        status = fcntl(s, F_SETFL, status);
    }
    if (status < 0) {
#ifdef DEBUG_HTTP
        perror("nonblocking");
#endif
        __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
        closesocket(s);
        return INVALID_SOCKET;
    }
#endif /* !__BEOS__ */
#endif /* !VMS */
#endif /* !_WINSOCKAPI_ */

    if (connect(s, addr, addrlen) == -1) {
        switch (socket_errno()) {
            case EINPROGRESS:
            case EWOULDBLOCK:
                break;
            default:
                __xmlIOErr(XML_FROM_HTTP, 0,
                           "error connecting to HTTP server");
                closesocket(s);
                return INVALID_SOCKET;
        }
    }
#ifndef HAVE_POLL_H
    tv.tv_sec = timeout;
    tv.tv_usec = 0;

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4018)
#endif
#ifndef _WINSOCKAPI_
    if (s > FD_SETSIZE)
        return INVALID_SOCKET;
#endif
    FD_ZERO(&wfd);
    FD_SET(s, &wfd);

#ifdef _WINSOCKAPI_
    FD_ZERO(&xfd);
    FD_SET(s, &xfd);

    switch (select(s + 1, NULL, &wfd, &xfd, &tv))
#else
    switch (select(s + 1, NULL, &wfd, NULL, &tv))
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#else /* !HAVE_POLL_H */
    p.fd = s;
    p.events = POLLOUT;
    switch (poll(&p, 1, timeout * 1000))
#endif /* !HAVE_POLL_H */

    {
        case 0:
            /* Time out */
            __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
            closesocket(s);
            return INVALID_SOCKET;
        case -1:
            /* Ermm.. ?? */
            __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
            closesocket(s);
            return INVALID_SOCKET;
    }

#ifndef HAVE_POLL_H
    if (FD_ISSET(s, &wfd)
#ifdef _WINSOCKAPI_
        || FD_ISSET(s, &xfd)
#endif
        )
#else /* !HAVE_POLL_H */
    if (p.revents == POLLOUT)
#endif /* !HAVE_POLL_H */
    {
        XML_SOCKLEN_T len;

        len = sizeof(status);
#ifdef SO_ERROR
        if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) <
            0) {
            /* Solaris error code */
            __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
            closesocket(s);
            return INVALID_SOCKET;
        }
#endif
        if (status) {
            __xmlIOErr(XML_FROM_HTTP, 0,
                       "Error connecting to remote host");
            closesocket(s);
            errno = status;
            return INVALID_SOCKET;
        }
    } else {
        /* pbm */
        __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
        closesocket(s);
        return INVALID_SOCKET;
    }

    return (s);
}
Beispiel #5
0
 /* system calls which differ in signature across OS's in ways that C++ cannot deal with */
 extern int SOCK_getsockopt(int  s, int level, int optname, void *optval, GETSOCKOPT_LENGTH_T *optlen) {
   return getsockopt(s, level, optname, optval, (void *)optlen);
 }
Beispiel #6
0
void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {
    char tmpfile[256], *err;
    int dfd, maxtries = 5;
    int sockerr = 0;
    socklen_t errlen = sizeof(sockerr);
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(privdata);
    REDIS_NOTUSED(mask);

    /* If this event fired after the user turned the instance into a master
     * with SLAVEOF NO ONE we must just return ASAP. */
    if (server.repl_state == REDIS_REPL_NONE) {
        close(fd);
        return;
    }

    /* Check for errors in the socket. */
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1)
        sockerr = errno;
    if (sockerr) {
        aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);
        redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s",
            strerror(sockerr));
        goto error;
    }

    /* If we were connecting, it's time to send a non blocking PING, we want to
     * make sure the master is able to reply before going into the actual
     * replication process where we have long timeouts in the order of
     * seconds (in the meantime the slave would block). */
    if (server.repl_state == REDIS_REPL_CONNECTING) {
        redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event.");
        /* Delete the writable event so that the readable event remains
         * registered and we can wait for the PONG reply. */
        aeDeleteFileEvent(server.el,fd,AE_WRITABLE);
        server.repl_state = REDIS_REPL_RECEIVE_PONG;
        /* Send the PING, don't check for errors at all, we have the timeout
         * that will take care about this. */
        syncWrite(fd,"PING\r\n",6,100);
        return;
    }

    /* Receive the PONG command. */
    if (server.repl_state == REDIS_REPL_RECEIVE_PONG) {
        char buf[1024];

        /* Delete the readable event, we no longer need it now that there is
         * the PING reply to read. */
        aeDeleteFileEvent(server.el,fd,AE_READABLE);

        /* Read the reply with explicit timeout. */
        buf[0] = '\0';
        if (syncReadLine(fd,buf,sizeof(buf),
            server.repl_syncio_timeout*1000) == -1)
        {
            redisLog(REDIS_WARNING,
                "I/O error reading PING reply from master: %s",
                strerror(errno));
            goto error;
        }

        /* We don't care about the reply, it can be +PONG or an error since
         * the server requires AUTH. As long as it replies correctly, it's
         * fine from our point of view. */
        if (buf[0] != '-' && buf[0] != '+') {
            redisLog(REDIS_WARNING,"Unexpected reply to PING from master.");
            goto error;
        } else {
            redisLog(REDIS_NOTICE,
                "Master replied to PING, replication can continue...");
        }
    }

    /* AUTH with the master if required. */
    if(server.masterauth) {
        err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL);
        if (err) {
            redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err);
            sdsfree(err);
            goto error;
        }
    }

    /* Set the slave port, so that Master's INFO command can list the
     * slave listening port correctly. */
    {
        sds port = sdsfromlonglong(server.port);
        err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port,
                                         NULL);
        sdsfree(port);
        /* Ignore the error if any, not all the Redis versions support
         * REPLCONF listening-port. */
        if (err) {
            redisLog(REDIS_NOTICE,"(non critical): Master does not understand REPLCONF listening-port: %s", err);
            sdsfree(err);
        }
    }

    /* Issue the SYNC command */
    if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) {
        redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s",
            strerror(errno));
        goto error;
    }

    /* Prepare a suitable temp file for bulk transfer */
    while(maxtries--) {
        snprintf(tmpfile,256,
            "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid());
        dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);
        if (dfd != -1) break;
        sleep(1);
    }
    if (dfd == -1) {
        redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno));
        goto error;
    }

    /* Setup the non blocking download of the bulk file. */
    if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL)
            == AE_ERR)
    {
        redisLog(REDIS_WARNING,"Can't create readable event for SYNC");
        goto error;
    }

    server.repl_state = REDIS_REPL_TRANSFER;
    server.repl_transfer_size = -1;
    server.repl_transfer_read = 0;
    server.repl_transfer_last_fsync_off = 0;
    server.repl_transfer_fd = dfd;
    server.repl_transfer_lastio = server.unixtime;
    server.repl_transfer_tmpfile = zstrdup(tmpfile);
    return;

error:
    close(fd);
    server.repl_transfer_s = -1;
    server.repl_state = REDIS_REPL_CONNECT;
    return;
}
Beispiel #7
0
/*
 * Set the date in the machines controlled by timedaemons by communicating the
 * new date to the local timedaemon.  If the timedaemon is in the master state,
 * it performs the correction on all slaves.  If it is in the slave state, it
 * notifies the master that a correction is needed.
 * Returns 0 on success.  Returns > 0 on failure, setting retval to 2;
 */
int
netsettime(time_t tval)
{
	struct timeval tout;
	struct servent *sp;
	struct tsp msg;
	struct sockaddr_in lsin, dest, from;
	fd_set ready;
	long waittime;
	int s, port, timed_ack, found, lerr;
	socklen_t length;
	char hostname[MAXHOSTNAMELEN];

	if ((sp = getservbyname("timed", "udp")) == NULL) {
		warnx("timed/udp: unknown service");
		return (retval = 2);
	}

	dest.sin_port = sp->s_port;
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		if (errno != EAFNOSUPPORT)
			warn("timed");
		return (retval = 2);
	}

	memset(&lsin, 0, sizeof(lsin));
	lsin.sin_family = AF_INET;
	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
		lsin.sin_port = htons((u_short)port);
		if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0)
			break;
		if (errno == EADDRINUSE)
			continue;
		if (errno != EADDRNOTAVAIL)
			warn("bind");
		goto bad;
	}
	if (port == IPPORT_RESERVED / 2) {
		warnx("all ports in use");
		goto bad;
	}
	memset(&msg, 0, sizeof(msg));
	msg.tsp_type = TSP_SETDATE;
	msg.tsp_vers = TSPVERSION;
	if (gethostname(hostname, sizeof(hostname))) {
		warn("gethostname");
		goto bad;
	}
	(void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
	msg.tsp_seq = htons((u_short)0);
	msg.tsp_time.tv_sec = htonl((u_long)tval);
	msg.tsp_time.tv_usec = htonl((u_long)0);
	length = sizeof(struct sockaddr_in);
	if (connect(s, (struct sockaddr *)&dest, length) < 0) {
		warn("connect");
		goto bad;
	}
	if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
		if (errno != ECONNREFUSED)
			warn("send");
		goto bad;
	}

	timed_ack = -1;
	waittime = WAITACK;
loop:
	tout.tv_sec = waittime;
	tout.tv_usec = 0;

	FD_ZERO(&ready);
	FD_SET(s, &ready);
	found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);

	length = sizeof(lerr);
	if (!getsockopt(s,
	    SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) {
		if (lerr != ECONNREFUSED)
			warnc(lerr, "send (delayed error)");
		goto bad;
	}

	if (found > 0 && FD_ISSET(s, &ready)) {
		length = sizeof(struct sockaddr_in);
		if (recvfrom(s, &msg, sizeof(struct tsp), 0,
		    (struct sockaddr *)&from, &length) < 0) {
			if (errno != ECONNREFUSED)
				warn("recvfrom");
			goto bad;
		}
		msg.tsp_seq = ntohs(msg.tsp_seq);
		msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
		msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
		switch (msg.tsp_type) {
		case TSP_ACK:
			timed_ack = TSP_ACK;
			waittime = WAITDATEACK;
			goto loop;
		case TSP_DATEACK:
			(void)close(s);
			return (0);
		default:
			warnx("wrong ack received from timed: %s",
			    tsptype[msg.tsp_type]);
			timed_ack = -1;
			break;
		}
	}
	if (timed_ack == -1)
		warnx("can't reach time daemon, time set locally");

bad:
	(void)close(s);
	return (retval = 2);
}
Beispiel #8
0
static int agent_socket_get_cred(int fd, struct ucred *cred)
{
	socklen_t credlen = sizeof(struct ucred);
	return getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &credlen);
}
Beispiel #9
0
static
int connect_with_timeout(struct lttcomm_sock *sock)
{
	unsigned long timeout = lttcomm_get_network_timeout();
	int ret, flags, connect_ret;
	struct timespec orig_time, cur_time;

	ret = fcntl(sock->fd, F_GETFL, 0);
	if (ret == -1) {
		PERROR("fcntl");
		return -1;
	}
	flags = ret;

	/* Set socket to nonblock */
	ret = fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK);
	if (ret == -1) {
		PERROR("fcntl");
		return -1;
	}

	ret = clock_gettime(CLOCK_MONOTONIC, &orig_time);
	if (ret == -1) {
		PERROR("clock_gettime");
		return -1;
	}

	connect_ret = connect(sock->fd,
		(struct sockaddr *) &sock->sockaddr.addr.sin,
		sizeof(sock->sockaddr.addr.sin));
	if (connect_ret == -1 && errno != EAGAIN
			&& errno != EWOULDBLOCK
			&& errno != EINPROGRESS) {
		goto error;
	} else if (!connect_ret) {
		/* Connect succeeded */
		goto success;
	}

	/*
	 * Perform poll loop following EINPROGRESS recommendation from
	 * connect(2) man page.
	 */
	do {
		struct pollfd fds;

		fds.fd = sock->fd;
		fds.events = POLLOUT;
		fds.revents = 0;
		ret = poll(&fds, 1, RECONNECT_DELAY);
		if (ret < 0) {
			goto error;
		} else if (ret > 0) {
			int optval;
			socklen_t optval_len = sizeof(optval);

			if (!(fds.revents & POLLOUT)) {
				/* Either hup or error */
				errno = EPIPE;
				goto error;
			}
			/* got something */
			ret = getsockopt(sock->fd, SOL_SOCKET,
				SO_ERROR, &optval, &optval_len);
			if (ret) {
				goto error;
			}
			if (!optval) {
				connect_ret = 0;
				goto success;
			} else {
				goto error;
			}
		}
		/* ret == 0: timeout */
		ret = clock_gettime(CLOCK_MONOTONIC, &cur_time);
		if (ret == -1) {
			PERROR("clock_gettime");
			connect_ret = ret;
			goto error;
		}
	} while (time_diff_ms(&cur_time, &orig_time) < timeout);

	/* Timeout */
	errno = ETIMEDOUT;
	connect_ret = -1;

success:
	/* Restore initial flags */
	ret = fcntl(sock->fd, F_SETFL, flags);
	if (ret == -1) {
		PERROR("fcntl");
		/* Continue anyway */
	}
error:
	return connect_ret;
}
Beispiel #10
0
/*
 * checks if a socket is connected or not by looking up the ip and port
 * of the remote host.
 * Returns 1 if connected and 0 if not.
 */
int net_is_connected(merlin_node *node)
{
	struct sockaddr_in sain;
	socklen_t slen;
	int optval = 0, gsoerr = 0, gsores = 0, gpnres = 0, gpnerr = 0;

	if (!node || node->sock < 0)
		return 0;

	if (node->state == STATE_CONNECTED)
		return 1;

	if (node->state != STATE_PENDING)
		return 0;

	/*
	 * yes, getpeername() actually has to be here, or getsockopt()
	 * won't return errors when we're not yet connected. It's
	 * important that we read the socket error state though, or
	 * some older kernels will maintain the link in SYN_SENT state
	 * more or less indefinitely, so get all the syscalls taken
	 * care of no matter if they actually work or not.
	 */
	errno = 0;
	slen = sizeof(struct sockaddr_in);
	gpnres = getpeername(node->sock, (struct sockaddr *)&sain, &slen);
	gpnerr = errno;
	slen = sizeof(optval);
	gsores = getsockopt(node->sock, SOL_SOCKET, SO_ERROR, &optval, &slen);
	gsoerr = errno;
	if (!gpnres && !gsores && !optval && !gpnerr && !gsoerr) {
		node_set_state(node, STATE_CONNECTED, "connect() attempt completed successfully");
		return 1;
	}

	/* diagnostics first */
	ldebug("%s is not connected: gpn/gso: %d:%d/%d:%d; optval: %d",
	       node->name, gpnres, gpnerr, gsores, gsoerr, optval);

	if (optval) {
		node_disconnect(node, "connect() to %s node %s failed: %s",
						node_type(node), node->name, strerror(optval));
		return 0;
	}

	if (gsores < 0 && gsoerr != ENOTCONN) {
		node_disconnect(node, "getsockopt(%d) failed for %s node %s: %s",
						node->sock, node_type(node), node->name, strerror(gsoerr));
	}

	if (gpnres < 0 && gpnerr != ENOTCONN) {
		lerr("getpeername(%d) failed for %s: %s",
			 node->sock, node->name, strerror(gpnerr));
	}

	/*
	 * if a connection is in progress, we should be getting
	 * ENOTCONN, but we need to give it time to complete
	 * first. 30 seconds should be enough.
	 */
	if (node->last_conn_attempt + MERLIN_CONNECT_TIMEOUT < time(NULL)) {
		node_disconnect(node, "connect() timed out after %d seconds",
						MERLIN_CONNECT_TIMEOUT);
	}

	return 0;
}
Beispiel #11
0
int
net_connect (struct sockaddr_in *cs, char *server,
        unsigned short int port, int sec)
{
        int                     n,
                                len,
                                error,
                                flags;
        int                     fd;
        struct timeval          tv;
        fd_set                  rset, wset;
        struct sockaddr_in      csa;

        if (cs == NULL)
                cs = &csa;

        /* first allocate a socket */
        cs->sin_family = AF_INET;
        cs->sin_port = htons (port);
        fd = socket (cs->sin_family, SOCK_STREAM, 0);
        if (fd == -1)
                return (-1);

        if (!(cs->sin_addr.s_addr = net_resolve (server))) {
                close (fd);
                return (-1);
        }

        flags = fcntl (fd, F_GETFL, 0);
        if (flags == -1) {
                close (fd);
                return (-1);
        }
        n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
        if (n == -1) {
                close (fd);
                return (-1);
        }

        error = 0;

        n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
        if (n < 0) {
                if (errno != EINPROGRESS) {
                        close (fd);
                        return (-1);
                }
        }
        if (n == 0)
                goto done;

        FD_ZERO(&rset);
        FD_ZERO(&wset);
        FD_SET(fd, &rset);
        FD_SET(fd, &wset);
        tv.tv_sec = sec;
        tv.tv_usec = 0;

        n = select(fd + 1, &rset, &wset, NULL, &tv);
        if (n == 0) {
                close(fd);
                errno = ETIMEDOUT;
                return (-1);
        }
        if (n == -1)
                return (-1);

        if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
                if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
                        len = sizeof(error);
                        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
                                errno = ETIMEDOUT;
                                return (-1);
                        }
                        if (error == 0) {
                                goto done;
                        } else {
                                errno = error;
                                return (-1);
                        }
                }
        } else
                return (-1);

done:
        n = fcntl(fd, F_SETFL, flags);
        if (n == -1)
                return (-1);
        return (fd);
}
Beispiel #12
0
static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
	{
	long ret=1;
	int *ip;
	struct sockaddr *to = NULL;
	bio_dgram_data *data = NULL;
#if defined(IP_MTU_DISCOVER) || defined(IP_MTU)
	long sockopt_val = 0;
	unsigned int sockopt_len = 0;
#endif
#ifdef OPENSSL_SYS_LINUX
	socklen_t addr_len;
	union	{
		struct sockaddr	sa;
		struct sockaddr_in s4;
#if OPENSSL_USE_IPV6
		struct sockaddr_in6 s6;
#endif
		} addr;
#endif

	data = (bio_dgram_data *)b->ptr;

	switch (cmd)
		{
	case BIO_CTRL_RESET:
		num=0;
	case BIO_C_FILE_SEEK:
		ret=0;
		break;
	case BIO_C_FILE_TELL:
	case BIO_CTRL_INFO:
		ret=0;
		break;
	case BIO_C_SET_FD:
		dgram_clear(b);
		b->num= *((int *)ptr);
		b->shutdown=(int)num;
		b->init=1;
		break;
	case BIO_C_GET_FD:
		if (b->init)
			{
			ip=(int *)ptr;
			if (ip != NULL) *ip=b->num;
			ret=b->num;
			}
		else
			ret= -1;
		break;
	case BIO_CTRL_GET_CLOSE:
		ret=b->shutdown;
		break;
	case BIO_CTRL_SET_CLOSE:
		b->shutdown=(int)num;
		break;
	case BIO_CTRL_PENDING:
	case BIO_CTRL_WPENDING:
		ret=0;
		break;
	case BIO_CTRL_DUP:
	case BIO_CTRL_FLUSH:
		ret=1;
		break;
	case BIO_CTRL_DGRAM_CONNECT:
		to = (struct sockaddr *)ptr;
#if 0
		if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
			{ perror("connect"); ret = 0; }
		else
			{
#endif
			switch (to->sa_family)
				{
				case AF_INET:
					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
					break;
#if OPENSSL_USE_IPV6
				case AF_INET6:
					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
					break;
#endif
				default:
					memcpy(&data->peer,to,sizeof(data->peer.sa));
					break;
				}
#if 0
			}
#endif
		break;
		/* (Linux)kernel sets DF bit on outgoing IP packets */
	case BIO_CTRL_DGRAM_MTU_DISCOVER:
#ifdef OPENSSL_SYS_LINUX
		addr_len = (socklen_t)sizeof(addr);
		memset((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
			{
			ret = 0;
			break;
			}
		sockopt_len = sizeof(sockopt_val);
		switch (addr.sa.sa_family)
			{
		case AF_INET:
			sockopt_val = IP_PMTUDISC_DO;
			if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
				&sockopt_val, sizeof(sockopt_val))) < 0)
				perror("setsockopt");
			break;
#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER)
		case AF_INET6:
			sockopt_val = IPV6_PMTUDISC_DO;
			if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
				&sockopt_val, sizeof(sockopt_val))) < 0)
				perror("setsockopt");
			break;
#endif
		default:
			ret = -1;
			break;
			}
		ret = -1;
#else
		break;
#endif
	case BIO_CTRL_DGRAM_QUERY_MTU:
#ifdef OPENSSL_SYS_LINUX
		addr_len = (socklen_t)sizeof(addr);
		memset((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
			{
			ret = 0;
			break;
			}
		sockopt_len = sizeof(sockopt_val);
		switch (addr.sa.sa_family)
			{
		case AF_INET:
			if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
				&sockopt_len)) < 0 || sockopt_val < 0)
				{
				ret = 0;
				}
			else
				{
				/* we assume that the transport protocol is UDP and no
				 * IP options are used.
				 */
				data->mtu = sockopt_val - 8 - 20;
				ret = data->mtu;
				}
			break;
#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
		case AF_INET6:
			if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
				&sockopt_len)) < 0 || sockopt_val < 0)
				{
				ret = 0;
				}
			else
				{
				/* we assume that the transport protocol is UDP and no
				 * IPV6 options are used.
				 */
				data->mtu = sockopt_val - 8 - 40;
				ret = data->mtu;
				}
			break;
#endif
		default:
			ret = 0;
			break;
			}
#else
		ret = 0;
#endif
		break;
	case BIO_CTRL_DGRAM_GET_MTU:
		return data->mtu;
		break;
	case BIO_CTRL_DGRAM_SET_MTU:
		data->mtu = num;
		ret = num;
		break;
	case BIO_CTRL_DGRAM_SET_CONNECTED:
		to = (struct sockaddr *)ptr;

		if ( to != NULL)
			{
			data->connected = 1;
			switch (to->sa_family)
				{
				case AF_INET:
					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
					break;
#if OPENSSL_USE_IPV6
				case AF_INET6:
					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
					break;
#endif
				default:
					memcpy(&data->peer,to,sizeof(data->peer.sa));
					break;
				}
			}
		else
			{
			data->connected = 0;
			memset(&(data->peer), 0x00, sizeof(data->peer));
			}
		break;
	case BIO_CTRL_DGRAM_GET_PEER:
		switch (data->peer.sa.sa_family)
			{
			case AF_INET:
				ret=sizeof(data->peer.sa_in);
				break;
#if OPENSSL_USE_IPV6
			case AF_INET6:
				ret=sizeof(data->peer.sa_in6);
				break;
#endif
			default:
				ret=sizeof(data->peer.sa);
				break;
			}
		if (num==0 || num>ret)
			num=ret;
		memcpy(ptr,&data->peer,(ret=num));
		break;
	case BIO_CTRL_DGRAM_SET_PEER:
		to = (struct sockaddr *) ptr;
		switch (to->sa_family)
			{
			case AF_INET:
				memcpy(&data->peer,to,sizeof(data->peer.sa_in));
				break;
#if OPENSSL_USE_IPV6
			case AF_INET6:
				memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
				break;
#endif
			default:
				memcpy(&data->peer,to,sizeof(data->peer.sa));
				break;
			}
		break;
	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
		break;
#if defined(SO_RCVTIMEO)
	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		struct timeval *tv = (struct timeval *)ptr;
		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
			(void*)&timeout, sizeof(timeout)) < 0)
			{ perror("setsockopt"); ret = -1; }
		}
#else
		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
			sizeof(struct timeval)) < 0)
			{ perror("setsockopt");	ret = -1; }
#endif
		break;
	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		int timeout, sz = sizeof(timeout);
		struct timeval *tv = (struct timeval *)ptr;
		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
			(void*)&timeout, &sz) < 0)
			{ perror("getsockopt"); ret = -1; }
		else
			{
			tv->tv_sec = timeout / 1000;
			tv->tv_usec = (timeout % 1000) * 1000;
			ret = sizeof(*tv);
			}
		}
#else
		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
			ptr, (void *)&ret) < 0)
			{ perror("getsockopt"); ret = -1; }
#endif
		break;
#endif
#if defined(SO_SNDTIMEO)
	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		struct timeval *tv = (struct timeval *)ptr;
		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
			(void*)&timeout, sizeof(timeout)) < 0)
			{ perror("setsockopt"); ret = -1; }
		}
#else
		if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
			sizeof(struct timeval)) < 0)
			{ perror("setsockopt");	ret = -1; }
#endif
		break;
	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		int timeout, sz = sizeof(timeout);
		struct timeval *tv = (struct timeval *)ptr;
		if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
			(void*)&timeout, &sz) < 0)
			{ perror("getsockopt"); ret = -1; }
		else
			{
			tv->tv_sec = timeout / 1000;
			tv->tv_usec = (timeout % 1000) * 1000;
			ret = sizeof(*tv);
			}
		}
#else
		if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 
			ptr, (void *)&ret) < 0)
			{ perror("getsockopt"); ret = -1; }
#endif
		break;
#endif
	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
		/* fall-through */
	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
#ifdef OPENSSL_SYS_WINDOWS
		if ( data->_errno == WSAETIMEDOUT)
#else
		if ( data->_errno == EAGAIN)
#endif
			{
			ret = 1;
			data->_errno = 0;
			}
		else
			ret = 0;
		break;
#ifdef EMSGSIZE
	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
		if ( data->_errno == EMSGSIZE)
			{
			ret = 1;
			data->_errno = 0;
			}
		else
			ret = 0;
		break;
#endif
	default:
		ret=0;
		break;
		}
	return(ret);
	}
Beispiel #13
0
JNIEXPORT jint JNICALL
Java_com_ghostagent_SoundManagementNative_connect(JNIEnv *env, jobject obj,
						  jint sockfd, jint timeout,
						  jstring address, jint port)
{
	const char *cp;
	struct sockaddr_in addr;
	int flags;
	int ret;
	fd_set wset;
	struct timeval tv;
	int error;
	socklen_t len;

	cp = (*env)->GetStringUTFChars(env, address, NULL);
	if (cp == NULL)
		return -1;

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(cp);

	(*env)->ReleaseStringUTFChars(env, address, cp);

	flags = fcntl(sockfd, F_GETFL);
	if (flags < 0)
		return -1;

	if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0)
		return -1;

	ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
	if (ret == 0) {
		fcntl(sockfd, F_SETFL, flags);
		return 0;
	}
	if (errno != EINPROGRESS) {
		fcntl(sockfd, F_SETFL, flags);
		return -1;
	}

	FD_ZERO(&wset);
	FD_SET(sockfd, &wset);

	memset(&tv, 0, sizeof(tv));
	tv.tv_sec = (time_t)timeout;

	if (select(sockfd + 1, NULL, &wset, NULL, &tv) <= 0) {
		fcntl(sockfd, F_SETFL, flags);
		return -1;
	}

	len = sizeof(error);
	ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
	if (ret < 0 || error != 0) {
		fcntl(sockfd, F_SETFL, flags);
		return -1;
	}

	fcntl(sockfd, F_SETFL, flags);
	return 0;
}
Beispiel #14
0
/**
 * @brief               SSH poll callback. This callback will be used when an event
 *                      caught on the socket.
 *
 * @param p             Poll object this callback belongs to.
 * @param fd            The raw socket.
 * @param revents       The current poll events on the socket.
 * @param userdata      Userdata to be passed to the callback function,
 *                      in this case the socket object.
 *
 * @return              0 on success, < 0 when the poll object has been removed
 *                      from its poll context.
 */
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
                            socket_t fd,
                            int revents,
                            void *v_s)
{
    ssh_socket s = (ssh_socket)v_s;
    char buffer[MAX_BUF_SIZE];
    ssize_t nread;
    int rc;
    int err = 0;
    socklen_t errlen = sizeof(err);

    /* Do not do anything if this socket was already closed */
    if (!ssh_socket_is_open(s)) {
        return -1;
    }
    SSH_LOG(SSH_LOG_TRACE, "Poll callback on socket %d (%s%s%s), out buffer %d",fd,
            (revents & POLLIN) ? "POLLIN ":"",
            (revents & POLLOUT) ? "POLLOUT ":"",
            (revents & POLLERR) ? "POLLERR":"",
            ssh_buffer_get_len(s->out_buffer));
    if ((revents & POLLERR) || (revents & POLLHUP)) {
        /* Check if we are in a connecting state */
        if (s->state == SSH_SOCKET_CONNECTING) {
            s->state = SSH_SOCKET_ERROR;
            rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
            if (rc < 0) {
                err = errno;
            }
            s->last_errno = err;
            ssh_socket_close(s);
            if (s->callbacks != NULL && s->callbacks->connected != NULL) {
                s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR,
                                        err,
                                        s->callbacks->userdata);
            }

            return -1;
        }
        /* Then we are in a more standard kind of error */
        /* force a read to get an explanation */
        revents |= POLLIN;
    }
    if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) {
        s->read_wontblock = 1;
        nread = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer));
        if (nread < 0) {
            if (p != NULL) {
                ssh_poll_remove_events(p, POLLIN);
            }

            if (s->callbacks != NULL && s->callbacks->exception != NULL) {
                s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
                                        s->last_errno,
                                        s->callbacks->userdata);
            }
            return -2;
        }
        if (nread == 0) {
            if (p != NULL) {
                ssh_poll_remove_events(p, POLLIN);
            }
            if (s->callbacks != NULL && s->callbacks->exception != NULL) {
                s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF,
                                        0,
                                        s->callbacks->userdata);
            }
            return -2;
        }

        if (s->session->socket_counter != NULL) {
            s->session->socket_counter->in_bytes += nread;
        }

        /* Bufferize the data and then call the callback */
        rc = ssh_buffer_add_data(s->in_buffer, buffer, nread);
        if (rc < 0) {
            return -1;
        }
        if (s->callbacks != NULL && s->callbacks->data != NULL) {
            do {
                nread = s->callbacks->data(ssh_buffer_get(s->in_buffer),
                                       ssh_buffer_get_len(s->in_buffer),
                                       s->callbacks->userdata);
                ssh_buffer_pass_bytes(s->in_buffer, nread);
            } while ((nread > 0) && (s->state == SSH_SOCKET_CONNECTED));

            /* p may have been freed, so don't use it
             * anymore in this function */
            p = NULL;
        }
    }
#ifdef _WIN32
    if (revents & POLLOUT || revents & POLLWRNORM) {
#else
    if (revents & POLLOUT) {
#endif
        uint32_t len;

        /* First, POLLOUT is a sign we may be connected */
        if (s->state == SSH_SOCKET_CONNECTING) {
            SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state");
            s->state = SSH_SOCKET_CONNECTED;
            if (p != NULL) {
                ssh_poll_set_events(p, POLLOUT | POLLIN);
            }

            rc = ssh_socket_set_blocking(ssh_socket_get_fd(s));
            if (rc < 0) {
                return -1;
            }

            if (s->callbacks != NULL && s->callbacks->connected != NULL) {
                s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,
                                        0,
                                        s->callbacks->userdata);
            }

            return 0;
        }

        /* So, we can write data */
        s->write_wontblock = 1;
        if (p != NULL) {
            ssh_poll_remove_events(p, POLLOUT);
        }

        /* If buffered data is pending, write it */
        len = ssh_buffer_get_len(s->out_buffer);
        if (len > 0) {
            ssh_socket_nonblocking_flush(s);
        } else if (s->callbacks != NULL && s->callbacks->controlflow != NULL) {
            /* Otherwise advertise the upper level that write can be done */
            SSH_LOG(SSH_LOG_TRACE,"sending control flow event");
            s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,
                                      s->callbacks->userdata);
        }
        /* TODO: Find a way to put back POLLOUT when buffering occurs */
    }

    /* Return -1 if the poll handler disappeared */
    if (s->poll_handle == NULL) {
        return -1;
    }

    return 0;
}

/** @internal
 * @brief returns the poll handle corresponding to the socket,
 * creates it if it does not exist.
 * @returns allocated and initialized ssh_poll_handle object
 */
ssh_poll_handle ssh_socket_get_poll_handle(ssh_socket s)
{
    if (s->poll_handle) {
        return s->poll_handle;
    }
    s->poll_handle = ssh_poll_new(s->fd,0,ssh_socket_pollcallback,s);
    return s->poll_handle;
}

/** \internal
 * \brief Deletes a socket object
 */
void ssh_socket_free(ssh_socket s){
  if (s == NULL) {
    return;
  }
  ssh_socket_close(s);
  ssh_buffer_free(s->in_buffer);
  ssh_buffer_free(s->out_buffer);
  SAFE_FREE(s);
}

#ifndef _WIN32
int ssh_socket_unix(ssh_socket s, const char *path) {
  struct sockaddr_un sunaddr;
  socket_t fd;
  sunaddr.sun_family = AF_UNIX;
  snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);

  fd = socket(AF_UNIX, SOCK_STREAM, 0);
  if (fd == SSH_INVALID_SOCKET) {
    ssh_set_error(s->session, SSH_FATAL,
		    "Error from socket(AF_UNIX, SOCK_STREAM, 0): %s",
		    strerror(errno));
    return -1;
  }

  if (fcntl(fd, F_SETFD, 1) == -1) {
    ssh_set_error(s->session, SSH_FATAL,
		    "Error from fcntl(fd, F_SETFD, 1): %s",
		    strerror(errno));
    close(fd);
    return -1;
  }

  if (connect(fd, (struct sockaddr *) &sunaddr,
        sizeof(sunaddr)) < 0) {
    ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
		    strerror(errno));
    close(fd);
    return -1;
  }
  ssh_socket_set_fd(s,fd);
  return 0;
}
#endif

/** \internal
 * \brief closes a socket
 */
void ssh_socket_close(ssh_socket s){
  if (ssh_socket_is_open(s)) {
#ifdef _WIN32
    CLOSE_SOCKET(s->fd);
    s->last_errno = WSAGetLastError();
#else
    CLOSE_SOCKET(s->fd);
    s->last_errno = errno;
#endif
  }

  if(s->poll_handle != NULL){
    ssh_poll_free(s->poll_handle);
    s->poll_handle=NULL;
  }

  s->state = SSH_SOCKET_CLOSED;
}

/**
 * @internal
 * @brief sets the file descriptor of the socket.
 * @param[out] s ssh_socket to update
 * @param[in] fd file descriptor to set
 * @warning this function updates boths the input and output
 * file descriptors
 */
void ssh_socket_set_fd(ssh_socket s, socket_t fd) {
    s->fd = fd;

    if (s->poll_handle) {
        ssh_poll_set_fd(s->poll_handle,fd);
    } else {
        s->state = SSH_SOCKET_CONNECTING;

        /* POLLOUT is the event to wait for in a nonblocking connect */
        ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLOUT);
#ifdef _WIN32
        ssh_poll_add_events(ssh_socket_get_poll_handle(s), POLLWRNORM);
#endif
    }
}
Beispiel #15
0
/**
 * @brief
 *	Open a connection with a pbs server.
 *	Do not allow TCP to block us if Server host is down
 *	At this point, this does not attempt to find a fail_over Server
 *
 * @param[in]   server - specifies the server to which to connect
 * @param[in]   tout - timeout value for select
 *
 * @return int
 * @retval >= 0	index to the internal connection table representing the
 *		connection made.
 * @retval -1	error encountered in getting index
 */
int
pbs_connect_noblk(char *server, int tout)
{
	int out;
	int i;
	pbs_socklen_t l;
	int n;
	struct timeval tv;
	fd_set fdset;
	struct batch_reply *reply;
	char server_name[PBS_MAXSERVERNAME+1];
	unsigned int server_port;
	struct addrinfo *aip, *pai;
	struct addrinfo hints;
	struct sockaddr_in *inp;
	short int connect_err = 0;

	struct sockaddr_in sockname;
	pbs_socklen_t	 socknamelen;

#ifdef WIN32
	int     non_block = 1;
	struct sockaddr_in to_sock;
	struct sockaddr_in from_sock;
#endif

#ifndef WIN32
	int nflg;
	int oflg;
#endif

	/* initialize the thread context data, if not already initialized */
	if (pbs_client_thread_init_thread_context() != 0)
		return -1;

	if (pbs_loadconf(0) == 0)
		return -1;

	/* get server host and port	*/

	server = PBS_get_server(server, server_name, &server_port);
	if (server == NULL) {
		pbs_errno = PBSE_NOSERVER;
		return -1;
	}

	/* Reserve a connection state record */
	if (pbs_client_thread_lock_conntable() != 0)
		return -1;

	out = -1;
	for (i=1;i<NCONNECTS;i++) {
		if (connection[i].ch_inuse) continue;
		out = i;
		connection[out].ch_inuse = 1;
		connection[out].ch_errno = 0;
		connection[out].ch_socket= -1;
		connection[out].ch_errtxt = NULL;
		break;
	}

	if (pbs_client_thread_unlock_conntable() != 0)
		return -1; /* pbs_errno set by the function */

	if (out < 0) {
		pbs_errno = PBSE_NOCONNECTS;
		return -1;
	}


	/* get socket	*/

#ifdef WIN32
	/* the following lousy hack is needed since the socket call needs */
	/* SYSTEMROOT env variable properly set! */
	if (getenv("SYSTEMROOT") == NULL) {
		setenv("SYSTEMROOT", "C:\\WINNT", 1);
		setenv("SystemRoot", "C:\\WINNT", 1);
	}
	connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (connection[out].ch_socket < 0) {
		setenv("SYSTEMROOT", "C:\\WINDOWS", 1);
		setenv("SystemRoot", "C:\\WINDOWS", 1);
		connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
	}
#else
	connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
#endif
	if (connection[out].ch_socket < 0) {
		connection[out].ch_inuse = 0;
		pbs_errno = ERRORNO;
		return -1;
	}

	/* set socket non-blocking */

#ifdef WIN32
	if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR)
#else
	oflg = fcntl(connection[out].ch_socket, F_GETFL) & ~O_ACCMODE;
	nflg = oflg | O_NONBLOCK;
	if (fcntl(connection[out].ch_socket, F_SETFL, nflg) == -1)
#endif
		goto err;

	/* and connect... */

	strcpy(pbs_server, server);    /* set for error messages from commands */
	memset(&hints, 0, sizeof(struct addrinfo));
	/*
	 *      Why do we use AF_UNSPEC rather than AF_INET?  Some
	 *      implementations of getaddrinfo() will take an IPv6
	 *      address and map it to an IPv4 one if we ask for AF_INET
	 *      only.  We don't want that - we want only the addresses
	 *      that are genuinely, natively, IPv4 so we start with
	 *      AF_UNSPEC and filter ai_family below.
	 */
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (getaddrinfo(server, NULL, &hints, &pai) != 0) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_BADHOST;
		return -1;
	}
	for (aip = pai; aip != NULL; aip = aip->ai_next) {
		/* skip non-IPv4 addresses */
		if (aip->ai_family == AF_INET) {
			inp = (struct sockaddr_in *) aip->ai_addr;
			break;
		}
	}
	if (aip == NULL) {
		/* treat no IPv4 addresses as getaddrinfo() failure */
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_BADHOST;
		freeaddrinfo(pai);
		return -1;
	} else
		inp->sin_port = htons(server_port);
	if (connect(connection[out].ch_socket,
		aip->ai_addr,
		aip->ai_addrlen) < 0) {
		connect_err = 1;
	}
	if (connect_err == 1)
	{
		/* connect attempt failed */
		pbs_errno = ERRORNO;
		switch (pbs_errno) {
#ifdef WIN32
			case WSAEWOULDBLOCK:
#else
			case EINPROGRESS:
			case EWOULDBLOCK:
#endif
				while (1) {
					FD_ZERO(&fdset);
					FD_SET(connection[out].ch_socket, &fdset);
					tv.tv_sec = tout;
					tv.tv_usec = 0;
					n = select(connection[out].ch_socket+1, NULL, &fdset, NULL, &tv);
					if (n > 0) {
						pbs_errno = 0;
						l = sizeof(pbs_errno);
						(void)getsockopt(connection[out].ch_socket,
							SOL_SOCKET, SO_ERROR,
							&pbs_errno, &l);
						if (pbs_errno == 0)
							break;
						else
							goto err;
					} if ((n < 0) &&
#ifdef WIN32
						(ERRORNO == WSAEINTR)
#else
						(ERRORNO == EINTR)
#endif
						) {
						continue;
					} else {
						goto err;
					}
				}
				break;

			default:
err:
				CLOSESOCKET(connection[out].ch_socket);
				connection[out].ch_inuse = 0;
				freeaddrinfo(pai);
				return -1;	/* cannot connect */

		}
	}
	freeaddrinfo(pai);

	/* reset socket blocking */
#ifdef WIN32
	non_block = 0;
	if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR)
#else
	if (fcntl(connection[out].ch_socket, F_SETFL, oflg) < 0)
#endif
		goto err;

	/*
	 * multiple threads cant get the same connection id above,
	 * so no need to lock this piece of code
	 */
	/* setup connection level thread context */
	if (pbs_client_thread_init_connect_context(out) != 0) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		/* pbs_errno set by the pbs_connect_init_context routine */
		return -1;
	}
	/*
	 * even though the following is communication with server on
	 * a connection handle, it does not need to be lock since
	 * this connection handle has not be returned back yet to the client
	 * so others threads cannot use it
	 */

	/* send "dummy" connect message */
	DIS_tcp_setup(connection[out].ch_socket);
	if ((i = encode_DIS_ReqHdr(connection[out].ch_socket,
		PBS_BATCH_Connect, pbs_current_user)) ||
		(i = encode_DIS_ReqExtend(connection[out].ch_socket,
		NULL))) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}
	if (DIS_tcp_wflush(connection[out].ch_socket)) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}
	reply = PBSD_rdrpy(out);
	PBSD_FreeReply(reply);

	/*do configured authentication (kerberos, pbs_iff, whatever)*/

	/*Get the socket port for engage_authentication()*/
	socknamelen = sizeof(sockname);
	if (getsockname(connection[out].ch_socket, (struct sockaddr *)&sockname, &socknamelen))
		return -1;
	if (engage_authentication(connection[out].ch_socket,
		server,
		server_port,
		&sockname) == -1) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_PERM;
		return -1;
	}

	/* setup DIS support routines for following pbs_* calls */
	DIS_tcp_setup(connection[out].ch_socket);
	pbs_tcp_timeout = PBS_DIS_TCP_TIMEOUT_VLONG;	/* set for 3 hours */

	return out;
}
int connect_with_timeout(char *host, int port, int timeout_sec,
		int timeout_usec, char *account)
{
	  int res, valopt;
	  struct sockaddr_in addr;
	  long arg;
	  fd_set myset;
	  struct timeval tv;
	  socklen_t lon;
	  char buffer[181] = {0};

	  /* Base64 */
	  char sender[181] = {0};
	  char receiver[181] = {0};
	  int rc;

	  // Create socket
	  int soc = socket(AF_INET, SOCK_STREAM, 0);

	  // Set non-blocking
	  arg = fcntl(soc, F_GETFL, NULL);
	  arg |= O_NONBLOCK;
	  fcntl(soc, F_SETFL, arg);

	  // Trying to connect with timeout
	  addr.sin_family = AF_INET;
	  addr.sin_port = htons(port);
	  addr.sin_addr.s_addr = inet_addr(host);
	  res = connect(soc, (struct sockaddr *)&addr, sizeof(addr));

	  if (res < 0) {
	     if (errno == EINPROGRESS) {
	        tv.tv_sec = timeout_sec;
	        tv.tv_usec = timeout_usec;
	        FD_ZERO(&myset);
	        FD_SET(soc, &myset);
	        if (select(soc+1, NULL, &myset, NULL, &tv) > 0) {
	           lon = sizeof(int);
	           getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
	           if (valopt) {
	              return -2;
	           }
	        }
	        else {
	           return -3;
	        }
	     }
	     else {
	        return -4;
	     }
	  }

	  // Set to blocking mode again...
	  arg = fcntl(soc, F_GETFL, NULL);
	  arg &= (~O_NONBLOCK);
	  fcntl(soc, F_SETFL, arg);

	  rc = Base64Encode(account, sender, BUFFFERLEN);
	  send(soc,sender,181,NULL);
	  recv(soc, buffer, 181, NULL);
	  rc = Base64Decode(buffer, receiver, BUFFFERLEN);

	  printf ("Connect to server: account= %s, buffer = %s\n", account, buffer);
	  if (strcmp(buffer,"Failed"))
	  {
		  return soc;
	  }
	  else
	  {
		shutdown(soc,2);
		return -5;
	  }
}
Beispiel #17
0
static int tcpconn_async_connect(struct socket_info* send_sock,
					union sockaddr_union* server, char *buf, unsigned len,
					struct tcp_connection** c, int *ret_fd)
{
	int fd, n;
	union sockaddr_union my_name;
	socklen_t my_name_len;
	struct tcp_connection* con;

	struct pollfd pf;

	unsigned int elapsed,to;
	int err;
	unsigned int err_len;
	int poll_err;
	char *ip;
	unsigned short port;
	struct timeval begin;

	/* create the socket */
	fd = socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
	if (fd == -1){
		LM_ERR("socket: (%d) %s\n", errno, strerror(errno));
		return -1;
	}
	if (tcp_init_sock_opt(fd)<0){
		LM_ERR("tcp_init_sock_opt failed\n");
		goto error;
	}
	my_name_len = sockaddru_len(send_sock->su);
	memcpy( &my_name, &send_sock->su, my_name_len);
	su_setport( &my_name, 0);
	if (bind(fd, &my_name.s, my_name_len )!=0) {
		LM_ERR("bind failed (%d) %s\n", errno,strerror(errno));
		goto error;
	}

	/* attempt to do connect and see if we do block or not */
	poll_err = 0;
	elapsed = 0;
	to = hep_async_local_connect_timeout*1000;

	if (gettimeofday(&(begin), NULL)) {
		LM_ERR("Failed to get TCP connect start time\n");
		goto error;
	}

again:
	n = connect(fd, &server->s, sockaddru_len(*server));
	if (n == -1) {
		if (errno == EINTR){
			elapsed=get_time_diff(&begin);
			if (elapsed < to) goto again;
			else {
				LM_DBG("Local connect attempt failed \n");
				goto async_connect;
			}
		}
		if (errno != EINPROGRESS && errno!=EALREADY) {
			get_su_info(&server->s, ip, port);
			LM_ERR("[server=%s:%d] (%d) %s\n",ip, port, errno,strerror(errno));
			goto error;
		}
	} else goto local_connect;

	/* let's poll for a little */

	pf.fd = fd;
	pf.events = POLLOUT;

	while(1){
		elapsed = get_time_diff(&begin);
		if (elapsed < to)
			to -= elapsed;
		else {
			LM_DBG("Polling is overdue \n");
			goto async_connect;
		}

		n = poll(&pf, 1, to/1000);

		if (n < 0){
			if (errno == EINTR) continue;
			get_su_info(&server->s, ip, port);
			LM_ERR("poll/select failed:[server=%s:%d] (%d) %s\n",
				ip, port, errno, strerror(errno));
			goto error;
		} else if (n==0) /* timeout */ continue;

		if (pf.revents & (POLLERR|POLLHUP|POLLNVAL)){
			LM_ERR("poll error: flags %x\n", pf.revents);
			poll_err=1;
		}


		err_len=sizeof(err);
		getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
		if ((err==0) && (poll_err==0)) goto local_connect;
		if (err!=EINPROGRESS && err!=EALREADY){
			get_su_info(&server->s, ip, port);
			LM_ERR("failed to retrieve SO_ERROR [server=%s:%d] (%d) %s\n",
				ip, port, err, strerror(err));
			goto error;
		}
	}

async_connect:
	LM_DBG("Create connection for async connect\n");
	/* create a new dummy connection */
	con = tcp_conn_create(fd, server, send_sock, S_CONN_CONNECTING);
	if (con==NULL) {
		LM_ERR("tcp_conn_create failed\n");
		goto error;
	}

	/* attach the write buffer to it */
	lock_get(&con->write_lock);

	if (add_write_chunk(con,buf,len,0) < 0) {
		LM_ERR("Failed to add the initial write chunk\n");
		/* FIXME - seems no more SHM now ...
		 * continue the async connect process ? */
	}

	lock_release(&con->write_lock);
	/* report an async, in progress connect */
	*c = con;
	return 0;

local_connect:
	con = tcp_conn_create(fd, server, send_sock, S_CONN_OK);
	if (con==NULL) {
		LM_ERR("tcp_conn_create failed, closing the socket\n");
		goto error;
	}
	*c = con;
	*ret_fd = fd;
	/* report a local connect */
	return 1;

error:
	close(fd);
	*c = NULL;
	return -1;
}
Beispiel #18
0
int
main(int argc, char **argv)
{
    struct sockaddr_storage __ss;
    struct sockaddr *sa = (struct sockaddr *)&__ss;
    int on = 1;
    socklen_t sa_size;
    int ch;
#if	defined(IPPROTO_IP) && defined(IP_TOS)
    int tos = -1;
#endif
#ifdef ENCRYPTION
    des_check_key = 1;	/* Kludge for Mac NCSA telnet 2.6 /bg */
#endif

	pfrontp = pbackp = ptyobuf;
    netip = netibuf;
    nfrontp = nbackp = netobuf;
	    
#ifdef __SYMBIAN32__
	if( getConnectionUp() < 0) exit(1);
#endif	

    setprogname(argv[0]);

    progname = *argv;
#ifdef ENCRYPTION
    nclearto = 0;
#endif

#ifdef _CRAY
    /*
     * Get number of pty's before trying to process options,
     * which may include changing pty range.
     */
    highpty = getnpty();
#endif /* CRAY */

    if (argc == 2 && strcmp(argv[1], "--version") == 0) {
#ifndef __SYMBIAN32__
	print_version(NULL); 
#endif //__SYMBIAN32__
	exit(0);
    }

    while ((ch = getopt(argc, argv, valid_opts)) != -1) {
	switch(ch) {

#ifdef	AUTHENTICATION
	case 'a':
	    /*
	     * Check for required authentication level
	     */
	    if (strcmp(optarg, "debug") == 0) {
		auth_debug_mode = 1;
	    } else if (strcasecmp(optarg, "none") == 0) {
		auth_level = 0;
	    } else if (strcasecmp(optarg, "otp") == 0) {
		auth_level = 0;
		require_otp = 1;
	    } else if (strcasecmp(optarg, "other") == 0) {
		auth_level = AUTH_OTHER;
	    } else if (strcasecmp(optarg, "user") == 0) {
		auth_level = AUTH_USER;
	    } else if (strcasecmp(optarg, "valid") == 0) {
		auth_level = AUTH_VALID;
	    } else if (strcasecmp(optarg, "off") == 0) {
		/*
		 * This hack turns off authentication
		 */
		auth_level = -1;
	    } else {
		fprintf(stderr,
			"telnetd: unknown authorization level for -a\n");
	    }
	    break;
#endif	/* AUTHENTICATION */

	case 'B': /* BFTP mode is not supported any more */
	    break;
	case 'd':
	    if (strcmp(optarg, "ebug") == 0) {
		debug++;
		break;
	    }
	    usage();
	    /* NOTREACHED */
	    break;

#ifdef DIAGNOSTICS
	case 'D':
	    /*
	     * Check for desired diagnostics capabilities.
	     */
	    if (!strcmp(optarg, "report")) {
		diagnostic |= TD_REPORT|TD_OPTIONS;
	    } else if (!strcmp(optarg, "exercise")) {
		diagnostic |= TD_EXERCISE;
	    } else if (!strcmp(optarg, "netdata")) {
		diagnostic |= TD_NETDATA;
	    } else if (!strcmp(optarg, "ptydata")) {
		diagnostic |= TD_PTYDATA;
	    } else if (!strcmp(optarg, "options")) {
		diagnostic |= TD_OPTIONS;
	    } else {
		usage();
		/* NOT REACHED */
	    }
	    break;
#endif /* DIAGNOSTICS */


	case 'h':
	    hostinfo = 0;
	    break;

	case 'k': /* Linemode is not supported any more */
	case 'l':
	    break;

	case 'n':
	    keepalive = 0;
	    break;

#ifdef _CRAY
	case 'r':
	    {
		char *strchr();
		char *c;

		/*
		 * Allow the specification of alterations
		 * to the pty search range.  It is legal to
		 * specify only one, and not change the
		 * other from its default.
		 */
		c = strchr(optarg, '-');
		if (c) {
		    *c++ = '\0';
		    highpty = atoi(c);
		}
		if (*optarg != '\0')
		    lowpty = atoi(optarg);
		if ((lowpty > highpty) || (lowpty < 0) ||
		    (highpty > 32767)) {
		    usage();
		    /* NOT REACHED */
		}
		break;
	    }
#endif	/* CRAY */

	case 'S':
#ifdef	HAVE_PARSETOS
	    if ((tos = parsetos(optarg, "tcp")) < 0)
		fprintf(stderr, "%s%s%s\n",
			"telnetd: Bad TOS argument '", optarg,
			"'; will try to use default TOS");
#else
	    fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
		    "-S flag not supported\n");
#endif
	    break;

	case 'u': {
	    char *eptr;

	    utmp_len = strtol(optarg, &eptr, 0);
	    if (optarg == eptr)
		fprintf(stderr, "telnetd: unknown utmp len (%s)\n", optarg);
	    break;
	}

	case 'U':
	    registerd_host_only = 1;
	    break;

#ifdef	AUTHENTICATION
	case 'X':
	    /*
	     * Check for invalid authentication types
	     */
	    auth_disable_name(optarg);
	    break;
#endif
	case 'y':
	    no_warn = 1;
	    break;
#ifdef AUTHENTICATION
	case 'z':
	    log_unauth = 1;
	    break;

#endif	/* AUTHENTICATION */

	case 'L':
	    new_login = optarg;
	    break;
			
	default:
	    fprintf(stderr, "telnetd: %c: unknown option\n", ch);
	    /* FALLTHROUGH */
	case '?':
	    usage();
	    /* NOTREACHED */
	}
    }

    argc -= optind;
    argv += optind;

    if (debug) {
	int port = 0;
	struct servent *sp;

	if (argc > 1) {
	    usage ();
	} else if (argc == 1) {
	    sp = (struct servent*)roken_getservbyname (*argv, "tcp");
	    if (sp)
		port = sp->s_port;
	    else
		port = htons(atoi(*argv));
	} else {
#ifdef 	__SYMBIAN32__
		port = htons(atoi("23"));		
#else
#ifdef KRB5
	    port = krb5_getportbyname (NULL, "telnet", "tcp", 23);
#else
	    port = k_getportbyname("telnet", "tcp", htons(23));
#endif
#endif //__SYMBIAN32__
	}
	mini_inetd (port);
    } else if (argc > 0) {
	usage();
	/* NOT REACHED */
    }

#ifdef _SC_CRAY_SECURE_SYS
    secflag = sysconf(_SC_CRAY_SECURE_SYS);

    /*
     *	Get socket's security label
     */
    if (secflag)  {
	socklen_t szss = sizeof(ss);
	int sock_multi;
	socklen_t szi = sizeof(int);

	memset(&dv, 0, sizeof(dv));

	if (getsysv(&sysv, sizeof(struct sysv)) != 0) 
	    fatalperror(net, "getsysv");

	/*
	 *	Get socket security label and set device values
	 *	   {security label to be set on ttyp device}
	 */
#ifdef SO_SEC_MULTI			/* 8.0 code */
	if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
			(void *)&ss, &szss) < 0) ||
	    (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
			(void *)&sock_multi, &szi) < 0)) 
	    fatalperror(net, "getsockopt");
	else {
	    dv.dv_actlvl = ss.ss_actlabel.lt_level;
	    dv.dv_actcmp = ss.ss_actlabel.lt_compart;
	    if (!sock_multi) {
		dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
		dv.dv_valcmp = dv.dv_actcmp;
	    } else {
		dv.dv_minlvl = ss.ss_minlabel.lt_level;
		dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
		dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
	    }
	    dv.dv_devflg = 0;
	}
#else /* SO_SEC_MULTI */		/* 7.0 code */
	if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
		       (void *)&ss, &szss) >= 0) {
	    dv.dv_actlvl = ss.ss_slevel;
	    dv.dv_actcmp = ss.ss_compart;
	    dv.dv_minlvl = ss.ss_minlvl;
	    dv.dv_maxlvl = ss.ss_maxlvl;
	    dv.dv_valcmp = ss.ss_maxcmp;
	}
#endif /* SO_SEC_MULTI */
    }
#endif	/* _SC_CRAY_SECURE_SYS */

 
    roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
    sa_size = sizeof (__ss);
    
    if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) {
	fprintf(stderr, "%s: ", progname);
	perror("getpeername");
	_exit(1);
    }

    if (keepalive &&
	setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
		   (void *)&on, sizeof (on)) < 0) {		 
#ifndef __SYMBIAN32__		     
	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
#endif
	;
    }
    

#if	defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
    {
# ifdef HAVE_GETTOSBYNAME
	struct tosent *tp;
	if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
	    tos = tp->t_tos;
# endif
	if (tos < 0)
	    tos = 020;	/* Low Delay bit */
	if (tos
	    && sa->sa_family == AF_INET
	    && (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
			   (void *)&tos, sizeof(tos)) < 0)
	    && (errno != ENOPROTOOPT) )
	    syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
    }
#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
    net = STDIN_FILENO;
    doit(sa, sa_size);
    /* NOTREACHED */
    return 0;
}  /* end of main */
Beispiel #19
0
void ps_terminal_run_program(int fd_control, char *arguments)
{
    int fd_master, pid_program, exit_status;
    socklen_t sizeof_credentials;
    struct ucred credentials;

    // run the program under the uid of the user that connected to the server

    sizeof_credentials = sizeof(credentials);

    if(getsockopt(fd_control, SOL_SOCKET, SO_PEERCRED, &credentials, &sizeof_credentials) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to get uid of controlling user - error [%s]"), strerror(errno));

    if (ps_terminal_set_user(credentials.uid) == EXIT_FAILURE)
    {
        ps_terminal_send_exitcode(fd_control, EXIT_FAILURE);
        return;
    }

    // create a pseudoterminal

    fd_master = posix_openpt(O_RDWR | O_NOCTTY);

    if (fd_master == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("posix_openpt() failed -error [%s]"), strerror(errno));

    if (grantpt(fd_master) == -1)
        ps_log(0 /*EXIT_FAILURE*/, LOG_ERROR("grantpt() failed - error [%s]"), strerror(errno));

    if (unlockpt(fd_master) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unlockpt() failed - error [%s]"), strerror(errno));

    // fork a new process to run the program

    pid_program=fork();

    if (pid_program == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unable to fork - error [%s]"), strerror(errno));

    if (pid_program == 0)
    {
        close(fd_control);
        ps_program_exec(fd_master, arguments);
        ps_log(EXIT_FAILURE, LOG_ERROR("trespassing error!"));
    }

//  TEST for a problem with bash. It seems that bash disables cntl-d (eof) handling
//  in the pseudo terminal if there is input before it outputs its prompt. This requires
//  us to use the exit statement in a script that is inside a here-document. The sh shell
//  does not have this behaviour. Needs further investigation...
//sleep(1);

    ps_terminal_io_loop(fd_control, fd_master);

    if (waitpid(pid_program, &exit_status, 0) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("waitpid failed - error [%s]"), strerror(errno));

    // return status to controller

    ps_log(0, LOG_INFO("after wait - exit_status [%d]"), exit_status);
    ps_terminal_send_exitcode(fd_control, exit_status);
    close(fd_master);
    close(fd_control);
}
Beispiel #20
0
int conn_nonb(char *ip,int port,int nsec)
{
    int flags, n, error;
    //socklen_t len;
    fd_set rset,wset;
    struct timeval tval;

    FD_ZERO(&wset);
    FD_ZERO(&rset);
    tval.tv_sec = nsec;
    tval.tv_usec = 0;
    //struct servent *sent;

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &address.sin_addr);
    address.sin_port = htons(port);

    error = 0;
    if((n=connect(sockfd,(struct sockaddr *)&address,sizeof(address)))<0){
        if(errno!=EINPROGRESS)
        {
            printf("Connecting error!\n");
            return -1;
        }
        else if(n==0)
        { //This case may be happen on localhost?
            printf("Connecting success! \n");
            return 0;
        }
    }
    FD_SET(sockfd,&rset);
    wset=rset;
    //usleep(10);


    int rst = select(sockfd + 1, &rset,&wset,NULL,&tval);

    switch (rst) {
        case -1:
            perror("Select error"); exit(-1);
        case 0:
            close(sockfd);
            //printf("Timed Out!\n");
            break;
        default:
            if (FD_ISSET(sockfd,&rset)||FD_ISSET(sockfd,&wset)) {
                int error;
                socklen_t len = sizeof (error);
                if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0)
                {
                    printf ("getsockopt fail,connected fail\n");
                    return -1;
                }
                if(error==0)
                {
                    //printf ("%d open\n",port);
                    return 0;
                }
            }
            close(sockfd);
    }
    return -1;
}
Beispiel #21
0
void
rpc_init(char *name, int prog, int vers, void (*dispatch)(), int defport)
{
	struct sockaddr_in saddr;
	SVCXPRT	*transp;
	int	sock;
	socklen_t asize;

	asize = sizeof(saddr);
	sock = 0;
	if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0
	    && saddr.sin_family == AF_INET) {
		socklen_t ssize = sizeof (int);
		int fdtype = 0;
		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
				(char *)&fdtype, &ssize) == -1)
			xlog(L_FATAL, "getsockopt failed: %s", strerror(errno));
		/* inetd passes a UDP socket or a listening TCP socket.
		 * listen will fail on a connected TCP socket(passed by rsh).
		 */
		if (!(fdtype == SOCK_STREAM && listen(0,5) == -1)) {
			_rpcfdtype = fdtype;
			_rpcpmstart = 1;
		}
	}
	if (!_rpcpmstart) {
		pmap_unset(prog, vers);
		sock = RPC_ANYSOCK;
	}

	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
		static SVCXPRT *last_transp = NULL;
 
		if (_rpcpmstart == 0) {
			if (last_transp
			    && (!defport || defport == last_transp->xp_port)) {
				transp = last_transp;
				goto udp_transport;
			}
			if (defport == 0)
				sock = RPC_ANYSOCK;
			else if ((sock = makesock(defport, IPPROTO_UDP)) < 0) {
				xlog(L_FATAL, "%s: cannot make a UDP socket\n",
						name);
			}
		}
		if (sock == RPC_ANYSOCK)
			sock = svcudp_socket (prog, 1);
		transp = svcudp_create(sock);
		if (transp == NULL) {
			xlog(L_FATAL, "cannot create udp service.");
		}
      udp_transport:
		if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) {
			xlog(L_FATAL, "unable to register (%s, %d, udp).",
					name, vers);
		}
		last_transp = transp;
	}

	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
		static SVCXPRT *last_transp = NULL;

		if (_rpcpmstart == 0) {
			if (last_transp
			    && (!defport || defport == last_transp->xp_port)) {
				transp = last_transp;
				goto tcp_transport;
			}
			if (defport == 0)
				sock = RPC_ANYSOCK;
			else if ((sock = makesock(defport, IPPROTO_TCP)) < 0) {
				xlog(L_FATAL, "%s: cannot make a TCP socket\n",
						name);
			}
		}
		if (sock == RPC_ANYSOCK)
			sock = svctcp_socket (prog, 1);
		transp = svctcp_create(sock, 0, 0);
		if (transp == NULL) {
			xlog(L_FATAL, "cannot create tcp service.");
		}
      tcp_transport:
		if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) {
			xlog(L_FATAL, "unable to register (%s, %d, tcp).",
					name, vers);
		}
		last_transp = transp;
	}

	if (_rpcpmstart) {
		signal (SIGALRM, closedown);
		alarm (_RPCSVC_CLOSEDOWN);
	}
}
Beispiel #22
0
/* we receive a connection acknowledgement from the server,
 * consisting of nothing more than a status report. If success,
 * then we initiate authentication method */
static pmix_status_t recv_connect_ack(int sd)
{
    pmix_status_t reply;
    pmix_status_t rc;
    struct timeval tv, save;
    pmix_socklen_t sz;
    bool sockopt = true;
    uint32_t u32;
    char nspace[PMIX_MAX_NSLEN+1];

    pmix_output_verbose(2, pmix_globals.debug_output,
                        "pmix: RECV CONNECT ACK FROM SERVER");

    /* get the current timeout value so we can reset to it */
    sz = sizeof(save);
    if (0 != getsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void*)&save, &sz)) {
        if (ENOPROTOOPT == errno) {
            sockopt = false;
        } else {
           return PMIX_ERR_UNREACH;
       }
   } else {
        /* set a timeout on the blocking recv so we don't hang */
        tv.tv_sec  = 2;
        tv.tv_usec = 0;
        if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) {
            pmix_output_verbose(2, pmix_globals.debug_output,
                                "pmix: recv_connect_ack could not setsockopt SO_RCVTIMEO");
            return PMIX_ERR_UNREACH;
        }
    }

    /* receive the status reply */
    rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t));
    if (PMIX_SUCCESS != rc) {
        PMIX_ERROR_LOG(rc);
        return rc;
    }
    reply = ntohl(u32);

    if (PMIX_PROC_IS_CLIENT) {
        /* see if they want us to do the handshake */
        if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) {
            PMIX_PSEC_CLIENT_HANDSHAKE(rc, pmix_client_globals.myserver, sd);
            if (PMIX_SUCCESS != rc) {
                return rc;
            }
        } else if (PMIX_SUCCESS != reply) {
            return reply;
        }
        pmix_output_verbose(2, pmix_globals.debug_output,
                            "pmix: RECV CONNECT CONFIRMATION");

        /* receive our index into the server's client array */
        rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t));
        if (PMIX_SUCCESS != rc) {
            PMIX_ERROR_LOG(rc);
            return rc;
        }
        pmix_globals.pindex = ntohl(u32);
    } else {  // we are a tool
        /* if the status indicates an error, then we are done */
        if (PMIX_SUCCESS != reply) {
            PMIX_ERROR_LOG(reply);
            return reply;
        }
        /* recv our nspace */
        rc = pmix_ptl_base_recv_blocking(sd, (char*)&pmix_globals.myid.nspace, PMIX_MAX_NSLEN+1);
        if (PMIX_SUCCESS != rc) {
            PMIX_ERROR_LOG(rc);
            return rc;
        }
        /* our rank is always zero */
        pmix_globals.myid.rank = 0;

        /* get the server's nspace and rank so we can send to it */
        pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t);
        pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t);
        pmix_ptl_base_recv_blocking(sd, (char*)nspace, PMIX_MAX_NSLEN+1);
        pmix_client_globals.myserver->nptr->nspace = strdup(nspace);
        pmix_client_globals.myserver->info->pname.nspace = strdup(nspace);
        pmix_ptl_base_recv_blocking(sd, (char*)&(pmix_client_globals.myserver->info->pname.rank), sizeof(int));

        pmix_output_verbose(2, pmix_globals.debug_output,
                            "pmix: RECV CONNECT CONFIRMATION FOR TOOL %s:%d FROM SERVER %s:%d",
                            pmix_globals.myid.nspace, pmix_globals.myid.rank,
                            pmix_client_globals.myserver->info->pname.nspace,
                            pmix_client_globals.myserver->info->pname.rank);

        /* get the returned status from the security handshake */
        pmix_ptl_base_recv_blocking(sd, (char*)&reply, sizeof(pmix_status_t));
        if (PMIX_SUCCESS != reply) {
            /* see if they want us to do the handshake */
            if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) {
                PMIX_PSEC_CLIENT_HANDSHAKE(reply, pmix_client_globals.myserver, sd);
                if (PMIX_SUCCESS != reply) {
                    return reply;
                }
                /* if the handshake succeeded, then fall thru to the next step */
            } else {
                return reply;
            }
        }
    }

    if (sockopt) {
        if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &save, sz)) {
            return PMIX_ERR_UNREACH;
        }
    }

    return PMIX_SUCCESS;
}
Beispiel #23
0
void *socks_connector_sel(void *p)
{
   fd_set rset, wset;
   int maxfd = 0, len, so_err;
   SocksQueue_t *squeue, sq;
   time_t t;
   struct timeval tv;
   socklen_t err_len;

   for (;;)
   {
      if (term_req())
         return NULL;

      FD_ZERO(&rset);
      FD_ZERO(&wset);
      MFD_SET(CNF(socksfd[0]), &rset, maxfd);
      t = time(NULL);

      for (squeue = socks_queue_; squeue; squeue = squeue->next)
      {
         switch (squeue->state)
         {
            case SOCKS_NEW:
               /*if (!squeue->fd)
               {
                  log_msg(LOG_CRIT, "SOCKS_NEW and fd = %d, but should be 0", squeue->fd);
                  squeue->state = SOCKS_DELETE;
                  continue;
               }*/

               if (t < squeue->restart_time)
               {
                  log_debug("SOCKS request is scheduled for connection not before %ds", squeue->restart_time - t);
                  continue;
               }

               // check and increase retry counter
               squeue->retry++;
               if (!squeue->perm && (squeue->retry > SOCKS_MAX_RETRY))
               {
                  log_msg(LOG_NOTICE, "temporary request failed %d times and will be removed", squeue->retry - 1);
                  squeue->state = SOCKS_DELETE;
                  continue;
               }

               log_debug("creating socket for unconnected SOCKS request");
               if ((squeue->fd = socket(CNF(socks_dst)->sin_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0)) == -1)
               {
                  log_msg(LOG_ERR, "cannot create socket for new SOCKS request: \"%s\"", strerror(errno));
                  continue;
               }

               set_nonblock(squeue->fd);
               log_debug("queueing fd %d for connect", squeue->fd);
               squeue->connect_time = t;
               if (socks_tcp_connect(squeue->fd, (struct sockaddr*) CNF(socks_dst), SOCKADDR_SIZE(CNF(socks_dst))) == -1)
               {
                  socks_reschedule(squeue);
                  continue;
               }

               squeue->state = SOCKS_CONNECTING;
               MFD_SET(squeue->fd, &wset, maxfd);

               break;

            case SOCKS_4AREQ_SENT:
               MFD_SET(squeue->fd, &rset, maxfd);
               break;
         }
      }

      // select all file descriptors
      set_select_timeout(&tv);
      log_debug("selecting (maxfd = %d)", maxfd);
      if ((maxfd = select(maxfd + 1, &rset, &wset, NULL, &tv)) == -1)
      {
         log_msg(LOG_EMERG, "select encountered error: \"%s\", restarting", strerror(errno));
         continue;
      }
      log_debug("select returned %d", maxfd);

      // check socks request pipe
      if (FD_ISSET(CNF(socksfd[0]), &rset))
      {
         maxfd--;
         if ((len = read(CNF(socksfd[0]), &sq, sizeof(sq))) == -1)
            log_msg(LOG_ERR, "failed to read from SOCKS request pipe, fd = %d: \"%s\"", 
                  CNF(socksfd[0]), strerror(errno));
         if (len < sizeof(sq))
            log_msg(LOG_ERR, "read from SOCKS request pipe truncated to %d of %d bytes, ignoring.", 
                  len, sizeof(sq));
         else
         {
            log_debug("received %d bytes on SOCKS request pipe fd %d", len, CNF(socksfd[0]));
            if (sq.next)
            {
               log_debug("output of SOCKS request queue triggered");
               socks_output_queue((FILE*) sq.next);
            }
            else if (IN6_IS_ADDR_UNSPECIFIED(&sq.addr))
            {
               log_debug("termination request on SOCKS request queue received");
            }
            else
            {
               log_debug("SOCKS queuing request received");
               socks_enqueue(&sq);
            }
         }
      }

      // handle all other file descriptors
      t = time(NULL);
      for (squeue = socks_queue_; maxfd && squeue; squeue = squeue->next)
      {
         // check write set, this is valid after connect()
         if (FD_ISSET(squeue->fd, &wset))
         {
            maxfd--;
            if (squeue->state == SOCKS_CONNECTING)
            {
               // test if connect() worked
               log_debug("check socket error");
               err_len = sizeof(so_err);
               if (getsockopt(squeue->fd, SOL_SOCKET, SO_ERROR, &so_err, &err_len) == -1)
               {
                  log_msg(LOG_ERR, "getsockopt failed: \"%s\", rescheduling request", strerror(errno));
                  socks_reschedule(squeue);
                  continue;
               }
               if (so_err)
               {
                  log_msg(LOG_ERR, "getsockopt returned %d (\"%s\")", so_err, strerror(so_err));
                  socks_reschedule(squeue);
                  continue;
               }
               // everything seems to be ok, now check request status
               if (socks_send_request(squeue) == -1)
               {
                  log_msg(LOG_ERR, "SOCKS request failed");
                  socks_reschedule(squeue);
                  continue;
               }
               // request successfully sent, advance state machine
               squeue->state = SOCKS_4AREQ_SENT;
            }
            else
               log_debug("unknown state %d in write set", squeue->state);
         }

         // check read set, this is valid after write, i.e. receiving SOCKS response
         if (FD_ISSET(squeue->fd, &rset))
         {
            maxfd--;
            if (squeue->state == SOCKS_4AREQ_SENT)
            {
               if (socks_rec_response(squeue) == -1)
               {
                  socks_reschedule(squeue);
                  continue;
               }
               // success
               log_debug("activating peer fd %d", squeue->fd);
               socks_activate_peer(squeue);
               squeue->state = SOCKS_DELETE;
            }
            else
               log_debug("unknown state %d in read set", squeue->state);
         }
      }

      // delete requests from queue which are marked for deletion
      for (squeue = socks_queue_; squeue; squeue = squeue->next)
         if (squeue->state == SOCKS_DELETE)
         {
            socks_unqueue(squeue);
            // restart loop
            squeue = socks_queue_;
            if (!squeue)
            {
               log_debug("last entry deleted, breaking loop");
               break;
            }
         }
   }
}
Beispiel #24
0
int WdtSocket::getSendBufferSize() const {
  int size;
  socklen_t sizeSize = sizeof(size);
  getsockopt(fd_, SOL_SOCKET, SO_SNDBUF, (void *)&size, &sizeSize);
  return size;
}
Beispiel #25
0
static int sendtoxymond(char *recipient, char *message, FILE *respfd, char **respstr, int fullresponse, int timeout)
{
	struct in_addr addr;
	struct sockaddr_in saddr;
	int	sockfd;
	fd_set	readfds;
	fd_set	writefds;
	int	res, isconnected, wdone, rdone;
	struct timeval tmo;
	char *msgptr = message;
	char *p;
	char *rcptip = NULL;
	int rcptport = 0;
	int connretries = SENDRETRIES;
	char *httpmessage = NULL;
	char recvbuf[32768];
	int haveseenhttphdrs = 1;
	int respstrsz = 0;
	int respstrlen = 0;
	int result = XYMONSEND_OK;

	if (dontsendmessages && !respfd && !respstr) {
		printf("%s\n", message);
		return XYMONSEND_OK;
	}

	setup_transport(recipient);

	dbgprintf("Recipient listed as '%s'\n", recipient);

	if (strncmp(recipient, "http://", strlen("http://")) != 0) {
		/* Standard communications, directly to Xymon daemon */
		rcptip = strdup(recipient);
		rcptport = xymondportnumber;
		p = strchr(rcptip, ':');
		if (p) {
			*p = '\0'; p++; rcptport = atoi(p);
		}
		dbgprintf("Standard protocol on port %d\n", rcptport);
	}
	else {
		char *bufp;
		char *posturl = NULL;
		char *posthost = NULL;

		if (xymonproxyhost == NULL) {
			char *p;

			/*
			 * No proxy. "recipient" is "http://host[:port]/url/for/post"
			 * Strip off "http://", and point "posturl" to the part after the hostname.
			 * If a portnumber is present, strip it off and update rcptport.
			 */
			rcptip = strdup(recipient+strlen("http://"));
			rcptport = xymondportnumber;

			p = strchr(rcptip, '/');
			if (p) {
				posturl = strdup(p);
				*p = '\0';
			}

			p = strchr(rcptip, ':');
			if (p) {
				*p = '\0';
				p++;
				rcptport = atoi(p);
			}

			posthost = strdup(rcptip);

			dbgprintf("HTTP protocol directly to host %s\n", posthost);
		}
		else {
			char *p;

			/*
			 * With proxy. The full "recipient" must be in the POST request.
			 */
			rcptip = strdup(xymonproxyhost);
			rcptport = xymonproxyport;

			posturl = strdup(recipient);

			p = strchr(recipient + strlen("http://"), '/');
			if (p) {
				*p = '\0';
				posthost = strdup(recipient + strlen("http://"));
				*p = '/';

				p = strchr(posthost, ':');
				if (p) *p = '\0';
			}

			dbgprintf("HTTP protocol via proxy to host %s\n", posthost);
		}

		if ((posturl == NULL) || (posthost == NULL)) {
			sprintf(errordetails + strlen(errordetails), "Unable to parse HTTP recipient");
			if (posturl) xfree(posturl);
			if (posthost) xfree(posthost);
			if (rcptip) xfree(rcptip);
			return XYMONSEND_EBADURL;
		}

		bufp = msgptr = httpmessage = malloc(strlen(message)+1024);
		bufp += sprintf(httpmessage, "POST %s HTTP/1.0\n", posturl);
		bufp += sprintf(bufp, "MIME-version: 1.0\n");
		bufp += sprintf(bufp, "Content-Type: application/octet-stream\n");
		bufp += sprintf(bufp, "Content-Length: %d\n", strlen(message));
		bufp += sprintf(bufp, "Host: %s\n", posthost);
		bufp += sprintf(bufp, "\n%s", message);

		if (posturl) xfree(posturl);
		if (posthost) xfree(posthost);
		haveseenhttphdrs = 0;

		dbgprintf("HTTP message is:\n%s\n", httpmessage);
	}

	if (inet_aton(rcptip, &addr) == 0) {
		/* recipient is not an IP - do DNS lookup */

		struct hostent *hent;
		char hostip[IP_ADDR_STRLEN];

		hent = gethostbyname(rcptip);
		if (hent) {
			memcpy(&addr, *(hent->h_addr_list), sizeof(struct in_addr));
			strcpy(hostip, inet_ntoa(addr));

			if (inet_aton(hostip, &addr) == 0) {
				result = XYMONSEND_EBADIP;
				goto done;
			}
		}
		else {
			sprintf(errordetails+strlen(errordetails), "Cannot determine IP address of message recipient %s", rcptip);
			result = XYMONSEND_EIPUNKNOWN;
			goto done;
		}
	}

retry_connect:
	dbgprintf("Will connect to address %s port %d\n", rcptip, rcptport);

	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = addr.s_addr;
	saddr.sin_port = htons(rcptport);

	/* Get a non-blocking socket */
	sockfd = socket(PF_INET, SOCK_STREAM, 0);
	if (sockfd == -1) { result = XYMONSEND_ENOSOCKET; goto done; }
	res = fcntl(sockfd, F_SETFL, O_NONBLOCK);
	if (res != 0) { result = XYMONSEND_ECANNOTDONONBLOCK; goto done; }

	res = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
	if ((res == -1) && (errno != EINPROGRESS)) {
		sprintf(errordetails+strlen(errordetails), "connect to Xymon daemon@%s:%d failed (%s)", rcptip, rcptport, strerror(errno));
		result = XYMONSEND_ECONNFAILED;
		goto done;
	}

	rdone = ((respfd == NULL) && (respstr == NULL));
	isconnected = wdone = 0;
	while (!wdone || !rdone) {
		FD_ZERO(&writefds);
		FD_ZERO(&readfds);
		if (!rdone) FD_SET(sockfd, &readfds);
		if (!wdone) FD_SET(sockfd, &writefds);
		tmo.tv_sec = timeout;  tmo.tv_usec = 0;
		res = select(sockfd+1, &readfds, &writefds, NULL, (timeout ? &tmo : NULL));
		if (res == -1) {
			sprintf(errordetails+strlen(errordetails), "Select failure while sending to Xymon daemon@%s:%d", rcptip, rcptport);
			result = XYMONSEND_ESELFAILED;
			goto done;
		}
		else if (res == 0) {
			/* Timeout! */
			shutdown(sockfd, SHUT_RDWR);
			close(sockfd);

			if (!isconnected && (connretries > 0)) {
				dbgprintf("Timeout while talking to Xymon daemon@%s:%d - retrying\n", rcptip, rcptport);
				connretries--;
				sleep(1);
				goto retry_connect;	/* Yuck! */
			}

			result = XYMONSEND_ETIMEOUT;
			goto done;
		}
		else {
			if (!isconnected) {
				/* Havent seen our connect() status yet - must be now */
				int connres;
				socklen_t connressize = sizeof(connres);

				res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &connres, &connressize);
				dbgprintf("Connect status is %d\n", connres);
				isconnected = (connres == 0);
				if (!isconnected) {
					sprintf(errordetails+strlen(errordetails), "Could not connect to Xymon daemon@%s:%d (%s)", 
						  rcptip, rcptport, strerror(connres));
					result = XYMONSEND_ECONNFAILED;
					goto done;
				}
			}

			if (!rdone && FD_ISSET(sockfd, &readfds)) {
				char *outp;
				int n;

				n = recv(sockfd, recvbuf, sizeof(recvbuf)-1, 0);
				if (n > 0) {
					dbgprintf("Read %d bytes\n", n);
					recvbuf[n] = '\0';

					/*
					 * When running over a HTTP transport, we must strip
					 * off the HTTP headers we get back, so the response
					 * is consistent with what we get from the normal Xymon daemon
					 * transport.
					 * (Non-http transport sets "haveseenhttphdrs" to 1)
					 */
					if (!haveseenhttphdrs) {
						outp = strstr(recvbuf, "\r\n\r\n");
						if (outp) {
							outp += 4;
							n -= (outp - recvbuf);
							haveseenhttphdrs = 1;
						}
						else n = 0;
					}
					else outp = recvbuf;

					if (n > 0) {
						if (respfd) {
							fwrite(outp, n, 1, respfd);
						}
						else if (respstr) {
							char *respend;

							if (respstrsz == 0) {
								respstrsz = (n+sizeof(recvbuf));
								*respstr = (char *)malloc(respstrsz);
							}
							else if ((n+respstrlen) >= respstrsz) {
								respstrsz += (n+sizeof(recvbuf));
								*respstr = (char *)realloc(*respstr, respstrsz);
							}
							respend = (*respstr) + respstrlen;
							memcpy(respend, outp, n);
							*(respend + n) = '\0';
							respstrlen += n;
						}
						if (!fullresponse) {
							rdone = (strchr(outp, '\n') == NULL);
						}
					}
				}
				else rdone = 1;
				if (rdone) shutdown(sockfd, SHUT_RD);
			}

			if (!wdone && FD_ISSET(sockfd, &writefds)) {
				/* Send some data */
				res = write(sockfd, msgptr, strlen(msgptr));
				if (res == -1) {
					sprintf(errordetails+strlen(errordetails), "Write error while sending message to Xymon daemon@%s:%d", rcptip, rcptport);
					result = XYMONSEND_EWRITEERROR;
					goto done;
				}
				else {
					dbgprintf("Sent %d bytes\n", res);
					msgptr += res;
					wdone = (strlen(msgptr) == 0);
					if (wdone) shutdown(sockfd, SHUT_WR);
				}
			}
		}
	}

done:
	dbgprintf("Closing connection\n");
	shutdown(sockfd, SHUT_RDWR);
	close(sockfd);
	xfree(rcptip);
	if (httpmessage) xfree(httpmessage);
	return result;
}
Beispiel #26
0
/*
 *  stress_socket_server()
 *	server writer
 */
static int stress_socket_server(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name,
	const pid_t pid,
	const pid_t ppid)
{
	char buf[SOCKET_BUF];
	int fd, status;
	int so_reuseaddr = 1;
	struct sigaction new_action;
	socklen_t addr_len = 0;
	struct sockaddr *addr;
	uint64_t msgs = 0;
	int rc = EXIT_SUCCESS;

	setpgid(pid, pgrp);

	new_action.sa_handler = handle_socket_sigalrm;
	sigemptyset(&new_action.sa_mask);
	new_action.sa_flags = 0;
	if (sigaction(SIGALRM, &new_action, NULL) < 0) {
		pr_fail_err(name, "sigaction");
		rc = EXIT_FAILURE;
		goto die;
	}
	if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) {
		pr_fail_dbg(name, "socket");
		rc = EXIT_FAILURE;
		goto die;
	}
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
		&so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
		pr_fail_dbg(name, "setsockopt");
		rc = EXIT_FAILURE;
		goto die_close;
	}

	stress_set_sockaddr(name, instance, ppid,
		opt_socket_domain, opt_socket_port, &addr, &addr_len);
	if (bind(fd, addr, addr_len) < 0) {
		pr_fail_dbg(name, "bind");
		rc = EXIT_FAILURE;
		goto die_close;
	}
	if (listen(fd, 10) < 0) {
		pr_fail_dbg(name, "listen");
		rc = EXIT_FAILURE;
		goto die_close;
	}

	do {
		int sfd = accept(fd, (struct sockaddr *)NULL, NULL);
		if (sfd >= 0) {
			size_t i, j;
			struct sockaddr addr;
			socklen_t len;
			int sndbuf;
			struct msghdr msg;
			struct iovec vec[sizeof(buf)/16];
#if defined(HAVE_SENDMMSG)
			struct mmsghdr msgvec[MSGVEC_SIZE];
			unsigned int msg_len = 0;
#endif
#if defined(SOCKET_NODELAY)
			int one = 1;
#endif

			len = sizeof(addr);
			if (getsockname(fd, &addr, &len) < 0) {
				pr_fail_dbg(name, "getsockname");
				(void)close(sfd);
				break;
			}
			len = sizeof(sndbuf);
			if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) {
				pr_fail_dbg(name, "getsockopt");
				(void)close(sfd);
				break;
			}
#if defined(SOCKET_NODELAY)
			if (opt_flags & OPT_FLAGS_SOCKET_NODELAY) {
				if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
					pr_inf(stderr, "%s: setsockopt TCP_NODELAY "
						"failed and disabled, errno=%d (%s)\n",
						name, errno, strerror(errno));
					opt_flags &= ~OPT_FLAGS_SOCKET_NODELAY;
				}
			}
#endif
			memset(buf, 'A' + (*counter % 26), sizeof(buf));
			switch (opt_socket_opts) {
			case SOCKET_OPT_SEND:
				for (i = 16; i < sizeof(buf); i += 16) {
					ssize_t ret = send(sfd, buf, i, 0);
					if (ret < 0) {
						if (errno != EINTR)
							pr_fail_dbg(name, "send");
						break;
					} else
						msgs++;
				}
				break;
			case SOCKET_OPT_SENDMSG:
				for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) {
					vec[j].iov_base = buf;
					vec[j].iov_len = i;
				}
				memset(&msg, 0, sizeof(msg));
				msg.msg_iov = vec;
				msg.msg_iovlen = j;
				if (sendmsg(sfd, &msg, 0) < 0) {
					if (errno != EINTR)
						pr_fail_dbg(name, "sendmsg");
				} else
					msgs += j;
				break;
#if defined(HAVE_SENDMMSG)
			case SOCKET_OPT_SENDMMSG:
				memset(msgvec, 0, sizeof(msgvec));
				for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) {
					vec[j].iov_base = buf;
					vec[j].iov_len = i;
					msg_len += i;
				}
				for (i = 0; i < MSGVEC_SIZE; i++) {
					msgvec[i].msg_hdr.msg_iov = vec;
					msgvec[i].msg_hdr.msg_iovlen = j;
				}
				if (sendmmsg(sfd, msgvec, MSGVEC_SIZE, 0) < 0) {
					if (errno != EINTR)
						pr_fail_dbg(name, "sendmmsg");
				} else
					msgs += (MSGVEC_SIZE * j);
				break;
#endif
			default:
				/* Should never happen */
				pr_err(stderr, "%s: bad option %d\n", name, opt_socket_opts);
				(void)close(sfd);
				goto die_close;
			}
			if (getpeername(sfd, &addr, &len) < 0) {
				pr_fail_dbg(name, "getpeername");
			}
			(void)close(sfd);
		}
		(*counter)++;
	} while (opt_do_run && (!max_ops || *counter < max_ops));

die_close:
	(void)close(fd);
die:
#ifdef AF_UNIX
	if (opt_socket_domain == AF_UNIX) {
		struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
		(void)unlink(addr_un->sun_path);
	}
#endif
	if (pid) {
		(void)kill(pid, SIGKILL);
		(void)waitpid(pid, &status, 0);
	}
	pr_dbg(stderr, "%s: %" PRIu64 " messages sent\n", name, msgs);

	return rc;
}
Beispiel #27
0
static int
CreateClientSocket(
    Tcl_Interp *interp,		/* For error reporting; can be NULL. */
    TcpState *state)
{
    socklen_t optlen;
    int async_callback = (state->addr != NULL);
    int status;
    int async = state->flags & TCP_ASYNC_CONNECT;

    if (async_callback) {
        goto reenter;
    }

    for (state->addr = state->addrlist; state->addr != NULL;
            state->addr = state->addr->ai_next) {
	status = -1;

        for (state->myaddr = state->myaddrlist; state->myaddr != NULL;
                state->myaddr = state->myaddr->ai_next) {
            int reuseaddr;
            
	    /*
	     * No need to try combinations of local and remote addresses of
	     * different families.
	     */

	    if (state->myaddr->ai_family != state->addr->ai_family) {
		continue;
	    }

            /*
             * Close the socket if it is still open from the last unsuccessful
             * iteration.
             */

            if (state->fds.fd >= 0) {
		close(state->fds.fd);
		state->fds.fd = -1;
	    }

	    state->fds.fd = socket(state->addr->ai_family, SOCK_STREAM, 0);
	    if (state->fds.fd < 0) {
		continue;
	    }

	    /*
	     * Set the close-on-exec flag so that the socket will not get
	     * inherited by child processes.
	     */
	    
	    fcntl(state->fds.fd, F_SETFD, FD_CLOEXEC);
	    
	    /*
	     * Set kernel space buffering
	     */
	    
	    TclSockMinimumBuffers(INT2PTR(state->fds.fd), SOCKET_BUFSIZE);
    
	    if (async) {
		status = TclUnixSetBlockingMode(state->fds.fd,
                        TCL_MODE_NONBLOCKING);
		if (status < 0) {
                    continue;
		}
	    }

            reuseaddr = 1;
            (void) setsockopt(state->fds.fd, SOL_SOCKET, SO_REUSEADDR,
                    (char *) &reuseaddr, sizeof(reuseaddr));
            status = bind(state->fds.fd, state->myaddr->ai_addr,
                    state->myaddr->ai_addrlen);
            if (status < 0) {
                continue;
            }

	    /*
	     * Attempt to connect. The connect may fail at present with an
	     * EINPROGRESS but at a later time it will complete. The caller
	     * will set up a file handler on the socket if she is interested
	     * in being informed when the connect completes.
	     */
	    
	    status = connect(state->fds.fd, state->addr->ai_addr,
                    state->addr->ai_addrlen);
	    if (status < 0 && errno == EINPROGRESS) {
                Tcl_CreateFileHandler(state->fds.fd,
                        TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, state);
                return TCL_OK;

            reenter:
                Tcl_DeleteFileHandler(state->fds.fd);

                /*
                 * Read the error state from the socket to see if the async
                 * connection has succeeded or failed. As this clears the
                 * error condition, we cache the status in the socket state
                 * struct for later retrieval by [fconfigure -error].
                 */

                optlen = sizeof(int);
                getsockopt(state->fds.fd, SOL_SOCKET, SO_ERROR,
                        (char *) &status, &optlen);
                state->status = status;
            }
	    if (status == 0) {
		CLEAR_BITS(state->flags, TCP_ASYNC_CONNECT);
		goto out;
	    }
	}
    }

out:

    if (async_callback) {
        /*
         * An asynchonous connection has finally succeeded or failed.
         */

        TcpWatchProc(state, state->filehandlers);
        TclUnixSetBlockingMode(state->fds.fd, state->cachedBlocking);

        /*
         * We need to forward the writable event that brought us here, bcasue
         * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
         * writable state from the socket, and so a subsequent select() on
         * behalf of a script level [fileevent] would not fire. It doesn't
         * hurt that this is also called in the successful case and will save
         * the event mechanism one roundtrip through select().
         */

        Tcl_NotifyChannel(state->channel, TCL_WRITABLE);
    } else if (status != 0) {
        /*
         * Failure for either a synchronous connection, or an async one that
         * failed before it could enter background mode, e.g. because an
         * invalid -myaddr was given.
         */

        if (interp != NULL) {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "couldn't open socket: %s", Tcl_PosixError(interp)));
        }
        return TCL_ERROR;
    }
    return TCL_OK;
}
Beispiel #28
0
static int
TcpGetOptionProc(
    ClientData instanceData,	/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to retrieve the value
				 * for, or NULL to get all options and their
				 * values. */
    Tcl_DString *dsPtr)		/* Where to store the computed value;
				 * initialized by caller. */
{
    TcpState *statePtr = instanceData;
    size_t len = 0;

    if (optionName != NULL) {
	len = strlen(optionName);
    }

    if ((len > 1) && (optionName[1] == 'e') &&
	    (strncmp(optionName, "-error", len) == 0)) {
	socklen_t optlen = sizeof(int);
	int err, ret;

        if (statePtr->status == 0) {
            ret = getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
                    (char *) &err, &optlen);
            if (ret < 0) {
                err = errno;
            }
        } else {
            err = statePtr->status;
            statePtr->status = 0;
        }
	if (err != 0) {
	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(err), -1);
	}
	return TCL_OK;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);

	if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }
            TcpHostPortList(interp, dsPtr, peername, size);
	    if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
	} else {
	    /*
	     * getpeername failed - but if we were asked for all the options
	     * (len==0), don't flag an error at that point because it could be
	     * an fconfigure request on a server socket (which have no peer).
	     * Same must be done on win&mac.
	     */

	    if (len) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
	    (strncmp(optionName, "-sockname", len) == 0))) {
	TcpFdList *fds;
        address sockname;
        socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
	    size = sizeof(sockname);
	    if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
		found = 1;
                TcpHostPortList(interp, dsPtr, sockname, size);
	    }
	}
        if (found) {
            if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
        } else {
            if (interp) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "can't get sockname: %s", Tcl_PosixError(interp)));
            }
	    return TCL_ERROR;
	}
    }

    if (len > 0) {
	return Tcl_BadChannelOption(interp, optionName, "peername sockname");
    }

    return TCL_OK;
}
Beispiel #29
0
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout) {

    int arg, ret;
    int soopt;
    socklen_t solen = sizeof(int);
    int cnt;
    /* set non-blocking socket */

    arg = fcntl(fdpoll->fd, F_GETFL, NULL);
    if (arg < 0) {
        uwsgi_error("fcntl()");
        return -1;
    }
    arg |= O_NONBLOCK;
    if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
        uwsgi_error("fcntl()");
        return -1;
    }

    ret = connect(fdpoll->fd, addr, addr_size);
    if (ret < 0) {
        /* check what happened */

        // in progress ?
        if (errno == EINPROGRESS) {
            if (timeout < 1)
                timeout = 3;
            fdpoll->events = POLLOUT;
            cnt = poll(fdpoll, 1, timeout * 1000);
            /* check for errors */
            if (cnt < 0 && errno != EINTR) {
                uwsgi_error("poll()");
                return -1;
            }
            /* something hapened on the socket ... */
            else if (cnt > 0) {
                if (getsockopt(fdpoll->fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
                    uwsgi_error("getsockopt()");
                    return -1;
                }
                /* is something bad ? */
                if (soopt) {
                    return -1;
                }
            }
            /* timeout */
            else {
                return -1;
            }
        }
        else {
            return -1;
        }
    }

    /* re-set blocking socket */
    arg &= (~O_NONBLOCK);
    if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
        uwsgi_error("fcntl()");
        return -1;
    }

    return 0;

}
Beispiel #30
-22
static void dgram_adjust_rcv_timeout(BIO *b)
	{
#if defined(SO_RCVTIMEO)
	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
	int sz = sizeof(int);

	/* Is a timer active? */
	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
		{
		struct timeval timenow, timeleft;

		/* Read current socket timeout */
#ifdef OPENSSL_SYS_WINDOWS
		int timeout;
		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
					   (void*)&timeout, &sz) < 0)
			{ perror("getsockopt"); }
		else
			{
			data->socket_timeout.tv_sec = timeout / 1000;
			data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
			}
#else
		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
						&(data->socket_timeout), (void *)&sz) < 0)
			{ perror("getsockopt"); }
#endif

		/* Get current time */
		get_current_time(&timenow);

		/* Calculate time left until timer expires */
		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
		timeleft.tv_sec -= timenow.tv_sec;
		timeleft.tv_usec -= timenow.tv_usec;
		if (timeleft.tv_usec < 0)
			{
			timeleft.tv_sec--;
			timeleft.tv_usec += 1000000;
			}

		if (timeleft.tv_sec < 0)
			{
			timeleft.tv_sec = 0;
			timeleft.tv_usec = 1;
			}

		/* Adjust socket timeout if next handhake message timer
		 * will expire earlier.
		 */
		if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
			(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
			(data->socket_timeout.tv_sec == timeleft.tv_sec &&
			 data->socket_timeout.tv_usec >= timeleft.tv_usec))
			{
#ifdef OPENSSL_SYS_WINDOWS
			timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
						   (void*)&timeout, sizeof(timeout)) < 0)
				{ perror("setsockopt"); }
#else
			if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
							sizeof(struct timeval)) < 0)
				{ perror("setsockopt"); }
#endif
			}
		}
#endif
	}