void add_client_socket(int server_socket, int epoll) {
    struct sockaddr_in cliaddr;
    socklen_t addr_size = sizeof cliaddr;

    int client_socket = accept(server_socket, (struct sockaddr*) &cliaddr, &addr_size);
    if (client_socket < 0) {
        perror("accept");
        return;
    }

    setnonblocking(client_socket);
    struct epoll_event connev;
    connev.data.fd = client_socket;
    connev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLHUP;
    if (!epoll_ctl(epoll, EPOLL_CTL_ADD, client_socket, &connev) < 0) {
        perror("Epoll fd add");
        close(client_socket);
        return;
    }
}
示例#2
0
void accept_cb(EV_P_ ev_io *w, int revents)
{
    struct listen_ctx *listener = (struct listen_ctx *)w;
    int serverfd = accept(listener->fd, NULL, NULL);
    if (serverfd == -1) {
        ERROR("accept");
        return;
    }
    setnonblocking(serverfd);
    int opt = 1;
    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

    struct server *server = new_server(serverfd, listener->method);
    server->listener = listener;

    ev_io_start(EV_A_ & server->recv_ctx->io);
}
示例#3
0
文件: proxy.c 项目: bdzxg/mspc
int 
pxy_start_listen()
{
	struct sockaddr_in addr1;

	master->listen_fd = socket(AF_INET,SOCK_STREAM,0);
	if (master->listen_fd < 0) {
		D("create listen fd error");
		return -1;
	}

	int reuse = 1;
	setsockopt(master->listen_fd,
		   SOL_SOCKET,
		   SO_REUSEADDR,
		   &reuse,
		   sizeof(int));
	
	if (setnonblocking(master->listen_fd) < 0) {
		D("set nonblocling error");
		return -1;
	}

	addr1.sin_family = AF_INET;
	addr1.sin_port = htons(setting.client_port);
	inet_aton(setting.ip, &addr1.sin_addr);
	
	if (bind(master->listen_fd, (struct sockaddr*)&addr1,
		sizeof(addr1)) < 0) {
		E("bind address %s:%d error", setting.ip,
		  setting.client_port);
		return -1;
	}

	if (listen(master->listen_fd,1000) < 0) {
		E("listen error");
		return -1;
	}
    
	return 0;
}
示例#4
0
int accept_agent_side( agent_t *agent, event_info_t *event_info) 
{
   socklen_t sin_size; 
   struct sockaddr_storage their_addr; 
   sin_size = sizeof(their_addr); 
   int index = find_empty_agent_sock(agent); 
	struct epoll_event event; 

   if(index < 0) 
   { 
      printf("agent sock table full!!!\n"); 
      exit(1); 
   } 

   if(( agent->agent_fd_pool[index] = 
		accept(agent->listen_fds.agent_listen_sock[event_info->fd], 
   	(struct sockaddr *) &their_addr, &sin_size)) == -1)
	{
		perror(""); 
		printf("%s %d\n", __FILE__, __LINE__); 
		exit(1); 	
   }

   setnonblocking(agent->agent_fd_pool[index]); 

	event.events = EPOLLOUT; 
	event.data.ptr =  &agent->agent_fd_pool_event[index]; 
	agent->agent_fd_pool_event[index].type =	AGENT_CONNECTED_UUID;  
	agent->agent_fd_pool_event[index].fd = index; 	

	if( epoll_ctl(agent->event_pool, EPOLL_CTL_ADD, 
	   agent->agent_fd_pool[index], &event)) 
	{ 
	   perror("");
	   printf("%s %d\n", __FILE__, __LINE__); 
	   exit(1); 
	}


   return EXIT_SUCCESS; 
}
示例#5
0
int build_server() {
    struct addrinfo hints, *res;
    int s;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    s = getaddrinfo("0.0.0.0", setting.faddr_port, &hints, &res);
    if (s != 0) {
        perror("getaddrinfo error");
        return -1;
    }

    serv_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

    if(serv_sock < 0) {
        perror("socket error");
        exit(1);
    }

    int opt = 1;
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    setsockopt(serv_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(serv_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif


    if ( bind(serv_sock, res->ai_addr, res->ai_addrlen) == -1) {
        perror("bind error");
        exit(1);
    }

    if( listen(serv_sock, SOMAXCONN) == -1 ) {
        perror("listen error");
        exit(1);
    }

    setnonblocking(serv_sock);
}
示例#6
0
文件: master.c 项目: salewski/dtach
/* Creates a new unix domain socket. */
static int
create_socket(char *name)
{
	int s;
	struct sockaddr_un sockun;

	if (strlen(name) > sizeof(sockun.sun_path) - 1)
	{
		errno = ENAMETOOLONG;
		return -1;
	}

	s = socket(PF_UNIX, SOCK_STREAM, 0);
	if (s < 0)
		return -1;
	sockun.sun_family = AF_UNIX;
	strcpy(sockun.sun_path, name);
	if (bind(s, (struct sockaddr*)&sockun, sizeof(sockun)) < 0)
	{
		close(s);
		return -1;
	}
	if (listen(s, 128) < 0)
	{
		close(s);
		return -1;
	}
	if (setnonblocking(s) < 0)
	{
		close(s);
		return -1;
	}
	/* chmod it to prevent any suprises */
	if (chmod(name, 0600) < 0)
	{
		close(s);
		return -1;
	}
	return s;
}
示例#7
0
static remote_t *create_remote(listen_ctx_t *listener,
                               struct sockaddr *addr)
{
    struct sockaddr *remote_addr;

    int index = rand() % listener->remote_num;
    if (addr == NULL) {
        remote_addr = listener->remote_addr[index];
    } else {
        remote_addr = addr;
    }

    int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);

    if (remotefd < 0) {
        ERROR("socket");
        return NULL;
    }

    int opt = 1;
    setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

    // Setup
    setnonblocking(remotefd);
#ifdef SET_INTERFACE
    if (listener->iface) {
        setinterface(remotefd, listener->iface);
    }
#endif

    remote_t *remote = new_remote(remotefd, listener->timeout);
    remote->addr_len = get_sockaddr_len(remote_addr);
    memcpy(&(remote->addr), remote_addr, remote->addr_len);
    remote->remote_index = index;

    return remote;
}
void setUpServer(int argc, char *argv[]) //Sets up the server
{
    timeout.tv_sec  = TIMEOUT_SEC;
    timeout.tv_usec = TIMEOUT_MS;
    
    
    if (argc < MIN_ARGS) 
    {
        fprintf(stderr,"ERROR, no port provided\n");
        exit(1);
    }
    //set up the socket. we are using TCP
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    if (sockfd < 0)  //make sure we can open the socket
    {
        error("ERROR opening socket");
    }
    
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); //allow reuse of address
    
    setnonblocking(sockfd); //nonblocking
    
    //port stuff
    bzero((char *) &serv_addr, sizeof(serv_addr));
    
    portno = atoi(argv[PORT_ARG_SERVER]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) //check it we can bind it
    {
        error("ERROR on binding");
    }
    
    listen(sockfd, LISTENING_QUEUE); //set up a listening queue
    
    clilen = sizeof(cli_addr); //set the length of the address
}
示例#9
0
int accept_host_side(agent_t *agent, client_t *new_client) 
{
	socklen_t sin_size; 
	struct sockaddr_in their_addr; 
	struct epoll_event event; 

	sin_size = sizeof(their_addr); 


	if(( new_client->host_sock = accept(agent->listen_fds.host_listen_sock, 
		(struct sockaddr *) &their_addr, &sin_size)) == -1)
	{
      perror(""); 
	   printf("%s %d\n", __FILE__, __LINE__); 
      exit(1); 
	}
   
	
	strcpy(new_client->source_ip, inet_ntoa(their_addr.sin_addr)); 
	new_client->source_port = htons(their_addr.sin_port); 
	

   new_client->host_fd_poll = OFF; 
	setnonblocking(new_client->host_sock); 
	event.events = EPOLLOUT; 
   event.data.ptr =  &new_client->host_side_event_info; 
   new_client->host_side_event_info.type = HOST_CONNECTED;  
	new_client->host_side_event_info.client = new_client; 

	if( epoll_ctl(agent->event_pool, EPOLL_CTL_ADD, 
	   new_client->host_sock, &event)) 
	{ 
	   perror("");
	   printf("%s %d\n", __FILE__, __LINE__); 
	   exit(1); 
	}


	return EXIT_SUCCESS; 
}
示例#10
0
CAcceptor::CAcceptor(CInetAddr& sockAddr, 
	int backlog, int timeout) : CSock(AF_INET, SOCK_STREAM)
{
	int res;
	if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &res, sizeof(int)) < 0)
	{
		KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \
			"set SO_REUSEADDR failed, err: %s", \
			__LINE__, strerror(errno));
		throw errno;
	}

	if(bind(m_fd, sockAddr.getsockaddr(), sizeof(struct sockaddr)) == -1)
	{
			KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \
				"call bind failed, err: %s", \
				__LINE__, strerror(errno));
			throw errno;
	}
	listen(m_fd, backlog);

	if(timeout > 0) //server option
	{
		if((res = setserveropt(timeout)) != 0)
		{
			KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \
				"acceptor set server option failed, err: %s", \
				__LINE__, strerror(res));
			throw res;
		}
	}

	if((res = setnonblocking()) != 0)
	{
		KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \
			"acceptor set nonblocking failed, err: %s", \
			__LINE__, strerror(res));
		throw res;
	}
}
示例#11
0
ape_socket *ape_connect(char *ip, int port, acetables *g_ape)
{
	int sock, ret;
	struct sockaddr_in addr;
	
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_connect() - socket() : %s", strerror(errno));
		return NULL;
	}

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);
	memset(&(addr.sin_zero), '\0', 8);

	setnonblocking(sock);
	
	if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == 0 || errno != EINPROGRESS) {
		return NULL;
	}

	prepare_ape_socket(sock, g_ape);
	
	g_ape->co[sock]->buffer_in.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
	g_ape->co[sock]->buffer_in.size = DEFAULT_BUFFER_SIZE;

	g_ape->co[sock]->fd = sock;
	g_ape->co[sock]->state = STREAM_PROGRESS;
	g_ape->co[sock]->stream_type = STREAM_OUT;
	
	g_ape->bufout[sock].fd = sock;
	g_ape->bufout[sock].buf = NULL;
	g_ape->bufout[sock].buflen = 0;
	g_ape->bufout[sock].allocsize = 0;

	ret = events_add(g_ape->events, sock, EVENT_READ|EVENT_WRITE);
	
	return g_ape->co[sock];	
}
示例#12
0
int
init_socket(int efd, uint16_t sock_type, struct sockaddr *srv, uint16_t srvlen, size_t simultaneous_connection)
{
  struct epoll_event ev;
  static int optval = 1;
  int fd;

  if ((fd = socket(sock_type, SOCK_STREAM,  0)) == -1)
    return -1;

  if (!setnonblocking(fd))
    goto error;

  memset(&ev, 0, sizeof(struct epoll_event));

  ev.data.fd = fd;
  ev.events  = EPOLLIN | EPOLLET;

  if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1)
    goto error;

  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

  int on = 1;
  if (srv->sa_family == AF_INET6)
    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));

  if (bind(fd, srv, srvlen) == -1)
    goto error;

  if (listen(fd, simultaneous_connection) == -1)
    goto error;

  return fd;
error:
  close(fd);
  return -1;
}
示例#13
0
static void accept_cb (EV_P_ ev_io *w, int revents) {
    struct listen_ctx *listener = (struct listen_ctx *)w;
    int serverfd = accept(listener->fd, NULL, NULL);
    if (serverfd == -1) {
        ERROR("accept");
        return;
    }
    setnonblocking(serverfd);

    int opt = 1;
    setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

    if (verbose) {
        LOGD("accept a connection.");
    }

    struct server *server = new_server(serverfd, listener);
    ev_io_start(EV_A_ &server->recv_ctx->io);
    ev_timer_start(EV_A_ &server->recv_ctx->watcher);
}
示例#14
0
文件: stud.c 项目: mqudsi/stud
/* Create the bound socket in the parent process */
static int create_main_socket() {
    struct addrinfo *ai, hints;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
    const int gai_err = getaddrinfo(OPTIONS.FRONT_IP, OPTIONS.FRONT_PORT,
                                    &hints, &ai);
    if (gai_err != 0) {
        ERR("{getaddrinfo}: [%s]\n", gai_strerror(gai_err));
        exit(1);
    }

    int s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
    int t = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int));
#ifdef SO_REUSEPORT
    setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int));
#endif
    setnonblocking(s);

    if (bind(s, ai->ai_addr, ai->ai_addrlen)) {
        fail("{bind-socket}");
    }

#if TCP_DEFER_ACCEPT
    int timeout = 1; 
    setsockopt(s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int) );
#endif /* TCP_DEFER_ACCEPT */

    prepare_proxy_line(ai->ai_addr);

    freeaddrinfo(ai);
    listen(s, OPTIONS.BACKLOG);

    return s;
}
示例#15
0
文件: inet.c 项目: upidea/Mihttpd
/*
*	初始化网络
*/
int inet_init()
{
	socket_t s;
	int buf_size = 8*1024;
	int reuse = 1;
	
	if ((listening.s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		log_error(errno, "socket()");
		exit(1);
	}
	
	if (setsockopt(listening.s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1 || 
		setsockopt(listening.s, SOL_SOCKET, SO_REUSEADDR, &buf_size, sizeof(buf_size)) == -1) {
		log_error(errno, "setsockopt()");
		exit(1);
	}
	
	bzero(&listening.ls_addr, sizeof(listening.ls_addr));
	listening.ls_addr.sin_family = AF_INET;
	listening.ls_addr.sin_port = htons(LISTEN_PORT);
	listening.ls_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if (bind(listening.s, (struct sockaddr *)&listening.ls_addr, sizeof(listening.ls_addr)) == -1) {
		log_error(errno, "bind()");
		exit(1);
	}
	
	if (listen(listening.s, LISTEN_BACKLOG) == -1) {
		log_error(errno, "listen()");
		exit(1);
	}
	
	setnonblocking(listening.s);
	
	//注册一个accept()后的处理钩子
	//listening.handler = http_connection_init;
}
示例#16
0
bool CLoveTcp::CreateSocket()
{
	if((m_nSocket = socket(AF_INET,SOCK_STREAM,0))==-1)  
	{
		LogErrorMsg("create socket error");
		return false;
	}
	if (setnonblocking(m_nSocket) == -1)
	{
		LogErrorMsg("setnonblocking error");
	}
	int nSock = 0;
	if (setsockopt(m_nSocket,SOL_SOCKET,SO_REUSEADDR,&nSock,sizeof(nSock)) < 0)
	{
		/* code */
		LogErrorMsg("setsockopt failed");
	}
	m_nEpoll = epoll_create1(EPOLL_CLOEXEC);
	if (EpollAdd(m_nSocket) == false)
	{
		return false;
	};
	return true;
}
示例#17
0
int handle_accept(int fd)
{
	struct epoll_event ev;
	struct echo_data* pecho_data;

	int newsock = 0;
	do{//edge-trigger
		newsock = accept(fd,NULL,NULL);
		//if( newsock <=0 ){
		if( newsock == -1 ){ //error occur
			if( (errno == EAGAIN) || (errno == EWOULDBLOCK) ) break;
			else{
				perror("accept error");
				return -1;
			}
		} else {
			printf("Client accept with descriptor #%d\n" ,newsock);
			pecho_data = alloc_echo_data(newsock, MAX_ECHO_BUF);
			if( NULL == pecho_data ){
				perror("malloc error");
				return -1;
			}

			setnonblocking(newsock); //set nonblocking 
			ev.data.ptr = pecho_data;

			ev.events = EPOLLIN|EPOLLPRI|EPOLLET; //edge-trigger
			if( -1 == epoll_ctl(epfd, EPOLL_CTL_ADD, newsock, &ev) ){
				perror("epoll_ctl error!");
				return -1;
			}
		}
	}while(1);

	return 0;
}
示例#18
0
void handle_new_connection() 
{
	int listnum;	    //Current item in fd
	int connection;     // Socket file descriptor for incoming connections 
    
	connection = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    
	if (connection < 0) 
    {
		perror("accept");
		exit(EXIT_FAILURE);
	}
    
	setnonblocking(connection);
    
	for (listnum = 0; (listnum < MAX_USERS) && (connection != -1); listnum ++)
		if (fd[listnum] == 0) 
        {
			printf("\nConnection accepted:   FD=%d; Slot=%d\n", connection, listnum);
			fd[listnum] = connection;
			connection = -1;
		}
    
	if (connection != -1) 
    {
		// No room left in the queue!
		printf("\nNo room left for new client.\n");
    }
    else
    {
        struct user newUser;
        newUser.address.sin_addr.s_addr = cli_addr.sin_addr.s_addr; //store the ip
        printf("USER IP: %u at %d\n", newUser.address.sin_addr.s_addr, listnum - 1);
        users[fd[listnum - 1]] = newUser;
    }
}
示例#19
0
/**
 * HTTTP daemon listener entry point
 *
 * @param	listener	The Listener DCB
 * @param	config		Configuration (ip:port)
 */
static int
httpd_listen(DCB *listener, char *config)
{
struct sockaddr_in	addr;
char			*port;
int			one = 1;
short			pnum;
int                     rc;

	memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL));

	port = strrchr(config, ':');
	if (port)
		port++;
	else
		port = "6442";

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	pnum = atoi(port);
	addr.sin_port = htons(pnum);

	if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		return 0;
	}

        /* socket options */
	setsockopt(listener->fd,
                   SOL_SOCKET,
                   SO_REUSEADDR,
                   (char *)&one,
                   sizeof(one));

        /* set NONBLOCKING mode */
        setnonblocking(listener->fd);

        /* bind address and port */
        if (bind(listener->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
        	return 0;
	}

        rc = listen(listener->fd, SOMAXCONN);
        
        if (rc == 0) {
            fprintf(stderr,
                    "Listening http connections at %s\n",
                    config);
        } else {
            int eno = errno;
            errno = 0;
            fprintf(stderr,
                    "\n* Failed to start listening http due error %d, %s\n\n",
                    eno,
                    strerror(eno));
            return 0;
        }

        
        if (poll_add_dcb(listener) == -1)
	{
		return 0;
	}
	return 1;
}
示例#20
0
int
main(int argc, char **argv)
{
    srand(time(NULL));

    int i, c;
    int pid_flags    = 0;
    int mptcp        = 0;
    int mtu          = 0;
    char *user       = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password   = NULL;
    char *timeout    = NULL;
    char *method     = NULL;
    char *pid_path   = NULL;
    char *conf_path  = NULL;

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    int option_index                    = 0;
    static struct option long_options[] = {
        { "mtu",   required_argument, 0, 0 },
        { "mptcp", no_argument,       0, 0 },
        { "help",  no_argument,       0, 0 },
        {       0,                 0, 0, 0 }
    };

    opterr = 0;

    USE_TTY();

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                mtu = atoi(optarg);
                LOGI("set MTU to %d", mtu);
            } else if (option_index == 1) {
                mptcp = 1;
                LOGI("enable multipath TCP");
            } else if (option_index == 2) {
                usage();
                exit(EXIT_SUCCESS);
            }
            break;
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host   = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path  = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
#ifdef HAVE_SETRLIMIT
        case 'n':
            nofile = atoi(optarg);
            break;
#endif
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        case 'A':
            auth = 1;
            break;
        case '6':
            ipv6first = 1;
            break;
        case '?':
            // The option character is not recognized.
            LOGE("Unrecognized option: %s", optarg);
            opterr = 1;
            break;
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++)
                remote_addr[i] = conf->remote_addr[i];
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (user == NULL) {
            user = conf->user;
        }
        if (auth == 0) {
            auth = conf->auth;
        }
        if (mtu == 0) {
            mtu = conf->mtu;
        }
        if (mptcp == 0) {
            mptcp = conf->mptcp;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (method == NULL) {
        method = "rc4-md5";
    }

    if (timeout == NULL) {
        timeout = "600";
    }

#ifdef HAVE_SETRLIMIT
    /*
     * no need to check the return value here since we will show
     * the user an error message if setrlimit(2) fails
     */
    if (nofile > 1024) {
        if (verbose) {
            LOGI("setting NOFILE to %d", nofile);
        }
        set_nofile(nofile);
    }
#endif

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (ipv6first) {
        LOGI("resolving hostname to IPv6 address first");
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
    signal(SIGINT, signal_cb);
    signal(SIGTERM, signal_cb);

    // Setup keys
    LOGI("initializing ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup proxy context
    listen_ctx_t listen_ctx;
    listen_ctx.remote_num  = remote_num;
    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);
    for (int i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
                     remote_addr[i].port;
        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.method  = m;
    listen_ctx.mptcp   = mptcp;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd == -1) {
            FATAL("bind() error");
        }
        if (listen(listenfd, SOMAXCONN) == -1) {
            FATAL("listen() error");
        }
        setnonblocking(listenfd);

        listen_ctx.fd = listenfd;

        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
        ev_io_start(loop, &listen_ctx.io);
    }

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), mtu, m, auth, listen_ctx.timeout, NULL);
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL && ! run_as(user)) {
        FATAL("failed to switch user");
    }

    if (geteuid() == 0){
        LOGI("running from root user");
    }

    ev_run(loop, 0);

    return 0;
}
示例#21
0
int bsc_msc_connect(struct bsc_msc_connection *con)
{
	struct bsc_msc_dest *dest;
	struct osmo_fd *fd;
	struct sockaddr_in sin;
	int on = 1, ret;

	if (llist_empty(con->dests)) {
		LOGP(DMSC, LOGL_ERROR,
			"No MSC(%s) connections configured.\n",
			con->name);
		connection_loss(con);
		return -1;
	}

	/* TODO: Why are we not using the libosmocore soecket
	 * abstraction, or libosmo-netif? */

	/* move to the next connection */
	dest = (struct bsc_msc_dest *) con->dests->next;
	llist_del(&dest->list);
	llist_add_tail(&dest->list, con->dests);

	LOGP(DMSC, LOGL_NOTICE,
		"Attempting to connect MSC(%s) at %s:%d\n",
		con->name, dest->ip, dest->port);

	con->is_connected = 0;

	msgb_free(con->pending_msg);
	con->pending_msg = NULL;

	fd = &con->write_queue.bfd;
	fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	fd->priv_nr = 1;

	if (fd->fd < 0) {
		perror("Creating TCP socket failed");
		return fd->fd;
	}

	/* make it non blocking */
	setnonblocking(fd);

	/* set the socket priority */
	ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS,
			 &dest->dscp, sizeof(dest->dscp));
	if (ret != 0)
		LOGP(DMSC, LOGL_ERROR,
			"Failed to set DSCP to %d on MSC(%s). %s\n",
			dest->dscp, con->name, strerror(errno));

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(dest->port);
	inet_aton(dest->ip, &sin.sin_addr);

	ret = setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if (ret != 0)
		LOGP(DMSC, LOGL_ERROR,
		     "Failed to set SO_REUSEADDR socket option\n");
	ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));

	if (ret == -1 && errno == EINPROGRESS) {
		LOGP(DMSC, LOGL_ERROR,
			"MSC(%s) Connection in progress\n", con->name);
		fd->when = BSC_FD_WRITE;
		fd->cb = msc_connection_connect;
		con->timeout_timer.cb = msc_con_timeout;
		con->timeout_timer.data = con;
		osmo_timer_schedule(&con->timeout_timer, 20, 0);
	} else if (ret < 0) {
		perror("Connection failed");
		connection_loss(con);
		return ret;
	} else {
		fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
		fd->cb = osmo_wqueue_bfd_cb;
		con->is_connected = 1;
		if (con->connected)
			con->connected(con);
	}

	ret = osmo_fd_register(fd);
	if (ret < 0) {
		perror("Registering the fd failed");
		close(fd->fd);
		return ret;
	}

	return ret;
}
示例#22
0
int unblock_connect( const char* ip, int port, int time )
{
    int ret = 0;
    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 );

    int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
    int fdopt = setnonblocking( sockfd );
    ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) );
    if ( ret == 0 )
    {
        printf( "connect with server immediately\n" );
        fcntl( sockfd, F_SETFL, fdopt );
        return sockfd;
    }
    else if ( errno != EINPROGRESS )
    {
        printf( "unblock connect not support\n" );
        return -1;
    }

    fd_set readfds;
    fd_set writefds;
    struct timeval timeout;

    FD_ZERO( &readfds );
    FD_SET( sockfd, &writefds );

    timeout.tv_sec = time;
    timeout.tv_usec = 0;

    ret = select( sockfd + 1, NULL, &writefds, NULL, &timeout );
    if ( ret <= 0 )
    {
        printf( "connection time out\n" );
        close( sockfd );
        return -1;
    }

    if ( ! FD_ISSET( sockfd, &writefds  ) )
    {
        printf( "no events on sockfd found\n" );
        close( sockfd );
        return -1;
    }

    int error = 0;
    socklen_t length = sizeof( error );
    if( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &length ) < 0 )
    {
        printf( "get socket option failed\n" );
        close( sockfd );
        return -1;
    }

    if( error != 0 )
    {
        printf( "connection failed after select with the error: %d \n", error );
        close( sockfd );
        return -1;
    }
    
    printf( "connection ready after select with the socket: %d \n", sockfd );
    fcntl( sockfd, F_SETFL, fdopt );
    return sockfd;
}
示例#23
0
static void
accept_cb(EV_P_ ev_io *w, int revents)
{
    listen_ctx_t *listener = (listen_ctx_t *)w;
    struct sockaddr_storage destaddr;
    int err;

    int serverfd = accept(listener->fd, NULL, NULL);
    if (serverfd == -1) {
        ERROR("accept");
        return;
    }

    err = getdestaddr(serverfd, &destaddr);
    if (err) {
        ERROR("getdestaddr");
        return;
    }

    setnonblocking(serverfd);
    int opt = 1;
    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

    int index                    = rand() % listener->remote_num;
    struct sockaddr *remote_addr = listener->remote_addr[index];

    int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
    if (remotefd == -1) {
        ERROR("socket");
        return;
    }

    // Set flags
    setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
    setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

    // Enable TCP keepalive feature
    int keepAlive    = 1;
    int keepIdle     = 40;
    int keepInterval = 20;
    int keepCount    = 5;
    setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
    setsockopt(remotefd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
    setsockopt(remotefd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
    setsockopt(remotefd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

    // Set non blocking
    setnonblocking(remotefd);

    // Enable MPTCP
    if (listener->mptcp == 1) {
        int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt));
        if (err == -1) {
            ERROR("failed to enable multipath TCP");
        }
    }

    server_t *server = new_server(serverfd, listener->method);
    remote_t *remote = new_remote(remotefd, listener->timeout);
    server->remote   = remote;
    remote->server   = server;
    server->destaddr = destaddr;

    int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));

    if (r == -1 && errno != CONNECT_IN_PROGRESS) {
        ERROR("connect");
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    }

    // listen to remote connected event
    ev_io_start(EV_A_ & remote->send_ctx->io);
    ev_timer_start(EV_A_ & remote->send_ctx->watcher);
    ev_io_start(EV_A_ & server->recv_ctx->io);
}
示例#24
0
static void
server_recv_cb(EV_P_ ev_io *w, int revents)
{
    server_ctx_t *server_ctx = (server_ctx_t *)w;
    struct sockaddr_storage src_addr;
    memset(&src_addr, 0, sizeof(struct sockaddr_storage));

    buffer_t *buf = ss_malloc(sizeof(buffer_t));
    balloc(buf, buf_size);

    socklen_t src_addr_len = sizeof(struct sockaddr_storage);
    unsigned int offset    = 0;

#ifdef MODULE_REDIR
    char control_buffer[64] = { 0 };
    struct msghdr msg;
    memset(&msg, 0, sizeof(struct msghdr));
    struct iovec iov[1];
    struct sockaddr_storage dst_addr;
    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));

    msg.msg_name       = &src_addr;
    msg.msg_namelen    = src_addr_len;
    msg.msg_control    = control_buffer;
    msg.msg_controllen = sizeof(control_buffer);

    iov[0].iov_base = buf->data;
    iov[0].iov_len  = buf_size;
    msg.msg_iov     = iov;
    msg.msg_iovlen  = 1;

    buf->len = recvmsg(server_ctx->fd, &msg, 0);
    if (buf->len == -1) {
        ERROR("[udp] server_recvmsg");
        goto CLEAN_UP;
    } else if (buf->len > packet_size) {
        if (verbose) {
            LOGI("[udp] UDP server_recv_recvmsg fragmentation");
        }
    }

    if (get_dstaddr(&msg, &dst_addr)) {
        LOGE("[udp] unable to get dest addr");
        goto CLEAN_UP;
    }

    src_addr_len = msg.msg_namelen;
#else
    ssize_t r;
    r = recvfrom(server_ctx->fd, buf->data, buf_size,
                 0, (struct sockaddr *)&src_addr, &src_addr_len);

    if (r == -1) {
        // error on recv
        // simply drop that packet
        ERROR("[udp] server_recv_recvfrom");
        goto CLEAN_UP;
    } else if (r > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_recvfrom fragmentation");
        }
    }

    buf->len = r;
#endif

    if (verbose) {
        LOGI("[udp] server receive a packet");
    }

#ifdef MODULE_REMOTE
    tx += buf->len;

    int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size);
    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }
#endif

#ifdef MODULE_LOCAL
#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)
#ifdef __ANDROID__
    tx += buf->len;
#endif
    uint8_t frag = *(uint8_t *)(buf->data + 2);
    offset += 3;
#endif
#endif

    /*
     *
     * SOCKS5 UDP Request
     * +----+------+------+----------+----------+----------+
     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +----+------+------+----------+----------+----------+
     * | 2  |  1   |  1   | Variable |    2     | Variable |
     * +----+------+------+----------+----------+----------+
     *
     * SOCKS5 UDP Response
     * +----+------+------+----------+----------+----------+
     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +----+------+------+----------+----------+----------+
     * | 2  |  1   |  1   | Variable |    2     | Variable |
     * +----+------+------+----------+----------+----------+
     *
     * shadowsocks UDP Request (before encrypted)
     * +------+----------+----------+----------+
     * | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +------+----------+----------+----------+
     * |  1   | Variable |    2     | Variable |
     * +------+----------+----------+----------+
     *
     * shadowsocks UDP Response (before encrypted)
     * +------+----------+----------+----------+
     * | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +------+----------+----------+----------+
     * |  1   | Variable |    2     | Variable |
     * +------+----------+----------+----------+
     *
     * shadowsocks UDP Request and Response (after encrypted)
     * +-------+--------------+
     * |   IV  |    PAYLOAD   |
     * +-------+--------------+
     * | Fixed |   Variable   |
     * +-------+--------------+
     *
     */

#ifdef MODULE_REDIR
    char addr_header[512] = { 0 };
    int addr_header_len   = construct_udprelay_header(&dst_addr, addr_header);

    if (addr_header_len == 0) {
        LOGE("[udp] failed to parse tproxy addr");
        goto CLEAN_UP;
    }

    // reconstruct the buffer
    brealloc(buf, buf->len + addr_header_len, buf_size);
    memmove(buf->data + addr_header_len, buf->data, buf->len);
    memcpy(buf->data, addr_header, addr_header_len);
    buf->len += addr_header_len;

#elif MODULE_TUNNEL

    char addr_header[512] = { 0 };
    char *host            = server_ctx->tunnel_addr.host;
    char *port            = server_ctx->tunnel_addr.port;
    uint16_t port_num     = (uint16_t)atoi(port);
    uint16_t port_net_num = htons(port_num);
    int addr_header_len   = 0;

    struct cork_ip ip;
    if (cork_ip_init(&ip, host) != -1) {
        if (ip.version == 4) {
            // send as IPv4
            struct in_addr host_addr;
            memset(&host_addr, 0, sizeof(struct in_addr));
            int host_len = sizeof(struct in_addr);

            if (dns_pton(AF_INET, host, &host_addr) == -1) {
                FATAL("IP parser error");
            }
            addr_header[addr_header_len++] = 1;
            memcpy(addr_header + addr_header_len, &host_addr, host_len);
            addr_header_len += host_len;
        } else if (ip.version == 6) {
            // send as IPv6
            struct in6_addr host_addr;
            memset(&host_addr, 0, sizeof(struct in6_addr));
            int host_len = sizeof(struct in6_addr);

            if (dns_pton(AF_INET6, host, &host_addr) == -1) {
                FATAL("IP parser error");
            }
            addr_header[addr_header_len++] = 4;
            memcpy(addr_header + addr_header_len, &host_addr, host_len);
            addr_header_len += host_len;
        } else {
            FATAL("IP parser error");
        }
    } else {
        // send as domain
        int host_len = strlen(host);

        addr_header[addr_header_len++] = 3;
        addr_header[addr_header_len++] = host_len;
        memcpy(addr_header + addr_header_len, host, host_len);
        addr_header_len += host_len;
    }
    memcpy(addr_header + addr_header_len, &port_net_num, 2);
    addr_header_len += 2;

    // reconstruct the buffer
    brealloc(buf, buf->len + addr_header_len, buf_size);
    memmove(buf->data + addr_header_len, buf->data, buf->len);
    memcpy(buf->data, addr_header, addr_header_len);
    buf->len += addr_header_len;

#else

    char host[257] = { 0 };
    char port[64]  = { 0 };
    struct sockaddr_storage dst_addr;
    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));

    int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset,
                                                host, port, &dst_addr);
    if (addr_header_len == 0) {
        // error in parse header
        goto CLEAN_UP;
    }

    char *addr_header = buf->data + offset;
#endif

#ifdef MODULE_LOCAL
    char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr);
#else
    char *key = hash_key(dst_addr.ss_family, &src_addr);
#endif

    struct cache *conn_cache = server_ctx->conn_cache;

    remote_ctx_t *remote_ctx = NULL;
    cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx);

    if (remote_ctx != NULL) {
        if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) {
            remote_ctx = NULL;
        }
    }

    // reset the timer
    if (remote_ctx != NULL) {
        ev_timer_again(EV_A_ & remote_ctx->watcher);
    }

    if (remote_ctx == NULL) {
        if (verbose) {
#ifdef MODULE_REDIR
            char src[SS_ADDRSTRLEN];
            char dst[SS_ADDRSTRLEN];
            strcpy(src, get_addr_str((struct sockaddr *)&src_addr));
            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr));
            LOGI("[udp] cache miss: %s <-> %s", dst, src);
#else
            LOGI("[udp] cache miss: %s:%s <-> %s", host, port,
                 get_addr_str((struct sockaddr *)&src_addr));
#endif
        }
    } else {
        if (verbose) {
#ifdef MODULE_REDIR
            char src[SS_ADDRSTRLEN];
            char dst[SS_ADDRSTRLEN];
            strcpy(src, get_addr_str((struct sockaddr *)&src_addr));
            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr));
            LOGI("[udp] cache hit: %s <-> %s", dst, src);
#else
            LOGI("[udp] cache hit: %s:%s <-> %s", host, port,
                 get_addr_str((struct sockaddr *)&src_addr));
#endif
        }
    }

#ifdef MODULE_LOCAL

#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)
    if (frag) {
        LOGE("[udp] drop a message since frag is not 0, but %d", frag);
        goto CLEAN_UP;
    }
#endif

    const struct sockaddr *remote_addr = server_ctx->remote_addr;
    const int remote_addr_len          = server_ctx->remote_addr_len;

    if (remote_ctx == NULL) {
        // Bind to any port
        int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6);
        if (remotefd < 0) {
            ERROR("[udp] udprelay bind() error");
            goto CLEAN_UP;
        }
        setnonblocking(remotefd);

#ifdef SO_NOSIGPIPE
        set_nosigpipe(remotefd);
#endif
#ifdef IP_TOS
        // Set QoS flag
        int tos = 46;
        setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
#ifdef SET_INTERFACE
        if (server_ctx->iface) {
            if (setinterface(remotefd, server_ctx->iface) == -1)
                ERROR("setinterface");
        }
#endif

#ifdef __ANDROID__
        if (vpn) {
            if (protect_socket(remotefd) == -1) {
                ERROR("protect_socket");
                close(remotefd);
                goto CLEAN_UP;
            }
        }
#endif

        // Init remote_ctx
        remote_ctx                  = new_remote(remotefd, server_ctx);
        remote_ctx->src_addr        = src_addr;
        remote_ctx->af              = remote_addr->sa_family;
        remote_ctx->addr_header_len = addr_header_len;
        memcpy(remote_ctx->addr_header, addr_header, addr_header_len);

        // Add to conn cache
        cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);

        // Start remote io
        ev_io_start(EV_A_ & remote_ctx->io);
        ev_timer_start(EV_A_ & remote_ctx->watcher);
    }

    if (offset > 0) {
        buf->len -= offset;
        memmove(buf->data, buf->data + offset, buf->len);
    }

    int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size);

    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }

    if (buf->len > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_sendto fragmentation");
        }
    }

    int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len);

    if (s == -1) {
        ERROR("[udp] server_recv_sendto");
    }

#else

    int cache_hit  = 0;
    int need_query = 0;

    if (buf->len - addr_header_len > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_sendto fragmentation");
        }
    }

    if (remote_ctx != NULL) {
        cache_hit = 1;
        // detect destination mismatch
        if (remote_ctx->addr_header_len != addr_header_len
            || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) {
            if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) {
                need_query = 1;
            }
        } else {
            memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage));
        }
    } else {
        if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) {
            int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6);
            if (remotefd != -1) {
                setnonblocking(remotefd);
#ifdef SO_BROADCAST
                set_broadcast(remotefd);
#endif
#ifdef SO_NOSIGPIPE
                set_nosigpipe(remotefd);
#endif
#ifdef IP_TOS
                // Set QoS flag
                int tos = 46;
                setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
#ifdef SET_INTERFACE
                if (server_ctx->iface) {
                    if (setinterface(remotefd, server_ctx->iface) == -1)
                        ERROR("setinterface");
                }
#endif
                remote_ctx                  = new_remote(remotefd, server_ctx);
                remote_ctx->src_addr        = src_addr;
                remote_ctx->server_ctx      = server_ctx;
                remote_ctx->addr_header_len = addr_header_len;
                memcpy(remote_ctx->addr_header, addr_header, addr_header_len);
                memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage));
            } else {
                ERROR("[udp] bind() error");
                goto CLEAN_UP;
            }
        }
    }

    if (remote_ctx != NULL && !need_query) {
        size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);
        int s           = sendto(remote_ctx->fd, buf->data + addr_header_len,
                                 buf->len - addr_header_len, 0,
                                 (struct sockaddr *)&dst_addr, addr_len);

        if (s == -1) {
            ERROR("[udp] sendto_remote");
            if (!cache_hit) {
                close_and_free_remote(EV_A_ remote_ctx);
            }
        } else {
            if (!cache_hit) {
                // Add to conn cache
                remote_ctx->af = dst_addr.ss_family;
                char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr);
                cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);

                ev_io_start(EV_A_ & remote_ctx->io);
                ev_timer_start(EV_A_ & remote_ctx->watcher);
            }
        }
    } else {
        struct addrinfo hints;
        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family   = AF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = IPPROTO_UDP;

        struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len,
                                                    buf->len - addr_header_len);
        query_ctx->server_ctx      = server_ctx;
        query_ctx->addr_header_len = addr_header_len;
        query_ctx->src_addr        = src_addr;
        memcpy(query_ctx->addr_header, addr_header, addr_header_len);

        if (need_query) {
            query_ctx->remote_ctx = remote_ctx;
        }

        struct ResolvQuery *query = resolv_query(host, query_resolve_cb,
                                                 NULL, query_ctx, htons(atoi(port)));
        if (query == NULL) {
            ERROR("[udp] unable to create DNS query");
            close_and_free_query(EV_A_ query_ctx);
            goto CLEAN_UP;
        }
        query_ctx->query = query;
    }
#endif

CLEAN_UP:
    bfree(buf);
    ss_free(buf);
}
示例#25
0
void *tcp_server(void *arg) {
    sock_t *s = (sock_t *) arg;
    int i,fd,try_to_read,received;
    struct tcp_client *clients,*client;
    struct pollfd *pfds = NULL;
    volatile nfds_t nfds;
    setnonblocking(s->socket);

    nfds = 1;
    pfds = mallocz_or_die(nfds * sizeof(struct pollfd));
    pfds->fd = s->socket;
    pfds->events = POLLIN;
    clients = NULL;
    RELAY_ATOMIC_AND( RECEIVED_STATS.active_connections, 0);
    int rc;
    for (;;) {
        rc = poll(pfds,nfds,CONFIG.polling_interval_ms);
        if (rc == -1) {
            if (rc == EINTR)
                continue;
            WARN_ERRNO("poll");
            goto out;
        }
        for (i = 0; i < nfds; i++) {
            if (!pfds[i].revents)
                continue;
            if (pfds[i].fd == s->socket) {
                fd = accept(s->socket, NULL, NULL);
                if (fd == -1) {
                    WARN_ERRNO("accept");
                    goto out;
                }
                setnonblocking(fd);
                RELAY_ATOMIC_INCREMENT( RECEIVED_STATS.active_connections, 1 );
                pfds = realloc_or_die(pfds, (nfds + 1) * sizeof(*pfds));
                clients = realloc_or_die(clients,(nfds + 1) * sizeof(*clients));

                clients[nfds].pos = 0;
                clients[nfds].buf = mallocz_or_die(ASYNC_BUFFER_SIZE);
//                WARN("[%d] CREATE %p fd: %d",i,clients[nfds].buf,fd);
                pfds[nfds].fd  = fd;
                pfds[nfds].events = POLLIN;
                pfds[nfds].revents = 0;
                nfds++;
            } else {
                client = &clients[i];
                try_to_read = ASYNC_BUFFER_SIZE - client->pos; // try to read as much as possible
                if (try_to_read <= 0) {
                    WARN("disconnecting, try to read: %d, pos: %d", try_to_read, client->pos);
                    goto disconnect;
                }
                received = recv(pfds[i].fd, client->buf + client->pos, try_to_read,0);
                if (received <= 0) {
                    if (received == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
                        continue;

                disconnect:
                    shutdown(pfds[i].fd,SHUT_RDWR);
                    close(pfds[i].fd);
//                    WARN("[%d] DESTROY %p %d %d fd: %d vs %d",i,client->buf,client->x,i,pfds[i].fd,client->fd);
                    free(client->buf);

                    // shft left
                    memcpy(pfds + i,pfds + i + 1, (nfds - i - 1) * sizeof(struct pollfd));
                    memcpy(clients + i,clients + i + 1, (nfds - i - 1) * sizeof(struct tcp_client));

                    nfds--;
                    pfds = realloc_or_die(pfds, nfds * sizeof(struct pollfd));
                    clients = realloc_or_die(clients, nfds * sizeof(struct tcp_client));
                    RELAY_ATOMIC_DECREMENT( RECEIVED_STATS.active_connections, 1 );
                    continue;
                }
                client->pos += received;

            try_to_consume_one_more:

                if (client->pos < EXPECTED_HEADER_SIZE)
                    continue;

                if (EXPECTED(client) > MAX_CHUNK_SIZE) {
                    WARN("received frame (%d) > MAX_CHUNK_SIZE(%d)",EXPECTED(client),MAX_CHUNK_SIZE);
                    goto disconnect;
                }
                if (client->pos >= EXPECTED(client) + EXPECTED_HEADER_SIZE) {
                    buf_to_blob_enqueue(client->buf,EXPECTED(client));

                    client->pos -= EXPECTED(client) + EXPECTED_HEADER_SIZE;
                    if (client->pos < 0) {
                        WARN("BAD PACKET wrong 'next' position(< 0) pos: %d expected packet size:%d header_size: %d",
                             client->pos, EXPECTED(client),EXPECTED_HEADER_SIZE);
                        goto disconnect;
                    }
                    if (client->pos > 0) {
                        // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                                                                     ^ pos(12)
                        // after we remove the first packet + header it becomes:
                        // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                           ^ pos (5)
                        // and then we copy from header + data, to position 0, 5 bytes
                        //
                        // [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                           ^ pos (5)
                        memmove(client->buf,
                                client->buf + EXPECTED_HEADER_SIZE + EXPECTED(client),
                                client->pos);
                        if (client->pos >= EXPECTED_HEADER_SIZE)
                            goto try_to_consume_one_more;
                    }
                }
            }
        }
    }
out:
    for (i = 0; i < nfds; i++) {
        if (pfds[i].fd != s->socket)
            free(clients[i].buf);
        shutdown(pfds[i].fd, SHUT_RDWR);
        close(pfds[i].fd);
    }
    free(pfds);
    free(clients);
    set_aborted();
    pthread_exit(NULL);
}
示例#26
0
static void
query_resolve_cb(struct sockaddr *addr, void *data)
{
    struct query_ctx *query_ctx = (struct query_ctx *)data;
    struct ev_loop *loop        = query_ctx->server_ctx->loop;

    if (verbose) {
        LOGI("[udp] udns resolved");
    }

    query_ctx->query = NULL;

    if (addr == NULL) {
        LOGE("[udp] udns returned an error");
    } else {
        remote_ctx_t *remote_ctx = query_ctx->remote_ctx;
        int cache_hit            = 0;

        // Lookup in the conn cache
        if (remote_ctx == NULL) {
            char *key = hash_key(AF_UNSPEC, &query_ctx->src_addr);
            cache_lookup(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx);
        }

        if (remote_ctx == NULL) {
            int remotefd = create_remote_socket(addr->sa_family == AF_INET6);
            if (remotefd != -1) {
                setnonblocking(remotefd);
#ifdef SO_BROADCAST
                set_broadcast(remotefd);
#endif
#ifdef SO_NOSIGPIPE
                set_nosigpipe(remotefd);
#endif
#ifdef IP_TOS
                // Set QoS flag
                int tos = 46;
                setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
#ifdef SET_INTERFACE
                if (query_ctx->server_ctx->iface) {
                    if (setinterface(remotefd, query_ctx->server_ctx->iface) == -1)
                        ERROR("setinterface");
                }
#endif
                remote_ctx                  = new_remote(remotefd, query_ctx->server_ctx);
                remote_ctx->src_addr        = query_ctx->src_addr;
                remote_ctx->server_ctx      = query_ctx->server_ctx;
                remote_ctx->addr_header_len = query_ctx->addr_header_len;
                memcpy(remote_ctx->addr_header, query_ctx->addr_header,
                       query_ctx->addr_header_len);
            } else {
                ERROR("[udp] bind() error");
            }
        } else {
            cache_hit = 1;
        }

        if (remote_ctx != NULL) {
            memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_storage));

            size_t addr_len = get_sockaddr_len(addr);
            int s           = sendto(remote_ctx->fd, query_ctx->buf->data, query_ctx->buf->len,
                                     0, addr, addr_len);

            if (s == -1) {
                ERROR("[udp] sendto_remote");
                if (!cache_hit) {
                    close_and_free_remote(EV_A_ remote_ctx);
                }
            } else {
                if (!cache_hit) {
                    // Add to conn cache
                    char *key = hash_key(AF_UNSPEC, &remote_ctx->src_addr);
                    cache_insert(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);
                    ev_io_start(EV_A_ & remote_ctx->io);
                    ev_timer_start(EV_A_ & remote_ctx->watcher);
                }
            }
        }
    }

    // clean up
    close_and_free_query(EV_A_ query_ctx);
}
示例#27
0
int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
        return 1;
    }
    const char* ip = argv[1];
    int port = atoi( argv[2] );

    int ret = 0;
    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 );

    listenfd = socket( PF_INET, SOCK_STREAM, 0 );
    assert( listenfd >= 0 );

    ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
    assert( ret != -1 );

    ret = listen( listenfd, 5 );
    assert( ret != -1 );

    for( int i = 0; i < PROCESS_COUNT; ++i )
    {
        ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sub_process[i].pipefd );
        assert( ret != -1 );
        sub_process[i].pid = fork();
        if( sub_process[i].pid < 0 )
        {
            continue;
        }
        else if( sub_process[i].pid > 0 )
        {
            close( sub_process[i].pipefd[1] );
            setnonblocking( sub_process[i].pipefd[0] );
            continue;
        }
        else
        {
            close( sub_process[i].pipefd[0] );
            setnonblocking( sub_process[i].pipefd[1] );
            run_child( i );
            exit( 0 );
        }
    }

    epoll_event events[ MAX_EVENT_NUMBER ];
    epollfd = epoll_create( 5 );
    assert( epollfd != -1 );
    addfd( epollfd, listenfd );

    ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sig_pipefd );
    assert( ret != -1 );
    setnonblocking( sig_pipefd[1] );
    addfd( epollfd, sig_pipefd[0] );

    addsig( SIGCHLD, sig_handler );
    addsig( SIGTERM, sig_handler );
    addsig( SIGINT, sig_handler );
    addsig( SIGPIPE, SIG_IGN );
    bool stop_server = false;
    int sub_process_counter = 0;

    while( !stop_server )
    {
        int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
        if ( ( number < 0 ) && ( errno != EINTR ) )
        {
            printf( "epoll failure\n" );
            break;
        }

        for ( int i = 0; i < number; i++ )
        {
            int sockfd = events[i].data.fd;
            if( sockfd == listenfd )
            {
                int new_conn = 1;
                send( sub_process[sub_process_counter++].pipefd[0], ( char* )&new_conn, sizeof( new_conn ), 0 );
                printf( "send request to child %d\n", sub_process_counter-1 );
                sub_process_counter %= PROCESS_COUNT;
            }
            else if( ( sockfd == sig_pipefd[0] ) && ( events[i].events & EPOLLIN ) )
            {
                int sig;
                char signals[1024];
                ret = recv( sig_pipefd[0], signals, sizeof( signals ), 0 );
                if( ret == -1 )
                {
                    continue;
                }
                else if( ret == 0 )
                {
                    continue;
                }
                else
                {
                    for( int i = 0; i < ret; ++i )
                    {
                        switch( signals[i] )
                        {
                            case SIGCHLD:
                            {
	                        pid_t pid;
	                        int stat;
	                        while ( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 )
                                {
                                    for( int i = 0; i < PROCESS_COUNT; ++i )
                                    {
                                        if( sub_process[i].pid == pid )
                                        {
                                            close( sub_process[i].pipefd[0] );
                                            sub_process[i].pid = -1;
                                        }
                                    }
                                }
                                stop_server = true;
                                for( int i = 0; i < PROCESS_COUNT; ++i )
                                {
                                    if( sub_process[i].pid != -1 )
                                    {
                                        stop_server = false;
                                    }
                                }
                                break;
                            }
                            case SIGTERM:
                            case SIGINT:
                            {
                                printf( "kill all the clild now\n" );
                                for( int i = 0; i < PROCESS_COUNT; ++i )
                                {
                                    int pid = sub_process[i].pid;
                                    kill( pid, SIGTERM );
                                }
                                break;
                            }
                            default:
                            {
                                break;
                            }
                        }
                    }
                }
            }
            else 
            {
                continue;
            }
        }
    }

    del_resource();
    return 0;
}
示例#28
0
void
test_process_events_and_timers(test_connection_t *lc)
{
    struct epoll_event ev;
    int nfds;
        //等待epoll事件的发生

        nfds=epoll_wait(epfd,event_list, nevents,500);
	int err = (nfds == -1) ? errno : 0;
	if(err){
		if (err == EINTR) {
			if(t_event_timer_alarm){
				t_event_timer_alarm=0;
				return;
			}
		}
		perror("epoll_wait() failed");
		return;
	}
	if (nfds == 0) {
		//printf("epoll_wait() returned no events without timeout\n");
		return;
	}
        //处理所发生的所有事件
        for(int i=0;i<nfds;++i)
        {

	    test_connection_t *c=event_list[i].data.ptr;
	    c = (test_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

            if(c->fd==lc->fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
            {
		struct sockaddr_in in_addr;
                socklen_t in_len;
                int connfd = accept4(lc->fd,(struct sockaddr *)&in_addr, &in_len,SOCK_NONBLOCK);
                if(connfd<0){
                    perror("connfd<0");
                    //exit(1);
                }
                setnonblocking(connfd);

                char *str = inet_ntoa(in_addr.sin_addr);
                printf( "%d  accapt a connection from %s \n",event_list[i].events, str);
                //设置用于读操作的文件描述符
                //设置用于注测的读操作事件

                ev.events=EPOLLIN|EPOLLET;
                //ev.events=EPOLLIN;
		test_connection_t *cnew=(test_connection_t*)calloc(1,sizeof(test_connection_t));
		cnew->hand=init_hand;
		cnew->fd=connfd;
		cnew->current=0;

		ev.data.ptr=cnew;
                //注册ev

                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
            }
            else if((event_list[i].events&EPOLLIN) || (event_list[i].events&EPOLLOUT))//如果是已经连接的用户,并且收到数据,那么进行读入。
            {
                printf("EPOLLET | EPOLLOUT: %d\n",event_list[i].events);
		if(28 == event_list[i].events){
			perror("28");
			printf("%d\n",errno);
			//if(errno == ECONNRESET) return;//Connection reset by peer
			//else
				printf("epoll event: 28, errno: %d\n",errno);
			close(c->fd);
			free(c);
			return;
		}
		c->ev=&event_list[i];
		c->hand(c);

            }
            else { // 如果有数据发送
		perror("unknow event: ");
            }
        }
}
示例#29
0
int main()
{
	struct sockaddr_in server_addr;
	bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(8000);

	int server_socket = socket(PF_INET,SOCK_STREAM,0);
    if( server_socket < 0)
    {
        printf("Create Socket Failed!");
        exit(1);
    }
	int opt =1;
	setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
    {
        perror("Server Bind Port 53 Failed: "); 
        exit(1);
    }
	
	if ( listen(server_socket, 5) )
    {
        printf("Server Listen Failed!"); 
        exit(1);
    }
	pserver_context pcontext = (pserver_context) calloc(1,sizeof(server_context));
	pcontext->client_context_lt = gdsl_list_alloc("client socket",NULL,NULL);
	
	pcontext->kdpfd = epoll_create(5);
	pthread_attr_t attr;
    pthread_t threadId;
	pthread_attr_init(&attr); 
	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 
    /* 设置线程为分离属性*/ 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if(pthread_create(&threadId,&attr,message_handler,(void*)pcontext))
    { 
		perror("pthread_creat error!"); 
        exit(-1); 
	}
	
	while(1)
	{
		struct sockaddr_in client_addr;
        socklen_t length = sizeof(client_addr);
		printf("waiting for connection...\n");
		int new_client_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
        if ( new_client_socket < 0)
        {
            printf("Server Accept Failed!\n");
            /*break;*/
			continue;
        }
		setnonblocking(new_client_socket);
		pconnect_context pconnection = calloc(1,sizeof(connect_context));
		if( pconnection == NULL )
		{
			perror("calloc event fail: ");
			close(new_client_socket);
			continue;
		}
		pconnection->ev.events = EPOLLIN;
		pconnection->session.socket = new_client_socket;
		pconnection->socket = new_client_socket;
		pconnection->ev.data.ptr = (void*)pconnection;/*(void*)&(pconnection->session);*/

		if(epoll_ctl(pcontext->kdpfd, EPOLL_CTL_ADD, new_client_socket,&(pconnection->ev))<0)
		{
			perror("epoll_ctl fail: ");
			close(new_client_socket);
			continue;	
		}
		gdsl_list_insert_tail( pcontext->client_context_lt,(int*)(size_t)new_client_socket);
	}
	return 0;
}
示例#30
0
文件: sntsd.c 项目: theatrus/snts
int main(int argc, char *argv[]) {
         char scrap[500],bindto[128];
         struct hostent *myself;
         struct itimerval timers;
         struct itimerval oldtimers;
	 struct sigaction sig;
         struct timeval timeout;  /* Timeout for select */
         int readsocks;       /* Number of sockets ready for reading */
         int i, i2, addr_len;	
	 int sock;
	 int reuse_addr = 1, bind_to_other = 0;
	 int broadcast_enable = 1; /* sort of senseless without */
	 long utime;
	
	/* Suck in command line options */
	if (argc > 1) {
		/* something was passed */
		for(i=1;i<argc;i++) {
			if (strcmp("-g", argv[i]) == 0) {
				sscanf(argv[i+1], "%d", &groupid);
				if (groupid < 1) {
					printf("sntsd: group must be > 0\n");
					exit(1);
				}
				i++;  /* so the for isn't called and the # considered a bad option */
			} else if (strcmp("-a", argv[i]) == 0) {
				sscanf(argv[i+1], "%s", &bindto);
				bind_to_other=1;
				if (strlen(bindto)>16) { /* Just checking for too long input */
					printf("sntsd: IP address is too long\n");
					exit(1);
				}
				i++;
                        } else if (strcmp("-i", argv[i]) == 0) {

				i++;
			} else {
				printf("sntsd: bad command line option %s.\n", argv[i]);
				exit(1); 	
			}
		}
	}
	
	/* this is to allow for multiple hosts on the same group.  If twice the interval is reached, the host is assumed down and this host starts broadcasting */
	bcast_server_interval = bcast_interval * 2;
	
	
	
	/* Get socket */
	
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == -1) {
		perror("socket");
		exit(1);
	}
	
	/* So that we can re-bind to it without TIME_WAIT problems */
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr));
	/* Broadcast enable */
	
	setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable));
	
	/* Set socket to non-blocking with our setnonblocking routine */
        setnonblocking(sock);
        memset((char *) &server_address, 0, sizeof(server_address));
        server_address.sin_family = AF_INET;
	
        if (bind_to_other == 0) server_address.sin_addr.s_addr = htonl(INADDR_ANY); else
    				server_address.sin_addr.s_addr = inet_addr(bindto);
	
	server_address.sin_port = htons(SNTSPORT);
        if (bind(sock, (struct sockaddr *) &server_address, sizeof(server_address)) < 0 ) {
                 perror("bind");
                 close(sock);
                 exit(1);
        }
        /* Daemon ourselves */
	daemon(1,1);
	
	//signal(SIGALRM, timebcast);
	/* Linux doesn't like "signal" :( */

	sig.sa_handler = &timebcast;
	sig.sa_flags = SA_RESTART;
	sigaction(SIGALRM, &sig, NULL);

         oldtimers.it_interval.tv_sec = bcast_interval;
         oldtimers.it_value.tv_sec = bcast_interval;
         timers.it_interval.tv_sec = bcast_interval;
         timers.it_value.tv_sec = bcast_interval;


         if(setitimer(ITIMER_REAL, &timers, NULL)) {
	   printf("Failure setting timer (blame Linux)\n");
	   exit(1);
	 }

	/* Get info on myself or use passed IP address */
      if (bind_to_other == 0) { /* Lookup my IP  */
	
 	i = gethostname(scrap, sizeof(scrap));
	myself = gethostbyname(scrap);
        if (myself == NULL) {
                syslog(LOG_ERR, "Can't lookup my own IP - quiting");
                exit(1);
        }
       sprintf(myip, "%s", inet_ntoa(*((struct in_addr *)myself->h_addr)));

      } else sprintf(myip,"%s",bindto); /* Use specified IP */
      
	/* syslog starting message */
	sprintf(scrap, "sntsd version %s proto version %s starting up", VERSION, PROTOVERSION);
	syslog(LOG_NOTICE, scrap);
	sprintf(scrap, "starting using groupid: %d", groupid);
	syslog(LOG_NOTICE, scrap);
	sprintf(scrap, "using IP: %s",myip);
	syslog(LOG_NOTICE, scrap);
	
	udp_socket = sock;
	bcast.sin_family = AF_INET;
	bcast.sin_addr.s_addr = inet_addr(BCAST_ADDR);
	bcast.sin_port = htons(SNTSPORT);
	
	time(&starttime);
		
	/* pick random sequence number */

#ifdef COMPAT_SRANDOM
	time(&utime);
	srandom(utime);
#else
	srandomdev();	/* init using /dev/urandom on systems which have it */
#endif
	picknewsequence();
	
	
	/* Send 'master coming up' message */
	sprintf(outmessage, "snts %s %d hostup", PROTOVERSION, groupid);

	sendto(udp_socket, outmessage, sizeof(outmessage), 0, (struct sockaddr *)&bcast, sizeof(bcast));
	
	
	while (1) {
	/* i=recvfrom(udp_socket, message, sizeof(message), 0, (struct sockaddr *)&their_addr, &addr_len); */
		timeout.tv_sec = 10;
	        timeout.tv_usec = 0;
	        build_select_list();
	        readsocks = select(udp_socket+1, &socks, (fd_set *) 0, (fd_set *) 0, &timeout);

	        if (readsocks == 0) {
			
                } else if (readsocks > 0) {
		        i=recvfrom(udp_socket, message, sizeof(message), 0, (struct sockaddr *)&their_addr, &addr_len);
		
		
		        message[i] = '\0';
		
		        process_message();
		 }
}
}