Пример #1
0
/*
 * Receive packet with synchronous timeout
 */
static int recv_time (int s, void *rbuf, int len, unsigned int flags, unsigned long timeout_ms)
{
    fd_set fdset;

    struct timeval tmv;

    int rv, err;

    for (;;)
    {
        FD_ZERO (&fdset);
        FD_SET (s, &fdset);

        tmv.tv_sec = timeout_ms / 1000;
        tmv.tv_usec = (timeout_ms % 1000) * 1000;

        do
        {
            rv = select (s + 1, &fdset, NULL, NULL, &tmv);
        }
        while (rv == -1 && errno == EINTR);

        if (rv == 0)
        {
            timer (0);            /* Should not return */
            return -1;
        }

        set_socket_nonblock (s, 1);
        rv = recv (s, rbuf, len, flags);
        err = errno;
        set_socket_nonblock (s, 0);
        if (rv < 0)
        {
            if (E_WOULD_BLOCK (err) || err == EINTR)
            {
                continue;        /* Once again, with feeling... */
            }
            else
            {
                errno = err;
                return rv;
            }
        }
        else
        {
            return rv;
        }
    }
}
Пример #2
0
static sock_t new_listening_TCP_socket(int family, uint16_t port)
{
    sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);

    if (!sock_valid(sock)) {
        return ~0;
    }

#ifndef TCP_SERVER_USE_EPOLL
    int ok = set_socket_nonblock(sock);
#else
    int ok = 1;
#endif

    if (ok && family == AF_INET6) {
        ok = set_socket_dualstack(sock);
    }

    ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);

    if (!ok) {
        kill_sock(sock);
        return ~0;
    }

    return sock;
}
Пример #3
0
/* return 1 on success
 * return 0 on failure
 */
static int accept_connection(TCP_Server *TCP_server, sock_t sock)
{
    if (!sock_valid(sock))
        return 0;

    if (!set_socket_nonblock(sock)) {
        kill_sock(sock);
        return 0;
    }

    if (!set_socket_nosigpipe(sock)) {
        kill_sock(sock);
        return 0;
    }

    TCP_Secure_Connection *conn =
        &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS];

    if (conn->status != TCP_STATUS_NO_STATUS)
        kill_TCP_connection(conn);

    conn->status = TCP_STATUS_CONNECTED;
    conn->sock = sock;
    conn->next_packet_length = 0;

    ++TCP_server->incomming_connection_queue_index;
    return 1;
}
Пример #4
0
static sock_t new_listening_TCP_socket(int family, uint16_t port)
{
    sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);

    if (!sock_valid(sock)) {
        return ~0;
    }

    int ok = set_socket_nonblock(sock);

    if (ok && family == AF_INET6) {
        ok = set_socket_dualstack(sock);
    }

    if (ok) {
        ok = set_socket_reuseaddr(sock);
    }

    ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);

    if (!ok) {
        kill_sock(sock);
        return ~0;
    }

    return sock;
}
Пример #5
0
/* return index on success
 * return -1 on failure
 */
static int accept_connection(TCP_Server *TCP_server, Socket sock)
{
    if (!sock_valid(sock)) {
        return -1;
    }

    if (!set_socket_nonblock(sock)) {
        kill_sock(sock);
        return -1;
    }

    if (!set_socket_nosigpipe(sock)) {
        kill_sock(sock);
        return -1;
    }

    uint16_t index = TCP_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS;

    TCP_Secure_Connection *conn = &TCP_server->incoming_connection_queue[index];

    if (conn->status != TCP_STATUS_NO_STATUS) {
        kill_TCP_secure_connection(conn);
    }

    conn->status = TCP_STATUS_CONNECTED;
    conn->sock = sock;
    conn->next_packet_length = 0;

    ++TCP_server->incoming_connection_queue_index;
    return index;
}
Пример #6
0
async_sock::async_sock():
  pfi::network::mprpc::socket(::socket(AF_INET, SOCK_STREAM, 0)),
  state_(CLOSED),
  progress_(0)
{
  // FIXME: SOCK_NONBLOCK is linux only
  if (!set_socket_nonblock(this->get(), true))
    throw JUBATUS_EXCEPTION(rpc_internal_error()
        << jubatus::exception::error_api_func("fcntl")
        << jubatus::exception::error_errno(errno));

  unpacker_.reserve_buffer(4096);
}
Пример #7
0
static int tcp_connect(TNetWorkMsg *_ptNetWorkMsg, const char *_pcIP, int _iPort)
{
	if(NULL == _ptNetWorkMsg || NULL == _pcIP)
	{
		dbg();
		return ERR;
	}

	int iRet = ERR;
	unsigned int ul;
	dbgprintf(0, "start tcp connect to %s:%d", _ptNetWorkMsg->m_pcIp, _ptNetWorkMsg->m_iPort);
	
	fd_set rdevents,wrevents,exevents;
	struct   timeval tv;
	socklen_t sLen;
	struct sockaddr_in ptDestAddr;
	
	if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket)
	{
		struct linger so_linger;
    	_ptNetWorkMsg->m_iSocket = socket(AF_INET, SOCK_STREAM, 0);
		
    	if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket)
    	{
    		dbg();
			iRet = ERR;
			goto EXIT;
    	}

      	so_linger.l_onoff = 1;
       	so_linger.l_linger = 0;
       	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
       	
    	int cnt = SO_RCVBUF_LEN;
    	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_RCVBUF, (int *)&cnt,sizeof(int));
    	cnt = SO_SNDBUF_LEN;
    	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_SNDBUF, (int *)&cnt, sizeof(int));
	}

	#if 0
	// 绑定指定网卡或IP
	strut sockaddr_in sin;
	
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = xxx;
	sin.sin_port = xxx;
	
	bind(sock, (struct sockaddr *)&sin, sizeof(sin));
	// 绑定结束
	#endif

	//设置为非阻塞模式
	ul = 1;
    ioctl(_ptNetWorkMsg->m_iSocket, FIONBIO, &ul);   

	// 指定地址和端口
	memset(&ptDestAddr, 0, sizeof(struct sockaddr_in));
	
	ptDestAddr.sin_family 	 	= AF_INET;
	ptDestAddr.sin_port   	 	= htons(_iPort);
	ptDestAddr.sin_addr.s_addr 	= inet_addr(_pcIP);

    // 与服务器端建立连接
    iRet = connect(_ptNetWorkMsg->m_iSocket,(struct sockaddr*)&ptDestAddr, sizeof(ptDestAddr));

	dbgint(iRet);
	dbgint(errno);
	
    if(-1 == iRet && errno != EINPROGRESS)
	{
		dbg();
 		iRet = ERR;
		goto EXIT;
	}
	
	//若没有直接连接成功则需要等待
	if(0 != iRet)
	{  
		//把先前的套接字加到读集合里面	
		FD_ZERO(&rdevents);
		FD_SET(_ptNetWorkMsg->m_iSocket, &rdevents);  
		wrevents = rdevents;  
		
		//异常集合
		exevents = rdevents;   

		#if 1
		//设置时间为5秒
		tv.tv_sec = 5;  
		tv.tv_usec = 0;
		#else
		//设置时间为10秒
		tv.tv_sec = 10;  
		tv.tv_usec = 0;
		#endif

		iRet = select(_ptNetWorkMsg->m_iSocket + 1, &rdevents, &wrevents, &exevents, &tv);

		dbgint(iRet);

		if(iRet <= 0) 
		{  
			dbg();
			dbgint(errno);
	    	//错误处理
        	iRet = ERR;
			goto EXIT;
		}
		#if 0		
		else if(0 == iRet) 
		{  
	    	//超时处理
	   		close(_pConnection->m_iSocKet);		
	   		_pConnection->m_iSocKet = INVALID_SOCKET;
			
        	iRet = ERR;
			goto leave;
		}
		#endif		
		else 
		{
			if(2 == iRet) 
			{  
				int iErr;
				int iLen = sizeof(iErr); 
				getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iErr, (socklen_t*)&iLen); 

				if(iErr) 
				{ 
					//dbg();
					dbgint(errno);
					//超时处理
					iRet = ERR;
					goto EXIT;
				} 
			}	
			
		    //套接字已经准备好
    		if(_ptNetWorkMsg->m_iSocket < 0)
    		{
    			dbg();
				dbgint(errno);
				iRet = ERR;
				goto EXIT;
    		}
			
    		if(!FD_ISSET(_ptNetWorkMsg->m_iSocket, &rdevents) && !FD_ISSET(_ptNetWorkMsg->m_iSocket, &wrevents)) 
			{
				dbg();
				dbgint(errno);
		      	iRet = ERR;
				goto EXIT;
	    	}
		
  	 		if (getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iRet, &sLen) < 0)
	   		{
				//perror("getsockopt ");
				dbg();
				dbgint(errno);
	   		}

			#if 0
	   		if (iRet != 0) 
	   		{
				dbg();
			}
			#endif
			
	   		if(2 == iRet)
	   		{
	   			dbg();
				dbgint(errno);
				iRet = ERR;
				goto EXIT;
	   		}

			//到这里说明connect()正确返回
			
		}
	}

	
	iRet = OK;
	
	set_socket_nonblock(_ptNetWorkMsg->m_iSocket);

	#if 0
	iRet = epoll_add_connection(_ptConnection, 1);

	if(iRet!=0)
	{
		iRet = ERR;
		goto EXIT;	  
	}
	#endif
	 
EXIT:	
	if(OK != iRet && INVALID_SOCKET != _ptNetWorkMsg->m_iSocket)
	{
		//dbg();
		close(_ptNetWorkMsg->m_iSocket);
		_ptNetWorkMsg->m_iSocket = INVALID_SOCKET;
	}
	
	return iRet;
}
Пример #8
0
int main(int argc,char* argv[])
{
	int status;
	char* config = CONFIG; 
	char* optstr = "vc:?";

    struct sockaddr_in cli_addr;
    socklen_t  len_sock;

    struct epoll_event* ep_events;
    struct epoll_event event;

	//must have 2 paraments
	if(argc == 1)
	{
		print_usage();
		return 0;
	}

    //get the command line paraments
	while( (opt = getopt(argc,argv,optstr) )!= -1)
	{
		switch (opt)
		{
		  case 'c':
			 config = optstr;		 break;
		  case 'v':
			 printf("0.1VERSION\n"); break;
		  case '?':
			 print_usage();
			 return 0;
		}
	}

	// print the debug file
	sev_debug("config file: %s \n");

	// read the config file,check if success
	char buff[BUFLEN];
    as_conf* config = (as_conf*)malloc(sizeof(as_conf));

    status = read_config(config,buff,config,BUFLEN);
	if(status != OK)
	{
		log_err("read config file error !");
		exit(-1);
	}

    int listen_fd;
    listen_fd = creat_sockfd(9000);

    status = set_socket_nonblock(listen_fd);
    if(status != OK)
    {
        log_err("set sock fd block err!");
        exit(-1);
    }

    //create epoll ctl fd
    //malloc set of events
	int epfd = as_epoll_create(EPOLLSIZE);
    ep_events = (struct epoll_event*)malloc(EPOLLSIZE*sizeof(struct epoll_event));

    //construct event and register event to the set
    event.data.fd = listen_fd;
    event.events = EPOLLIN | EPOLLET;
    as_epoll_add(epfd,listen_fd,&event);

    //initial the thread pool
    // the pool use singleton pattern, pool is defined in .h
    init_pool(10);


    //main loop
    while(1)
    {
        int n_eves;
        n_eves = as_epoll_wait(epfd,ep_events,MAXEVESZ,TIMEOUT);

        int i,cli_fd;
        for(i=0;i<n_eves;i++)
        {
            cli_fd = ep_events[i].data.fd;
            if(listen_fd == cli_fd)
            {
                //some new clients ask to accept
                //accept,make_non_block,add_event
                //len_sock
                int fd = accept(listen_fd,(struct sockaddr*)&cli_addr,&len_sock);
                if(fd < 0)
                {
                    //log_err
                    log_err("accept cli fd error ! \n");
                    break;
                }

                //set fd non block
                //check status if normal
                status = set_socket_nonblock(fd);

                //set event paraments
                event.data.fd = fd;
                event.events = EPOLLIN | EPOLLET;

                //add event-->epoll
                as_epoll_add(epfd,fd,&event);

            }
            else
            {
                //accepted client's data ready to do_resquest
                //or need to close
                //how to detect the fd is a close signal
                if( (ep_events[i].events & EPOLLERR)|| (ep_events[i].events & EPOLLHUP)
                    || !(ep_events[i].events & EPOLLIN) )
                {
                    //log_info..need to close this client fd
                    close(fd);
                    continue;
                }
                //log_info  need to do the resquest
                printf("new task client:%d \n",fd);
                status = pool_addtask(do_resquest,&cli_fd);
                printf("task from client:%d  status:%d",fd,status);

            }
        }
        // need to fill timeout func.
        //printf("if timer end,the server will stop !\n");
        if(!as_timer())
        {
            log_info("long time no resquest,this server is about to out of service!");
            break;
        }

    }

    destroy_pool(pool);
    return 0;
}
Пример #9
0
/**
 * Same as eConnect() except you may the specify address family here (default is
 * AF_UNSPEC).
 * We couldn't just add the new family arg to eConnect because the original one
 * is pure virtual declared in EClientSocketBase. Thanks C++ design crap ...
 */
bool EPosixClientSocket::eConnect2( const char *host, unsigned int port,
	int clientId, int family )
{
	// already connected?
	if( m_fd >= 0) {
		assert(false); // for now we don't allow that
		return true;
	}

	// initialize Winsock DLL (only for Windows)
	if ( !SocketsInit())	{
		// Does this set errno?
		getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(),
			"Initializing Winsock DLL failed.");
		return false;
	}

	// use local machine if no host passed in
	if ( !( host && *host)) {
		host = "127.0.0.1";
	}

	// starting to connect to server
	struct addrinfo *aitop;

	int s = resolveHost( host, port, family, &aitop );
	if( s != 0 ) {
		SocketsDestroy();
		const char *err;
#ifdef HAVE_GETADDRINFO
		err = gai_strerror(s);
#else
		err = "Invalid address, hostname resolving not supported.";
#endif
		getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err );
		return false;
	}

	int con_errno = 0;
	for( struct addrinfo *ai = aitop; ai != NULL; ai = ai->ai_next ) {

		// create socket
		m_fd = socket(ai->ai_family, ai->ai_socktype, 0);
		if( m_fd < 0) {
			con_errno = errno;
			continue;
		}

		/* Set socket O_NONBLOCK. If wanted we could handle errors
		   (portability!) We could even make O_NONBLOCK optional. */
		int sn = set_socket_nonblock( m_fd );
		assert( sn == 0 );

		// try to connect
		if( timeout_connect( m_fd, ai->ai_addr, ai->ai_addrlen ) < 0 ) {
			con_errno = errno;
			SocketClose(m_fd);
			m_fd = -1;
			continue;
		}
		/* successfully  connected */
		break;
	}

	freeaddrinfo(aitop);

	/* connection failed, tell the error which happened in our last try  */
	if( m_fd < 0 ) {
		const char *err = strerror(con_errno);
		SocketsDestroy();
		getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err );
		return false;
	}

	// set client id
	setClientId( clientId);

	errno = 0;
	onConnectBase();
	if( !isOutBufferEmpty() ) {
		/* For now we consider it as error if it's not possible to send an
		   integer string within a single tcp packet. Here we don't know weather
		   ::send() really failed or not. If so then we hopefully still have
		   it's errno set.*/
		const char *err = (errno != 0) ? strerror(errno)
			: "Sending client id failed.";
		eDisconnect();
		getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err );
		return false;
	}

	if( wait_socket( m_fd, WAIT_READ ) <= 0 ) {
		const char *err = (errno != 0) ? strerror(errno) : strerror(ENODATA);
		eDisconnect();
		getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err );
		return false;
	}

	while( !isConnected() ) {
		assert( isSocketOK() ); // need to be handled if send() would destroy it
		if ( !checkMessagesConnect()) {
			const char *err = (errno != 0) ? strerror(errno)
				: "The remote host closed the connection.";
			eDisconnect();
			getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err );
			return false;
		}
	}
	// successfully connected
	return true;
}
Пример #10
0
int main (int argc, char **argv)
{
    struct tftphdr *tp;

    struct passwd *pw;

    struct options *opt;

    struct sockaddr_in myaddr;

    struct sockaddr_in bindaddr;

    int n;

    int fd = 0;

    int standalone = 0;            /* Standalone (listen) mode */

    char *address = NULL;        /* Address to listen to */

    pid_t pid;

    mode_t my_umask = 0;

    int spec_umask = 0;

    int c;

    int setrv;

    int waittime = 900;            /* Default time to wait for a connect */

    const char *user = "******";    /* Default user */

    char *p, *ep;

#ifdef WITH_REGEX
    char *rewrite_file = NULL;
#endif

    /* basename() is way too much of a pain from a portability standpoint */

    p = strrchr (argv[0], '/');
    __progname = (p && p[1]) ? p + 1 : argv[0];

    openlog (__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);

    while ((c = getopt (argc, argv, "cspvVla:u:U:r:t:m:")) != -1)
        switch (c)
        {
        case 'c':
            cancreate = 1;
            break;
        case 's':
            secure = 1;
            break;
        case 'p':
            unixperms = 1;
            break;
        case 'l':
            standalone = 1;
            break;
        case 'a':
            address = optarg;
            break;
        case 't':
            waittime = atoi (optarg);
            break;
        case 'u':
            user = optarg;
            break;
        case 'U':
            my_umask = strtoul (optarg, &ep, 8);
            if (*ep)
            {
                syslog (LOG_ERR, "Invalid umask: %s", optarg);
                exit (EX_USAGE);
            }
            spec_umask = 1;
            break;
        case 'r':
            for (opt = options; opt->o_opt; opt++)
            {
                if (!strcasecmp (optarg, opt->o_opt))
                {
                    opt->o_opt = "";    /* Don't support this option */
                    break;
                }
            }
            if (!opt->o_opt)
            {
                syslog (LOG_ERR, "Unknown option: %s", optarg);
                exit (EX_USAGE);
            }
            break;
#ifdef WITH_REGEX
        case 'm':
            if (rewrite_file)
            {
                syslog (LOG_ERR, "Multiple -m options");
                exit (EX_USAGE);
            }
            rewrite_file = optarg;
            break;
#endif
        case 'v':
            verbosity++;
            break;
        case 'V':
            /* Print configuration to stdout and exit */
            printf ("%s\n", TFTPD_CONFIG_STR);
            exit (0);
            break;
        default:
            usage ();
            break;
        }

    dirs = xmalloc ((argc - optind + 1) * sizeof (char *));
    for (ndirs = 0; optind != argc; optind++)
        dirs[ndirs++] = argv[optind];

    dirs[ndirs] = NULL;

    if (secure)
    {
        if (ndirs == 0)
        {
            syslog (LOG_ERR, "no -s directory");
            exit (EX_USAGE);
        }
        if (ndirs > 1)
        {
            syslog (LOG_ERR, "too many -s directories");
            exit (EX_USAGE);
        }
        if (chdir (dirs[0]))
        {
            syslog (LOG_ERR, "%s: %m", dirs[0]);
            exit (EX_NOINPUT);
        }
    }

    pw = getpwnam (user);
    if (!pw)
    {
        syslog (LOG_ERR, "no user %s: %m", user);
        exit (EX_NOUSER);
    }

    if (spec_umask || !unixperms)
        umask (my_umask);

    /* Note: on Cygwin, select() on a nonblocking socket becomes
       a nonblocking select. */
#ifndef __CYGWIN__
    set_socket_nonblock (fd, 1);
#endif

#ifdef WITH_REGEX
    if (rewrite_file)
        rewrite_rules = read_remap_rules (rewrite_file);
#endif

    /* If we're running standalone, set up the input port */
    if (standalone)
    {
        fd = socket (PF_INET, SOCK_DGRAM, 0);

        memset (&bindaddr, 0, sizeof bindaddr);
        bindaddr.sin_family = AF_INET;
        bindaddr.sin_addr.s_addr = INADDR_ANY;
        bindaddr.sin_port = htons (IPPORT_TFTP);

        if (address)
        {
            char *portptr, *eportptr;

            struct hostent *hostent;

            struct servent *servent;

            unsigned long port;

            address = tfstrdup (address);
            portptr = strrchr (address, ':');
            if (portptr)
                *portptr++ = '\0';

            if (*address)
            {
                hostent = gethostbyname (address);
                if (!hostent || hostent->h_addrtype != AF_INET)
                {
                    syslog (LOG_ERR, "cannot resolve local bind address: %s", address);
                    exit (EX_NOINPUT);
                }
                memcpy (&bindaddr.sin_addr, hostent->h_addr, hostent->h_length);
            }
            else
            {
                /* Default to using INADDR_ANY */
            }

            if (portptr && *portptr)
            {
                servent = getservbyname (portptr, "udp");
                if (servent)
                {
                    bindaddr.sin_port = servent->s_port;
                }
                else if ((port = strtoul (portptr, &eportptr, 0)) && !*eportptr)
                {
                    bindaddr.sin_port = htons (port);
                }
                else if (!strcmp (portptr, "tftp"))
                {
                    /* It's TFTP, we're OK */
                }
                else
                {
                    syslog (LOG_ERR, "cannot resolve local bind port: %s", portptr);
                    exit (EX_NOINPUT);
                }
            }
        }

        if (bind (fd, (struct sockaddr *) &bindaddr, sizeof bindaddr) < 0)
        {
            syslog (LOG_ERR, "cannot bind to local socket: %m");
            exit (EX_OSERR);
        }

        /* Daemonize this process */
        {
            pid_t f = fork ();

            int nfd;

            if (f > 0)
                exit (0);
            if (f < 0)
            {
                syslog (LOG_ERR, "cannot fork: %m");
                exit (EX_OSERR);
            }
            nfd = open ("/dev/null", O_RDWR);
            if (nfd >= 0)
            {
#ifdef HAVE_DUP2
                dup2 (nfd, 0);
                dup2 (nfd, 1);
                dup2 (nfd, 2);
#else
                close (0);
                dup (nfd);
                close (1);
                dup (nfd);
                close (2);
                dup (nfd);
#endif
                close (nfd);
            }
            else
            {
                close (0);
                close (1);
                close (2);
            }
#ifdef HAVE_SETSID
#ifndef __CYGWIN__                /* Kills the process on Cygwin? */
            setsid ();
#endif
#endif
        }
    }
    else
    {
        /* 0 is our socket descriptor */
        close (1);
        close (2);
    }

    /* This means we don't want to wait() for children */
#ifdef SA_NOCLDWAIT
    set_signal (SIGCHLD, SIG_IGN, SA_NOCLDSTOP | SA_NOCLDWAIT);
#else
    set_signal (SIGCHLD, SIG_IGN, SA_NOCLDSTOP);
#endif

    /* Take SIGHUP and use it to set a variable.  This
       is polled synchronously to make sure we don't
       lose packets as a result. */
    set_signal (SIGHUP, handle_sighup, 0);

    while (1)
    {
        fd_set readset;

        struct timeval tv_waittime;

        int rv;

        if (caught_sighup)
        {
            caught_sighup = 0;
            if (standalone)
            {
#ifdef HAVE_REGEX
                if (rewrite_file)
                {
                    freerules (rewrite_rules);
                    rewrite_rules = read_remap_rules (rewrite_file);
                }
#endif
            }
            else
            {
                /* Return to inetd for respawn */
                exit (0);
            }
        }

        FD_ZERO (&readset);
        FD_SET (fd, &readset);
        tv_waittime.tv_sec = waittime;
        tv_waittime.tv_usec = 0;

#ifdef __CYGWIN__
        /* On Cygwin, select() on a nonblocking socket returns immediately,
           with a rv of 0! */
        set_socket_nonblock (fd, 0);
#endif

        /* Never time out if we're in standalone mode */
        rv = select (fd + 1, &readset, NULL, NULL, standalone ? NULL : &tv_waittime);
        if (rv == -1 && errno == EINTR)
            continue;            /* Signal caught, reloop */
        if (rv == -1)
        {
            syslog (LOG_ERR, "select loop: %m");
            exit (EX_IOERR);
        }
        else if (rv == 0)
        {
            exit (0);            /* Timeout, return to inetd */
        }

#ifdef __CYGWIN__
        set_socket_nonblock (fd, 1);
#endif

        fromlen = sizeof (from);
        n = myrecvfrom (fd, buf, sizeof (buf), 0, (struct sockaddr *) &from, &fromlen, &myaddr);

        if (n < 0)
        {
            if (E_WOULD_BLOCK (errno) || errno == EINTR)
            {
                continue;        /* Again, from the top */
            }
            else
            {
                syslog (LOG_ERR, "recvfrom: %m");
                exit (EX_IOERR);
            }
        }

        if (standalone && myaddr.sin_addr.s_addr == INADDR_ANY)
        {
            /* myrecvfrom() didn't capture the source address; but we might
               have bound to a specific address, if so we should use it */
            memcpy (&myaddr.sin_addr, &bindaddr.sin_addr, sizeof bindaddr.sin_addr);
        }

        /*
         * Now that we have read the request packet from the UDP
         * socket, we fork and go back to listening to the socket.
         */
        pid = fork ();
        if (pid < 0)
        {
            syslog (LOG_ERR, "fork: %m");
            exit (EX_OSERR);    /* Return to inetd, just in case */
        }
        else if (pid == 0)
            break;                /* Child exit, parent loop */
    }

    /* Child process: handle the actual request here */

    /* Ignore SIGHUP */
    set_signal (SIGHUP, SIG_IGN, 0);

#ifdef HAVE_TCPWRAPPERS
    /* Verify if this was a legal request for us.  This has to be
       done before the chroot, while /etc is still accessible. */
    request_init (&wrap_request, RQ_DAEMON, __progname, RQ_FILE, fd, RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0);
    sock_methods (&wrap_request);
    if (hosts_access (&wrap_request) == 0)
    {
        if (deny_severity != -1)
            syslog (deny_severity, "connection refused from %s", inet_ntoa (from.sin_addr));
        exit (EX_NOPERM);        /* Access denied */
    }
    else if (allow_severity != -1)
    {
        syslog (allow_severity, "connect from %s", inet_ntoa (from.sin_addr));
    }
#endif

    /* Close file descriptors we don't need */
    close (fd);

    /* Get a socket.  This has to be done before the chroot(), since
       some systems require access to /dev to create a socket. */

    peer = socket (AF_INET, SOCK_DGRAM, 0);
    if (peer < 0)
    {
        syslog (LOG_ERR, "socket: %m");
        exit (EX_IOERR);
    }

    /* Set up the supplementary group access list if possible */
    /* /etc/group still need to be accessible at this point */
#ifdef HAVE_INITGROUPS
    setrv = initgroups (user, pw->pw_gid);
    if (setrv)
    {
        syslog (LOG_ERR, "cannot set groups for user %s", user);
        exit (EX_OSERR);
    }
#else
#ifdef HAVE_SETGROUPS
    if (setgroups (0, NULL))
    {
        syslog (LOG_ERR, "cannot clear group list");
    }
#endif
#endif

    /* Chroot and drop privileges */
    if (secure)
    {
        if (chroot ("."))
        {
            syslog (LOG_ERR, "chroot: %m");
            exit (EX_OSERR);
        }
#ifdef __CYGWIN__
        chdir ("/");            /* Cygwin chroot() bug workaround */
#endif
    }

#ifdef HAVE_SETREGID
    setrv = setregid (pw->pw_gid, pw->pw_gid);
#else
    setrv = setegid (pw->pw_gid) || setgid (pw->pw_gid);
#endif

#ifdef HAVE_SETREUID
    setrv = setrv || setreuid (pw->pw_uid, pw->pw_uid);
#else
    /* Important: setuid() must come first */
    setrv = setrv || setuid (pw->pw_uid) || (geteuid () != pw->pw_uid && seteuid (pw->pw_uid));
#endif

    if (setrv)
    {
        syslog (LOG_ERR, "cannot drop privileges: %m");
        exit (EX_OSERR);
    }

    /* Other basic setup */
    from.sin_family = AF_INET;

    /* Process the request... */

    myaddr.sin_port = htons (0);    /* We want a new local port */
    if (bind (peer, (struct sockaddr *) &myaddr, sizeof myaddr) < 0)
    {
        syslog (LOG_ERR, "bind: %m");
        exit (EX_IOERR);
    }
    if (connect (peer, (struct sockaddr *) &from, sizeof from) < 0)
    {
        syslog (LOG_ERR, "connect: %m");
        exit (EX_IOERR);
    }
    tp = (struct tftphdr *) buf;
    tp->th_opcode = ntohs (tp->th_opcode);
    if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
        tftp (tp, n);
    exit (0);
}
Пример #11
0
/* Create new TCP connection to ip_port/public_key
 */
TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
        const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
{
    if (networking_at_startup() != 0) {
        return NULL;
    }

    if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) {
        return NULL;
    }

    uint8_t family = ip_port.ip.family;

    TCP_Proxy_Info default_proxyinfo;

    if (proxy_info == NULL) {
        default_proxyinfo.proxy_type = TCP_PROXY_NONE;
        proxy_info = &default_proxyinfo;
    }

    if (proxy_info->proxy_type != TCP_PROXY_NONE) {
        family = proxy_info->ip_port.ip.family;
    }

    Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);

    if (!sock_valid(sock)) {
        return NULL;
    }

    if (!set_socket_nosigpipe(sock)) {
        kill_sock(sock);
        return 0;
    }

    if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
        kill_sock(sock);
        return NULL;
    }

    TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1);

    if (temp == NULL) {
        kill_sock(sock);
        return NULL;
    }

    temp->sock = sock;
    memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
    memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
    encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
    temp->ip_port = ip_port;
    temp->proxy_info = *proxy_info;

    switch (proxy_info->proxy_type) {
        case TCP_PROXY_HTTP:
            temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
            proxy_http_generate_connection_request(temp);
            break;

        case TCP_PROXY_SOCKS5:
            temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
            proxy_socks5_generate_handshake(temp);
            break;

        case TCP_PROXY_NONE:
            temp->status = TCP_CLIENT_CONNECTING;

            if (generate_handshake(temp) == -1) {
                kill_sock(sock);
                free(temp);
                return NULL;
            }

            break;
    }

    temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;

    return temp;
}