Esempio n. 1
0
int
main (void)
{
 
	int listenfd;
	ev_io io;
	struct ev_loop *loop = EV_DEFAULT;
	
	signal(SIGPIPE, SIG_IGN);
	signal(SIGABRT, SIG_IGN);
	
	listenfd = create_and_bind("127.0.0.1", "10001");
	
	setnonblocking(listenfd);
	
	if (listenfd < 0)
	{
		printf("listen sock error\n");
	}
	
	if (listen(listenfd, 128) == -1){
		printf("listen error\n");
	}
	
	ev_io_init(&io, accept_cb, listenfd, EV_READ);
	ev_io_start(loop, &io);
	
	ev_run(loop, 0);
	
 return 0;
}
Esempio n. 2
0
int main(int argc, char argv[])
{
    const char *ip = "127.0.0.1";
    const char *port = "2016";

    int sfd = create_and_bind(ip, port);
    if (sfd == -1)
    {
        return -1;
    }

    struct event_base *base = event_init();
    if (base == NULL)
    {
        return -1;
    }


    struct event ev;
    event_set(&ev, sfd, EV_READ|EV_PERSIST, accept_cb, NULL);
    event_add(&ev, NULL);

    event_base_dispatch(base);
    return 0;
}
Esempio n. 3
0
int create_send_socket(void){
	datafd = create_and_bind(LOCAL_IP, LOCAL_DATA_PORT);
	if(datafd < 0)
	{
		return datafd;
	}
	//lenfd = create_and_bind(LOCAL_IP, LOCAL_LEN_PORT);
	//if(lenfd < 0)
	//	return lenfd;
	return 1;
}
Esempio n. 4
0
int main (int argc, char *argv[])
{
    int sfd, s;
    int efd;
    struct epoll_event event;
    struct epoll_event events[MAXEVENTS];

    if (argc < 2){
        fprintf (stderr, "Usage: %s [port]\n", basename(argv[0]));
        exit (EXIT_FAILURE);
    }

    //  const char *ip = argv[1];
    //  int port = atoi(argv[2]);
    sfd = create_and_bind (argv[1]);
    if (sfd == -1) abort ();

    //listen for connection coming
    s = listen (sfd, SOMAXCONN);
    if (s == -1) {
        perror ("listen");
        abort ();
    }

    //create a epoll object
    efd = epoll_create1 (0);
    if (efd == -1) {
        perror ("epoll_create");
        abort ();
    }

    //add the listen socket to the event poll
    addfd(efd, sfd, 1);

    while(1)
    {
        int ret = epoll_wait(efd, events, MAXEVENTS, -1);
        if(ret < 0){
            printf("epoll wait failture..\n");
            break;
        }
        
        //et(events, ret, efd, sfd);
        lt(events, ret, efd, sfd);
    }


    close (sfd);

    return EXIT_SUCCESS;
}
Esempio n. 5
0
void main(int argc, char *argv[])
{
	
	// Create Socket
	int infd = create_and_bind("1234");

	// Bind Socket
	int outfd = bind_socket(infd)
	
	// Listen on Socket
	int r = listen(outfd)
	
	// Accept Socket	

}
Esempio n. 6
0
int main(int argc, char *argv[])
{
	if(argc <= 1)
	{
		printf("Usage: %s port\n", basename(argv[0]));
		return -1;
	}

	int ret = 0;
	int sfd = create_and_bind(argv[1]);
	if(sfd < 0) {printf("create_and_bind failed.\n"); return -2;}

	listen(sfd, 5);

	struct sockaddr_in client_address;
	socklen_t client_addrlength = sizeof( client_address );
	int connfd = accept( sfd, ( struct sockaddr* )&client_address, &client_addrlength );
	if ( connfd < 0 )
	{
		printf( "errno is: %d\n", errno );
		close( sfd);
		return -3;
	}

	char buff[1024];
	struct pollfd pfd[FDNUM];
	pfd[0].fd = connfd;
	pfd[0].events = POLLIN | POLLPRI;

	while(1)
	{
		memset( buff, '\0', sizeof( buff ) );
		int n = poll(pfd, 1, -1);
		printf("poll get %d fd ready.\n");

		if(pfd[0].revents & POLLIN)
		{
			int nr = read(connfd, buff, sizeof(buff));
			if(nr > 0)
			{
				printf("get %d bytes data: %s\n", nr, buff);
			}
			else if(nr == 0)
			{
				// client close the connection
				printf("client close the connection.\n");
				break;
			}
			else
			{
				// error occures
				perror("read");
				ret = -4;
				break;
			}
		}

		if(pfd[0].revents & POLLPRI)
		{
			int nr = recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
			if(nr < 0)
			{
				perror("recv");
				ret = -5;
				break;
			}
			printf("recv %d bytes OOB data: %s\n", nr, buff);
		}

	}


	close(sfd);

	return ret;
}
Esempio n. 7
0
int main(void)
{
    char in[3000],  sent[500], code[50], file[200], mime[100], moved[200], length[100], auth[200], auth_dir[500], start[100], end[100];
    char *result=NULL, *hostname, *hostnamef, *lines, *ext=NULL, *extf, *auth_dirf=NULL, *authf=NULL, *rangetmp;
    int buffer_chunks;
    long filesize, range=0;

    get_conf();
    create_and_bind();

    //Important stuff happens here.

    while(1) {
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
            perror("accept");
            continue;
        }

        if (!fork()) {
            close(sockfd);
        if (read(new_fd, in, 3000) == -1) {
    	perror("recive");
        } else {
    	lines = strtok(in, "\n\r");
    	do {
    	    hostname = strtok(NULL, "\n\r");
    		if (hostname[0] == 'R' && hostname[1] == 'a' && hostname[2] == 'n' && hostname[3] == 'g' && hostname[4] == 'e') {
    			rangetmp = hostname;
    			strcpy(code, "206 Partial Content");
    		}
    	} while (hostname[0] != 'H' || hostname[1] != 'o' || hostname[2] != 's' || hostname[3] != 't');
    	hostnamef = strtok(hostname, " ");
    	hostnamef = strtok(NULL, " ");
    	result = strtok(lines, " ");
    	result = strtok(NULL, " ");
    	if (strcmp(code, "206 Partial Content") == 0 ) {
    		rangetmp = strtok(strpbrk(rangetmp, "="), "=-");
    		range = atoi(rangetmp);
    	}

    	strcpy(file, result);
    	if (opendir(file)){
    	    if (file[strlen(file)-1] == '/'){
                    strcat(file, "/index.html");
    		openfile=fopen (file, "r");
                        if (openfile){
                            strcpy(code, "200 OK");
                        } else {
    		    //Here should be some kind of directory listing
    		    strcpy(file, "/404.html");
    		    openfile = fopen (file, "r");
    		    strcpy(code, "404 Not Found");
    		}
    	    } else {
    		strcpy(code, "301 Moved Permanently");
    		strcpy(moved, "Location: http://");
    		strcat(moved, hostnamef);
    		strcat(moved, result);
    		strcat(moved, "/");
    	    }
    	} else {
    	    openfile=fopen (file, "rb");
                if (openfile){
    		if (strlen(code) < 1) {
                    	strcpy (code, "200 OK");
    		}
                } else {
    		strcpy(file, "/404.html");
    		openfile = fopen (file, "r");
                    strcpy(code, "404 Not Found");
                }
                }
        }
        if (strcmp(code, "301 Moved Permanently") != 0){
    	fseek (openfile , 0 , SEEK_END);
                filesize = ftell (openfile);
        	rewind (openfile);
    	if (range > 0) {
    		sprintf(end, "%d", filesize);
    		filesize = filesize - range;
    		sprintf(start, "%d", range);
    		fseek (openfile , range , SEEK_SET);
    	}
    	buffer_chunks = filesize/1048576;
    	if(filesize%1048576 > 0){
    		buffer_chunks++;
    	}
    	sprintf(length, "%d", filesize);
    	buffer_counter = 0;
    	buffer = (char*) malloc (sizeof(char)*1048576);
        }

        if (strcmp(code, "404 Not Found") != 0 && strcmp(code, "301 Moved Permanently") !=0){
    	ext = strtok(file, ".");
            while(ext != NULL){
    	    ext = strtok(NULL, ".");
        	    if (ext != NULL){
    		extf = ext;
    	    }
    	}
        } else {
    	extf="html";
        }

        /* Maybe I should read mime types from a file. At least for now, add here what you need.*/

        if (strcmp(extf, "html") == 0){
    	strcpy (mime, "text/html");
            } else if(strcmp(extf, "jpg") == 0){
    	strcpy (mime, "image/jpeg");
        } else if(strcmp(extf, "gif") == 0){
    	strcpy (mime, "image/gif");
        } else if(strcmp(extf, "css") == 0){
    	strcpy (mime, "text/css");
        } else {
    	strcpy(mime, "application/octet-stream");
        }

        strcpy(sent, "HTTP/1.1 ");
        strcat(sent, code);
        strcat(sent, "\nServer: qshttpd 0.3.0\n");
        if(strcmp(code, "301 Moved Permanently") == 0){
    	strcat(sent, moved);
    	strcat(sent, "\n");
        }

        strcat(sent, "Content-Length: ");
        if(strcmp(code, "301 Moved Permanently") != 0){
            strcat(sent, length);
        } else {
    	strcat(sent, "0");
        }
        if(strcmp(code, "206 Partial Content") == 0) {
    	strcat(sent, "\nContent-Range: bytes ");
    	strcat(sent, start);
    	strcat(sent, "-");
    	strcat(sent, end);
    	strcat(sent, "/");
    	strcat(sent, end);
    }
        strcat(sent, "\nConnection: close\nContent-Type: ");
        strcat(sent, mime);
        strcat(sent, "; charset=");
        strcat(sent, charset);
        strcat(sent, "\n\n");
        write(new_fd, sent, strlen(sent));
    	while (buffer_counter < buffer_chunks) {
    		read_chunk();
    		write(new_fd, buffer, 1048576);
    	}
        close(new_fd);
            exit(0);
        }
        close(new_fd);
    }
    return 0;
}
Esempio n. 8
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 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;
    char *iface = NULL;

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

    ss_addr_t tunnel_addr = { .host = NULL, .port = NULL };
    char *tunnel_addr_str = NULL;

    opterr = 0;

    USE_TTY();

#ifdef ANDROID
    while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUvV")) != -1) {
#else
    while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUv")) != -1) {
#endif
        switch (c) {
        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 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'L':
            tunnel_addr_str = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'v':
            verbose = 1;
            break;
#ifdef ANDROID
        case 'V':
            vpn = 1;
            break;
#endif
        }
    }

    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 (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

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

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

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

    // parse tunnel addr
    parse_addr(tunnel_addr_str, &tunnel_addr);

    if (tunnel_addr.port == NULL) {
        FATAL("tunnel port is not defined");
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

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

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.tunnel_addr = tunnel_addr;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *) * remote_num);
    for (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 = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd < 0) {
            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]),
                      tunnel_addr, m, listen_ctx.timeout, iface);
    }

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

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

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    ev_run(loop, 0);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    return 0;
}
int main(int argc, char *argv[])
{
  int sfd, s;
  int efd;
  int so_rcvbuf = 0;
  int verbose = 0;
  struct epoll_event event;
  struct epoll_event *events;
  struct edata {
    int fd;
    int content_length;
    int content_offset;
    char *header_buf;
    int header_off;
    int header_max;
  };

  if (argc < 2 || argc > 3)
    {
      fprintf(stderr, "Usage: %s [port] [rcvbuf]\n", argv[0]);
      exit(EXIT_FAILURE);
    }

  sfd = create_and_bind(argv[1]);
  if (sfd == -1)
    abort();

  if (argc == 3)
      so_rcvbuf = atoi(argv[2]);

  s = make_socket_non_blocking(sfd);
  if (s == -1)
    abort();

  s = listen(sfd, SOMAXCONN);
  if (s == -1)
    {
      perror("listen");
      abort();
    }

  efd = epoll_create1(0);
  if (efd == -1)
    {
      perror("epoll_create");
      abort();
    }

  struct edata *ed = malloc(sizeof(*ed));
  ed->fd = sfd;
  ed->header_buf = 0;

  event.data.ptr = ed;
  event.events = EPOLLIN | EPOLLET;
  s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
  if (s == -1)
    {
      perror("epoll_ctl");
      abort();
    }

  /* Buffer where events are returned */
  events = calloc(MAXEVENTS, sizeof event);

  /* The event loop */
  while (1)
    {
      int n, i;

      n = epoll_wait(efd, events, MAXEVENTS, -1);
      for (i = 0; i < n; i++)
	{
	  struct edata *ed = events[i].data.ptr;
	  int fd = ed->fd;

	  if ((events[i].events & EPOLLERR) ||
              (events[i].events & EPOLLHUP) ||
              (!(events[i].events & EPOLLIN)))
	    {
	      fprintf(stderr, "epoll error\n");

	      s = epoll_ctl(efd, EPOLL_CTL_DEL, fd, 0);
	      if (s == -1)
		{
		  perror("epoll_ctl");
		  abort();
		}
	      close(fd);
	      free(ed);
	      continue;
	    }

	  else if (sfd == fd)
	    {
              while (1)
                {
                  struct sockaddr in_addr;
                  socklen_t in_len;
                  int infd;
                  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                  in_len = sizeof in_addr;
                  infd = accept(sfd, &in_addr, &in_len);
                  if (infd == -1)
                    {
                      if ((errno == EAGAIN) ||
                          (errno == EWOULDBLOCK))
                        {
                          break;
                        }
                      else
                        {
                          perror("accept");
                          break;
                        }
                    }

                  s = getnameinfo(&in_addr, in_len,
				  hbuf, sizeof hbuf,
				  sbuf, sizeof sbuf,
				  NI_NUMERICHOST | NI_NUMERICSERV);
                  if (s == 0)
                    {
		      if (verbose)
			printf("Accepted connection on descriptor %d "
			       "(host=%s, port=%s)\n", infd, hbuf, sbuf);
                    }

		  if (so_rcvbuf)
		    if (setsockopt(infd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf,
				   sizeof(so_rcvbuf)))
		      {
			perror("setsocopt");
			abort();
		      }
                  s = make_socket_non_blocking(infd);
                  if (s == -1)
                    abort();
		  ed = malloc(sizeof(*ed));
		  ed->fd = infd;
		  ed->content_length = -1;
		  ed->header_max = 999;
		  ed->header_buf = malloc(ed->header_max + 1);
		  ed->header_off = 0;
		  event.data.ptr = ed;
                  event.events = EPOLLIN | EPOLLET;
                  s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
                  if (s == -1)
                    {
                      perror("epoll_ctl");
                      abort();
                    }
                }
              continue;
            }
          else
            {
              int done = 0;
              while (1)
                {
                  ssize_t count;
                  char buf[32768];

		  if (ed->content_length == -1)
		    {
		      count = read(fd, ed->header_buf + ed->header_off,
				   ed->header_max - ed->header_off);

		    }
		  else
		    {
		      count = read(fd, buf, sizeof buf);
		    }
                  if (count == -1)
                    {
                      if (errno != EAGAIN)
                        {
                          perror("read");
                          done = 1;
                        }
                      break;
                    }
                  else if (count == 0)
                    {
                      done = 1;
                      break;
                    }
		  else
		    {
		      if (ed->content_length == -1)
			{
			  const char *cp2;
			  ed->header_off += count;
			  ed->header_buf[ed->header_off] = '\0';
			  cp2 = strstr(ed->header_buf, "\r\n\r\n");
			  if (cp2)
			    cp2 += 4;
			  else if (!cp2)
			    {
			      cp2 = strstr(ed->header_buf, "\n\n");
			      if (cp2)
				cp2 += 2;
			    }
			  if (cp2) /* complete header? */
			    {
			      const char *cp1 =
				strstr(ed->header_buf, "\nContent-Length:");
			      if (!cp1)
				cp1 = strstr(ed->header_buf, "\nContent-length:");
			      if (cp1 && cp1 < cp2)
				ed->content_length = atoi(cp1 + 16);
			      else
				ed->content_length = 0;
			      ed->content_offset = ed->header_off -
				(cp2 - ed->header_buf);

			      if (ed->content_offset == 0)
				{
				  if (strstr(ed->header_buf,
					     "\nExpect: 100-continue"))
				    {
				      char buf[64];
				      strcpy(buf, "HTTP/1.1 100 Continue\r\n\r\n");
				      write(fd, buf, strlen(buf));
				    }
				}
			      if (verbose)
				printf("complete header length=%d\n",
				       ed->content_length);
			    }
			  else
			    {
			      if (ed->header_off == ed->header_max)
				{
				  printf("Too big header\n");
				  done = 1;
				}
			    }
			}
		      else
			{
			  ed->content_offset += count;
			}
		      if (ed->content_length != -1 &&
			  ed->content_offset == ed->content_length)
			{
			  if (verbose)
			    printf("Got all content %d\n",
				   ed->content_length);
			  done = 1;
			}
		    }
                }

              if (done)
                {
		  if (verbose)
		    printf("Closing descriptor %d\n", fd);
		  char buf[1000];

		  strcpy(buf, "HTTP/1.0 200 OK\r\n"
			 "Content-Length: 0\r\n"
			 "Connection: Close\r\n"
			 "\r\n");
		  write(fd, buf, strlen(buf));

                  s = epoll_ctl(efd, EPOLL_CTL_DEL, fd, 0);
                  if (s == -1)
                    {
                      perror("epoll_ctl");
                      abort();
                    }
                  close(fd);
		  free(ed->header_buf);
		  free(ed);
                }
            }
        }
    }

  free(events);

  close(sfd);

  return EXIT_SUCCESS;
}
Esempio n. 10
0
int main(int argc, char **argv)
{
	int lfd, s, efd;
	struct epoll_event event;
	struct epoll_event *events;

	char path[MAX_LINE];
	int port;
	configuration(&port, path); 

	char port_str[6];
	bzero(port_str, 6);
	snprintf(port_str, 5, "%d", port);
	lfd=create_and_bind(port_str);
	if(lfd==-1) abort();

	s=listen(lfd, SOMAXCONN);
	if(s==-1)
	{
		perror("listen");
		abort();
	}

	efd=epoll_create1(0);
	if(efd==-1)
	{
		perror("epoll_create");
		abort();
	}
	addfd(efd, lfd, false);

	events=(struct epoll_event*)calloc(MAXEVENTS, sizeof(event));

	while(1)
	{
		int n, i;
		n=epoll_wait(efd, events, MAXEVENTS, -1);
		for(i=0; i<n; i++)
		{
			if ((events[i].events&EPOLLERR)||
				(events[i].events&EPOLLHUP)||
				(!(events[i].events&EPOLLIN)))
			{
				/* A error has occured on this fd, or the socket is not 
				 * ready for reading (why were we notified then?) */
				fprintf(stderr, "epoll error\n");
				close(events[i].data.fd);
				continue;
			}
			else if(lfd==events[i].data.fd)
			{
				/* We have a notification on the listening socket,
				 * which means one or more incoming connections. */
				while(1)
				{
					struct sockaddr in_addr;
					socklen_t in_len;
					int infd;
					char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

					in_len=sizeof(in_addr);
					infd=accept(lfd, &in_addr, &in_len);
					if(infd==-1)
					{
						if((errno==EAGAIN)||(errno==EWOULDBLOCK))
						{
							/* We have processed all incoming connections. */
							break;
						}
						else
						{
							perror("accept");
							break;
						}
					}
				
					s=getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST|NI_NUMERICSERV);

					if(s==0)
					{
						print("Accepted connnection on descriptor %d: (host=%s, port=%s)\n", infd, hbuf, sbuf);
					}

					/* Make the incoming socket non-blocking and 
					 * add it to the list of fds to monitor. */
					addfd(efd, infd, true); 
				}
				continue;
			}
			else
			{
				/* We have data on the fd waiting to be read. Read and display it. 
				 * We must read whatever data is available completely, as we are running 
				 * in edge-triggered mode and won't get a notification again for the same data. */
					pthread_t thread;
					args param;
					param.cfd=events[i].data.fd;
					param.efd=efd;
				//	pthread_create(&thread, NULL, worker, (void*)&param);
				 	worker((void*)&param);
			}	
		}
	}

	free(events);
	close(lfd);
	return EXIT_SUCCESS;
}
Esempio n. 11
0
int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    mode = profile.mode;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

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

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
    memset(storage, 0, sizeof(struct sockaddr_storage));
    if (get_sockaddr(remote_host, remote_port_str, storage, 1) == -1) {
        return -1;
    }

    // Setup proxy context
    struct ev_loop *loop = EV_DEFAULT;
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *));
    listen_ctx.remote_addr[0] = (struct sockaddr *)storage;
    listen_ctx.timeout = timeout;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        ERROR("bind()");
        return -1;
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        ERROR("listen()");
        return -1;
    }
    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("udprelay enabled");
        struct sockaddr *addr = (struct sockaddr *)storage;
        init_udprelay(local_addr, local_port_str, addr,
                      get_sockaddr_len(addr), m, timeout, NULL);
    }

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

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);
    close(listen_ctx.fd);

    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}
Esempio n. 12
0
int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    udprelay = profile.udp_relay;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

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

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        FATAL("bind()");
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        FATAL("listen()");
    }
    setnonblocking(listenfd);
    LOGD("server listening at port %s.", local_port_str);

    // Setup proxy context
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(ss_addr_t));
    listen_ctx.remote_addr[0].host = remote_host;
    listen_ctx.remote_addr[0].port = remote_port_str;
    listen_ctx.timeout = timeout;
    listen_ctx.fd = listenfd;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    struct ev_loop *loop = EV_DEFAULT;
    if (!loop) {
        FATAL("ev_loop error.");
    }
    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (udprelay) {
        LOGD("udprelay enabled.");
        init_udprelay(local_addr, local_port_str, remote_host, remote_port_str,
                      m, listen_ctx.timeout, NULL);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGD("closed nicely.");
    }

    // Clean up
    free_connections(loop);
    if (udprelay) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free(listen_ctx.remote_addr);
    close(listen_ctx.fd);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}
Esempio n. 13
0
int
main(int argc, char *argv[])
{
    int sfd, res, epoll, cnt, i, sd;
    struct epoll_event event, events[MAX_EVENTS];
    
    
    if (argc != 2) {
        perror("usage : port \n");
        exit(1);
    }
    
    sfd = create_and_bind(argv[1]);
    if (sfd == -1) {
        perror("error : cannot create socket!\n");
        exit(1);
    }
    
    res = make_socket_non_binding(sfd);
    if (res == -1) {
        perror("error : connot set flags!\n");
        exit(1);
    }
    
    res = listen(sfd, SOMAXCONN);
    if (res == -1) {
        perror("error : cannot listen!\n");
        exit(1);
    }
    
    epoll = epoll_create(1);
    if (epoll == -1) {
        perror("error : cannot create epoll!\n");
        exit(1);
    }
    
    event.events  = EPOLLIN | EPOLLOUT | EPOLLET;
    event.data.fd = sfd;
    res = epoll_ctl(epoll, EPOLL_CTL_ADD, sfd, &event);
    if (res == -1) {
        perror("error : can not add event to epoll!\n");
        exit(1);
    }
    
    while (1) {
        cnt = epoll_wait(epoll, events, MAX_EVENTS, -1);
        
        for (i = 0; i < cnt; i++) {
            
            if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)
                || !(events[i].events & EPOLLIN))
            {
                perror("error : socket fd error!\n");
                close(events[i].data.fd);
                continue;
            
            } else if (events[i].data.fd == sfd) {
                
                while (1) { 
                    struct sockaddr client_addr;
                    int addrlen = sizeof(struct sockaddr);
                    
                    sd = accept(sfd, &client_addr, &addrlen);
                    if (sd == -1) {
                    
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            break;
                        
                        } else {
                            perror("error : cannot accept new socket!\n");
                            continue;
                        }
                        
                    } 
                    
                    res = make_socket_non_binding(sd);
                    if (res == -1) {
                        perror("error : cannot set flags!\n");
                        exit(1);
                    }
                    
                    event.data.fd = sd;
                    event.events  = EPOLLET | EPOLLIN;
                    res = epoll_ctl(epoll, EPOLL_CTL_ADD, sd, &event);
                    if (res == -1) {
                        perror("error : cannot add to epoll!\n");
                        exit(1);
                    }
                }  
                
            } else {
                int cnt;
                char buf[BUF_SIZE];
                
                while (1) {
                
                    cnt = read(events[i].data.fd,  buf, BUF_SIZE);
                    if (cnt == -1) {
                        if (errno == EAGAIN) {
                            break;
                        }
                        
                        perror("error : read error!\n");
                        exit(1);
                
                    } else if (cnt == 0) {
                        close(events[i].data.fd);
                        break;
                    } 
                
                    printf("receive client data : %s\n", buf);
                }
            }
        }
    }
    
    close(sfd);
    
    return 0;
}
Esempio n. 14
0
int
main (int argc, char *argv[])
{
    int sfd, s;
    int efd;
    struct epoll_event event;
    struct epoll_event *events;
    if (argc != 2)
    {
        fprintf (stderr, "Usage: %s [port]\n", argv[0]);
        exit (EXIT_FAILURE);
    }
    sfd = create_and_bind (argv[1]);
    if (sfd == -1)
        abort ();
    s = make_socket_non_blocking (sfd);
    if (s == -1)
        abort ();
    s = listen (sfd, SOMAXCONN);
    if (s == -1)
    {
        perror ("listen");
        abort ();
    }
    efd = epoll_create1 (0);
    if (efd == -1)
    {
        perror ("epoll_create");
        abort ();
    }
    event.data.fd = sfd;
    event.events = EPOLLIN | EPOLLET;
    // READ AND ET
    s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
    if (s == -1)
    {
        perror ("epoll_ctl");
        abort ();
    }
    /* Buffer where events are returned */
    /* function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. */
    /* max event is 64 */
    events = calloc (MAXEVENTS, sizeof event);
    /* The event loop */
    while (1)
    {
        printf("wait here\n");
        int n, i;
        // RETURN THE ERADY NUMBS
        // ET AND LT only for the epoll_wait
        n = epoll_wait (efd, events, MAXEVENTS, -1);
        for (i = 0; i < n; i++)
        {
            if ((events[i].events & EPOLLERR) ||
                    (events[i].events & EPOLLHUP) ||
                    (!(events[i].events & EPOLLIN)))
            {
                /* An error has occured on this fd, or the socket is not
                   ready for reading (why were we notified then?) */
                fprintf (stderr, "epoll error\n");
                close (events[i].data.fd);
                continue;
            }

            else if (sfd == events[i].data.fd)
            {
                /* We have a notification on the listening socket, which
                   means one or more incoming connections. */
                while (1)
                {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int infd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                    in_len = sizeof in_addr;
                    // if there is connection wait to process it will return the
                    // infd
                    infd = accept (sfd, &in_addr, &in_len);
                    if (infd == -1)
                    {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
                        {
                            /* We have processed all incoming
                               connections. */
                            break;
                        }
                        else
                        {
                            perror ("accept");
                            break;
                        }
                    }
                    //it converts a socket address to a corresponding host and service
                    //return numeric host and service
                    s = getnameinfo (&in_addr, in_len,
                                     hbuf, sizeof hbuf,
                                     sbuf, sizeof sbuf,
                                     NI_NUMERICHOST | NI_NUMERICSERV);
                    if (s == 0)
                    {
                        printf ("Accepted connection on descriptor %d "
                                "(host=%s, port=%s)\n", infd, hbuf, sbuf);
                    }

                    /* Make the incoming socket non-blocking and add it to the
                       list of fds to monitor. */
                    s = make_socket_non_blocking (infd);
                    if (s == -1)
                        abort ();
                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
                    if (s == -1)
                    {
                        perror ("epoll_ctl");
                        abort ();
                    }
                }
                continue;
            }
            else
            {
                /* We have data on the fd waiting to be read. Read and
                   display it. We must read whatever data is available
                   completely, as we are running in edge-triggered mode
                   and won't get a notification again for the same
                   data. */
                int done = 0;
                while (1)
                {
                    ssize_t count;
                    char buf[512];
                    count = read (events[i].data.fd, buf, sizeof buf);
                    if (count == -1)
                    {
                        /* If errno == EAGAIN, that means we have read all
                           data. So go back to the main loop. */
                        if (errno != EAGAIN)
                        {
                            perror ("read");
                            done = 1;
                        }
                        break;
                    }
                    else if (count == 0)
                    {
                        /* End of file. The remote has closed the
                           connection. */
                        done = 1;
                        break;
                    }
                    /* Write the buffer to standard output */
                    s = write (1, buf, count);
                    if (s == -1)
                    {
                        perror ("write");
                        abort ();
                    }
                }
                if (done)
                {
                    printf ("Closed connection on descriptor %d\n",
                            events[i].data.fd);

                    /* Closing the descriptor will make epoll remove it
                       from the set of descriptors which are monitored. */
                    close (events[i].data.fd);
                }
            }
        }
    }
    free (events);
    close (sfd);
    return EXIT_SUCCESS;
}
Esempio n. 15
0
int main(int argc, char *argv[]) {
  int sfd, s;
  int efd;
  struct epoll_event event;
  struct epoll_event *events;

  if(argc != 2) {
    fprintf(stderr, "Usage: %s [port]\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  sfd = create_and_bind(argv[1]);
  if(sfd == -1) 
    abort();

  s = make_socket_non_blocking(sfd);
  if(s == -1) 
    abort();

  s = listen(sfd, SOMAXCONN);
  if(s == -1) {
    perror("listen");
    abort();  
  }

  efd = epoll_create1(0);
  if(efd == -1) {
    perror("epoll_create1");
    abort();
  }
  event.data.fd = sfd;
  event.events = EPOLLIN | EPOLLET;
  s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
  if(s == -1) {
    perror("epoll_ctl");
    abort();
  }

  events = calloc(MAXEVENTS, sizeof(event));
  /* The event loop */
  while(1) {
    int n, i;
    
    n = epoll_wait(efd, events, MAXEVENTS, -1);
    for(i = 0; i < n; i++) {
      if((events[i].events & EPOLLERR) || 
	(events[i].events & EPOLLHUP) || 
	(!(events[i].events & EPOLLIN))) {
        /*An error occurred, notified but no ready*/
        fprintf(stderr, "epoll error\n");
        close(events[i].data.fd);
        continue;
      }
      else if(sfd == events[i].data.fd) {
        /*listener port is notified, which means incoming connection*/
        while(1) {
          struct sockaddr in_addr;
          socklen_t in_len;
          int infd;
          char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
   
          in_len = sizeof(in_addr);
          infd = accept(sfd, &in_addr, &in_len);
          if(infd == -1) {
            if((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
              /*we have processed all incoming connections*/
              break;
            }
            else {
              perror("accept");
              break;
            }
          }

          s = getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
          if(s == 0) {
            printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", infd, hbuf, sbuf);
          }

          /*make the socket non-blocking and add it to monitor list*/
          s = make_socket_non_blocking(infd);
          if(s == -1)
            abort();
  
          event.data.fd = infd;
          event.events = EPOLLIN | EPOLLET;
          s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
          if(s == -1) {
            perror("epoll_ctl");
            abort();
          }
        }
        continue;
      }
      else {
        /*read is ready*/ 
        int done = 0;
        while(1) {
          ssize_t count;
          char buf[512];

          count = read(events[i].data.fd, buf, sizeof(buf));
          if(count == -1) {
            if(errno != EAGAIN) {
              perror("read");
              done = 1;
            }
            break;
          }
          else if(count == 0) {
            /*End of file*/
            done = 1;
            break;
          }
          /*Write the buffer to stdout*/
          s = write(1, buf, count);
          if(s == -1) {
            perror("write");
            abort();
          }
        }

        if(done) {
          printf("closed connection on descriptor %d\n", events[i].data.fd);
          /*close connection*/
          close(events[i].data.fd);
        }
      }
    }
  }

  free(events);
  close(sfd);
  
  return EXIT_SUCCESS;
}
Esempio n. 16
0
int main (int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    const char *server_host[MAX_REMOTE_NUM];
    const char *server_port = NULL;

    int dns_thread_num = DNS_THREAD_NUM;

    int option_index = 0;
    static struct option long_options[] =
    {
        {"fast-open", no_argument, 0,  0 },
        {"port-start", required_argument, 0, 0 },
        {"port-end", required_argument, 0, 0 },
        {0,           0,           0,  0 }
    };

    opterr = 0;

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:uv",
                            long_options, &option_index)) != -1)
    {
        printf("option_index %d\n", option_index);
        switch (c)
        {
        case 0:

            if (option_index == 0)
            {
#ifdef TCP_FASTOPEN
                fast_open = 1;
                LOGD("using tcp fast open");
#else
                LOGE("tcp fast open is not supported by this environment");
#endif
            } else
            if (option_index == 1) 
            {
                start_port = atoi(optarg);
            } else
            if (option_index == 2) 
            {
                end_port = atoi(optarg);
            }

            break;
        case 's':
            server_host[server_num++] = optarg;
            break;
        case 'p':
            server_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 'i':
            iface = optarg;
            break;
        case 'd':
            dns_thread_num = atoi(optarg);
            if (!dns_thread_num) FATAL("Invalid DNS thread number");
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            udprelay = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        }
    }

    printf("start %d end %d\n", start_port, end_port);

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

    if (conf_path != NULL)
    {
        jconf_t *conf = read_jconf(conf_path);
        if (server_num == 0)
        {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++)
            {
                server_host[i] = conf->remote_addr[i].host;
            }
        }
        if (server_port == NULL) server_port = conf->remote_port;
        if (password == NULL) password = conf->password;
        if (method == NULL) method = conf->method;
        if (timeout == NULL) timeout = conf->timeout;
#ifdef TCP_FASTOPEN
        if (fast_open == 0) fast_open = conf->fast_open;
#endif
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) nofile = conf->nofile;
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile)
        {
            if (verbose)
            {
                LOGD("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

    if ((start_port > 0 && end_port <= 0) || (start_port <= 0 && end_port > 0)) {
        printf("Both start_prot and end_port needs to be specified\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (server_port != NULL && start_port > 0) {
        printf("server port can't be set if you want to use a port range\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (server_num == 0 || (server_port == NULL && start_port <= 0) || password == NULL)
    {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) timeout = "60";

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

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    // setup asyncns
    asyncns_t *asyncns;
    if (!(asyncns = asyncns_new(dns_thread_num)))
    {
        FATAL("asyncns failed");
    }

    // setup keys
    LOGD("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // inilitialize listen context
    struct listen_ctx listen_ctx_list[server_num + 1];

    // bind to each interface
    while (server_num > 0)
    {
        int index = --server_num;
        const char* host = server_host[index];
        int success = 1;
        int listenfd;

        if (start_port > 0) {
            server_port = itoa(start_port);
        }
        do {
            // Bind to port
            
            listenfd = create_and_bind(host, server_port);
            success = 1;
            if (listenfd < 0)
            {
                success = 0;
            }
            if (listen(listenfd, SOMAXCONN) == -1)
            {
                success = 0;
            }
            if (!success) {
                if (start_port < end_port) {
                    start_port++;
                    server_port = itoa(start_port);
                } else
                {
                    FATAL("Out of listen ports!");
                    exit(1);
                }
            }
        } while (!success);
        setnonblocking(listenfd);
        LOGD("server listening at port %s.", server_port);

        struct listen_ctx *listen_ctx = &listen_ctx_list[index + 1];

        // Setup proxy context
        listen_ctx->timeout = atoi(timeout);
        listen_ctx->asyncns = asyncns;
        listen_ctx->fd = listenfd;
        listen_ctx->method = m;
        listen_ctx->iface = iface;

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

    // initialize the DNS
    struct listen_ctx *listen_ctx = &listen_ctx_list[0];
    int asyncnsfd = asyncns_fd(asyncns);
    listen_ctx->timeout = atoi(timeout);
    listen_ctx->asyncns = asyncns;
    listen_ctx->fd = asyncnsfd;
    listen_ctx->method = m;
    listen_ctx->iface = iface;
    ev_io_init (&listen_ctx->io, server_resolve_cb, asyncnsfd, EV_READ);
    ev_io_start (loop, &listen_ctx->io);

    // Setup UDP
    if (udprelay)
    {
        LOGD("udprelay enabled.");
        udprelay_init(server_host[0], server_port, dns_thread_num, m, listen_ctx->timeout, iface);
    }

    // setuid
    if (user != NULL)
        run_as(user);

    // start ev loop
    ev_run (loop, 0);
    return 0;
}
Esempio n. 17
0
void*
sock_boot (void *v_options)
{
  int sfd, s;
  int efd;
  struct epoll_event event;
  struct epoll_event *events;

  s_options* options = (s_options *) v_options;
  sfd = create_and_bind (options->port);
  if (sfd == -1)
    abort ();

  s = make_socket_non_blocking (sfd);
  if (s == -1)
    abort ();

  s = listen (sfd, SOMAXCONN);
  if (s == -1)
    {
      perror ("listen");
      abort ();
    }

  efd = epoll_create (1);
  if (efd == -1)
    {
      perror ("epoll_create");
      abort ();
    }

  event.data.fd = sfd;
  event.events = EPOLLIN | EPOLLET;
  s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
  if (s == -1)
    {
      perror ("epoll_ctl");
      abort ();
    }

  /* Buffer where events are returned */
  events = calloc (MAXEVENTS, sizeof event);

  /* The event loop */
  while (1)
    {
      int n, i;

      n = epoll_wait (efd, events, MAXEVENTS, -1);
      for (i = 0; i < n; i++)
	{
	  if ((events[i].events & EPOLLERR) ||
              (events[i].events & EPOLLHUP) ||
              (!(events[i].events & EPOLLIN)))
	    {
              /* An error has occured on this fd, or the socket is not
                 ready for reading (why were we notified then?) */
	      fprintf (stderr, "epoll error\n");
	      close (events[i].data.fd);
	      continue;
	    }

	  else if (sfd == events[i].data.fd)
	    {
              /* We have a notification on the listening socket, which
                 means one or more incoming connections. */
              while (1)
                {
                  struct sockaddr in_addr;
                  socklen_t in_len;
                  int infd;
                  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                  in_len = sizeof in_addr;
                  infd = accept (sfd, &in_addr, &in_len);
                  if (infd == -1)
                    {
                      if ((errno == EAGAIN) ||
                          (errno == EWOULDBLOCK))
                        {
                          /* We have processed all incoming
                             connections. */
                          break;
                        }
                      else
                        {
                          perror ("accept");
                          break;
                        }
                    }

                  s = getnameinfo (&in_addr, in_len,
                                   hbuf, sizeof hbuf,
                                   sbuf, sizeof sbuf,
                                   NI_NUMERICHOST | NI_NUMERICSERV);
                  if (s == 0)
                    {
                      printf("Accepted connection on descriptor %d "
                             "(host=%s, port=%s)\n", infd, hbuf, sbuf);
                    }

                  /* Make the incoming socket non-blocking and add it to the
                     list of fds to monitor. */
                  s = make_socket_non_blocking (infd);
                  if (s == -1)
                    abort ();

                  event.data.fd = infd;
                  event.events = EPOLLIN | EPOLLET;
                  s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
                  if (s == -1)
                    {
                      perror ("epoll_ctl");
                      abort ();
                    }
                }
              continue;
            }
          else
            {
              /* We have data on the fd waiting to be read. Read and
                 display it. We must read whatever data is available
                 completely, as we are running in edge-triggered mode
                 and won't get a notification again for the same
                 data. */
              int done = 0;

              while (1)
                {
                  ssize_t count;
                  char buf[512];

                  count = read (events[i].data.fd, buf, sizeof buf);
                  if (count == -1)
                    {
                      /* If errno == EAGAIN, that means we have read all
                         data. So go back to the main loop. */
                      if (errno != EAGAIN)
                        {
                          perror ("read");
                          done = 1;
                        }
                      break;
                    }
                  else if (count == 0)
                    {
                      /* End of file. The remote has closed the
                         connection. */
                      done = 1;
                      break;
                    }

                  char c_payload_size[9];
                  memcpy(c_payload_size,&buf[0],8);
                  c_payload_size[8] = '\0';
                  char *e;
                  unsigned long int payload_size = strtoul(c_payload_size,&e,16);
                  clients_data[i].payload_size = payload_size;
                  memcpy(clients_data[i].buffer,&buf[8],payload_size);


                  t_split *directives = ksplit(clients_data[i].buffer,"\x0d\x0a");
                  int j;
                  for (j=0; j < directives->count; ++j) {
  
                    memcpy(&received_data_queue[received_data_queue_tail++],directives->splited_ary[j],payload_size);
                    if (received_data_queue_tail > MAX_RECEIVE_QUEUE) received_data_queue_tail = 0;
                    //strcpy(clients_data[i].buffer,&buf[8]);
  #ifdef DEBUG
                    //printf("payload_size:[%d] | ",payload_size);
                    //printf("clients_data[%d].payload_size:[%lu] | ",i,payload_size);
                    printf("clients_data[%d].buffer:[%s]\n",i,directives->splited_ary[j]);
  #endif
                  }
                }

              if (done)
                {
                  printf ("Closed connection on descriptor %d\n",
                          events[i].data.fd);

                  /* Closing the descriptor will make epoll remove it
                     from the set of descriptors which are monitored. */
                  close (events[i].data.fd);
                }
            }
        }
    }

  free (events);

  close (sfd);

  return EXIT_SUCCESS;
}
Esempio n. 18
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 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;

    opterr = 0;

    while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:c:b:a:")) != -1) {
        switch (c) {
        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;
        }
    }

    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 (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

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

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

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

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

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

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0) {
        FATAL("bind() error");
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        FATAL("listen() error");
    }
    setnonblocking(listenfd);
    LOGI("listening at %s:%s", local_addr, local_port);

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = 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 = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.fd = listenfd;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;
    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    ev_run(loop, 0);

    return 0;
}
Esempio n. 19
0
int main (int argc, char **argv)
{

    int i, c;
    int pid_flags = 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;
    char *iface = NULL;

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

    opterr = 0;

    while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uv")) != -1)
    {
        switch (c)
        {
        case 's':
            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 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            udprelay = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        }
    }

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

    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 (remote_num == 0 || remote_port == NULL ||
            local_port == NULL || password == NULL)
    {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) timeout = "10";

    if (local_addr == NULL) local_addr = "0.0.0.0";

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

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

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

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0)
    {
        FATAL("bind() error..");
    }
    if (listen(listenfd, SOMAXCONN) == -1)
    {
        FATAL("listen() error.");
    }
    setnonblocking(listenfd);
    LOGD("server listening at port %s.", local_port);

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(ss_addr_t) * remote_num);
    while (remote_num > 0)
    {
        int index = --remote_num;
        if (remote_addr[index].port == NULL) remote_addr[index].port = remote_port;
        listen_ctx.remote_addr[index] = remote_addr[index];
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.fd = listenfd;
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = ev_default_loop(0);
    if (!loop)
    {
        FATAL("ev_loop error.");
    }
    ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start (loop, &listen_ctx.io);

    // Setup UDP
    if (udprelay)
    {
        LOGD("udprelay enabled.");
        udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, m, listen_ctx.timeout, iface);
    }

    // setuid
    if (user != NULL)
        run_as(user);

    ev_run (loop, 0);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    return 0;
}
Esempio n. 20
0
int EpollServer::create_and_bind(const char *port) {

	return create_and_bind(NULL, port);
}
Esempio n. 21
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    const char *server_host[MAX_REMOTE_NUM];

    char * nameservers[MAX_DNS_NUM + 1];
    int nameserver_num = 0;

    int option_index = 0;
    static struct option long_options[] =
    {
        { "fast-open",          no_argument,       0, 0 },
        { "acl",                required_argument, 0, 0 },
        { "manager-address",    required_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:i:d:a:uUv",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            } else if (option_index == 2) {
                manager_address = optarg;
            }
            break;
        case 's':
            if (server_num < MAX_REMOTE_NUM) {
                server_host[server_num++] = optarg;
            }
            break;
        case 'p':
            server_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 'i':
            iface = optarg;
            break;
        case 'd':
            if (nameserver_num < MAX_DNS_NUM) {
                nameservers[nameserver_num++] = optarg;
            }
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 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 (server_num == 0) {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++) {
                server_host[i] = conf->remote_addr[i].host;
            }
        }
        if (server_port == NULL) {
            server_port = conf->remote_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
#ifdef TCP_FASTOPEN
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#endif
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
        if (conf->nameserver != NULL) {
            nameservers[nameserver_num++] = conf->nameserver;
        }
    }

    if (server_num == 0) {
        server_host[server_num++] = NULL;
    }

    if (server_num == 0 || server_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (method == NULL) {
        method = "table";
    }

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

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

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // setup udns
    if (nameserver_num == 0) {
#ifdef __MINGW32__
        nameservers[nameserver_num++] = "8.8.8.8";
        resolv_init(loop, nameservers, nameserver_num);
#else
        resolv_init(loop, NULL, 0);
#endif
    } else {
        resolv_init(loop, nameservers, nameserver_num);
    }

    for (int i = 0; i < nameserver_num; i++) {
        LOGI("using nameserver: %s", nameservers[i]);
    }

    // inilitialize listen context
    struct listen_ctx listen_ctx_list[server_num];

    // bind to each interface
    while (server_num > 0) {
        int index = --server_num;
        const char * host = server_host[index];

        if (mode != UDP_ONLY) {
            // Bind to port
            int listenfd;
            listenfd = create_and_bind(host, server_port);
            if (listenfd < 0) {
                FATAL("bind() error");
            }
            if (listen(listenfd, SSMAXCONN) == -1) {
                FATAL("listen() error");
            }
            setnonblocking(listenfd);
            struct listen_ctx *listen_ctx = &listen_ctx_list[index];

            // Setup proxy context
            listen_ctx->timeout = atoi(timeout);
            listen_ctx->fd = listenfd;
            listen_ctx->method = m;
            listen_ctx->iface = iface;
            listen_ctx->loop = loop;

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

        // Setup UDP
        if (mode != TCP_ONLY) {
            init_udprelay(server_host[index], server_port, m, atoi(timeout),
                          iface);
        }

        LOGI("listening at %s:%s", host ? host : "*", server_port);

    }

    if (manager_address != NULL) {
        ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
        ev_timer_start(EV_DEFAULT, &stat_update_watcher);
    }

    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
    }

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

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // start ev loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    if (manager_address != NULL) {
        ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
    }

    // Clean up
    for (int i = 0; i <= server_num; i++) {
        struct listen_ctx *listen_ctx = &listen_ctx_list[i];
        if (mode != UDP_ONLY) {
            ev_io_stop(loop, &listen_ctx->io);
            close(listen_ctx->fd);
        }
    }

    if (mode != UDP_ONLY) {
        free_connections(loop);
    }

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    resolv_shutdown(loop);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}
int main (int argc, char *argv[])
{
	struct epoll_event event, *events;
	int sfd, s;
	int efd;

	/* Set up listening socket, 'listen_sock' (socket(),
	   bind(), listen()) */

	sfd = create_and_bind ("8888");
	if (sfd == -1)
		abort ();

	s = make_socket_non_blocking (sfd);
	if (s == -1)
	{
		err_sys("socket error");
		exit(1);
	}

	s = listen (sfd, SOMAXCONN);
	if (s == -1)
	{
		err_sys("listen");
		exit(-1);
	}

	efd = epoll_create1 (0);
	if (efd == -1)
	{
		err_sys("epoll_create");
		exit(-1);
	}

	event.data.fd = sfd;
	//event.events = EPOLLIN | EPOLLET;
	event.events = EPOLLIN;
	s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
	if (s == -1)
	{
		err_sys("epoll_ctl");
		exit(-1);
	}

	/* Buffer where events are returned */
	events = calloc (MAXEVENTS, sizeof event);

	/* The event loop */
	while (1)
	{
		int n, i;

		n = epoll_wait (efd, events, MAXEVENTS, -1);
		for (i = 0; i < n; i++)
		{
			if ((events[i].events & EPOLLERR) ||
					(events[i].events & EPOLLHUP) ||
					(!(events[i].events & EPOLLIN)))
			{
				/* An error has occured on this fd, or the socket is not
				   ready for reading (why were we notified then?) */
				fprintf (stderr, "epoll error\n");
				close (events[i].data.fd);
				continue;
			}

			else if (sfd == events[i].data.fd)
			{
				/* We have a notification on the listening socket, which
				   means one or more incoming connections. */
				while (1)
				{
					struct sockaddr in_addr;
					socklen_t in_len;
					int infd;
					char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

					in_len = sizeof in_addr;
					infd = accept (sfd, &in_addr, &in_len);
					if (infd == -1)
					{
						if ((errno == EAGAIN) ||
								(errno == EWOULDBLOCK))
						{
							/* We have processed all incoming
							   connections. */
							break;
						}
						else
						{
							perror ("accept");
							break;
						}
					}

					s = getnameinfo (&in_addr, in_len,
							hbuf, sizeof hbuf,
							sbuf, sizeof sbuf,
							NI_NUMERICHOST | NI_NUMERICSERV);
					if (s == 0)
					{
						printf("Accepted connection on descriptor %d "
								"(host=%s, port=%s)\n", infd, hbuf, sbuf);
					}

					/* Make the incoming socket non-blocking and add it to the
					   list of fds to monitor. */
					s = make_socket_non_blocking (infd);
					if (s == -1)
						abort ();

					event.data.fd = infd;
					//event.events = EPOLLIN | EPOLLET;
					event.events = EPOLLIN;
					s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
					if (s == -1)
					{
						err_sys("epoll_ctl");
					}
				}
				continue;
			}
			else
			{
				/* We have data on the fd waiting to be read. Read and
				   display it. We must read whatever data is available
				   completely, as we are running in edge-triggered mode
				   and won't get a notification again for the same
				   data. */
				int done = 0;

				while (1)
				{
					ssize_t count;
					char buf[2];

					count = read (events[i].data.fd, buf, sizeof buf);
					if (count == -1)
					{
						/* If errno == EAGAIN, that means we have read all
						   data. So go back to the main loop. */
						if (errno != EAGAIN)
						{
							perror ("read");
							done = 1;
						}
						break;
					}
					else if (count == 0)
					{
						/* End of file. The remote has closed the
						   connection. */
						done = 1;
						break;
					}

					/* Write the buffer to standard output */
					s = write (1, buf, count);
					if (s == -1)
					{
						err_sys("write");
					}
				}

				if (done)
				{
					printf ("Closed connection on descriptor %d\n",
							events[i].data.fd);

					/* Closing the descriptor will make epoll remove it
					   from the set of descriptors which are monitored. */
					close (events[i].data.fd);
				}
			}
		}
	}

	return 0;
}
Esempio n. 23
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 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;
    char *iface = NULL;

    srand(time(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[] =
    {
        { "fast-open", no_argument,       0, 0 },
        { "acl",       required_argument, 0, 0 },
        { 0,           0,                 0, 0 }
    };

    opterr = 0;

    USE_TTY();

#ifdef ANDROID
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvVA",
                            long_options, &option_index)) != -1) {
#else
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvA",
                            long_options, &option_index)) != -1) {
#endif
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            }
            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 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            auth = 1;
            break;
#ifdef ANDROID
        case 'V':
            vpn = 1;
            break;
#endif
        }
    }

    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 (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

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

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

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

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

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

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

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *) * remote_num);
    for (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 = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0) {
        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("udprelay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), m, listen_ctx.timeout, iface);
    }

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

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    for (i = 0; i < remote_num; i++) {
        free(listen_ctx.remote_addr[i]);
    }
    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}

#else

int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    mode = profile.mode;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

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

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
    memset(storage, 0, sizeof(struct sockaddr_storage));
    if (get_sockaddr(remote_host, remote_port_str, storage, 1) == -1) {
        return -1;
    }

    // Setup proxy context
    struct ev_loop *loop = EV_DEFAULT;
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *));
    listen_ctx.remote_addr[0] = (struct sockaddr *)storage;
    listen_ctx.timeout = timeout;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        ERROR("bind()");
        return -1;
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        ERROR("listen()");
        return -1;
    }
    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("udprelay enabled");
        struct sockaddr *addr = (struct sockaddr *)storage;
        init_udprelay(local_addr, local_port_str, addr,
                      get_sockaddr_len(addr), m, timeout, NULL);
    }

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

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);
    close(listen_ctx.fd);

    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}
Esempio n. 24
0
int main(int argc, char* argv[]) {
  int listen_fd, ret;
  int epoll_fd;
  struct epoll_event event;
  struct epoll_event *events;

  listen_fd = create_and_bind(PORT);
  if (listen_fd == -1) {
    return -1;
  }

  ret = set_non_block(listen_fd);
  if (ret == -1) {
    return -1;
  }

  ret = listen(listen_fd, SOMAXCONN);
  if (ret == -1) {
    perror("listen");
    return -1;
  }

  epoll_fd = epoll_create1(0);
  if (epoll_fd == -1) {
    perror("epoll_create");
    return -1;
  }

  event.data.fd = listen_fd;
  event.events = EPOLLIN | EPOLLET;
  ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event);
  if (ret == -1) {
    perror("epoll_ctl");
    return -1;
  }

  events = calloc(MAX_EVENTS, sizeof event);

  for (;;) {
    int n, i;

    n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
    for (i = 0; i < n; i++) {
      if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP || !events[i].events & EPOLLIN) {
        fprintf(stderr, "epoll error\n");
        close(events[i].data.fd);
        continue;
      } else if (listen_fd == events[i].data.fd) {
        for (;;) {
          struct sockaddr in_addr;
          socklen_t in_len;
          int in_fd;
          char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

          in_len = sizeof in_addr;
          in_fd = accept(listen_fd, &in_addr, &in_len);
          if (in_fd == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
              break;
            } else {
              perror("accpet");
              break;
            }
          }

          ret = getnameinfo(&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV);
          if (ret == 0) {
            printf("accept connection on fd %d, [%s:%s]\n",  in_fd, hbuf, sbuf);
          }

          ret = set_non_block(in_fd);
          if (ret == -1) {
            return -1;
          }

          event.data.fd = in_fd;
          event.events = EPOLLIN | EPOLLET;
          ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, in_fd, &event);
          if (ret == -1) {
            perror("epoll_ctl");
            return -1;
          }
        }
        continue;
      } else if (events[i].events & EPOLLIN) {
        // get request
        int done = 0;

        for (;;) {
          ssize_t count;
          char buf[512];

          count = read(events[i].data.fd, buf, sizeof buf);
          if (count == -1) {
            if (errno != EAGAIN) {
              perror("read");
              done = 1;
              break;
            }

            event.events = EPOLLOUT | EPOLLET;
            event.data.fd = events[i].data.fd;
            ret = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, events[i].data.fd, &event);
            if (ret == -1) {
              perror("epoll_ctl:mod");
              done = 1;
            }

            break;
          } else if (count == 0) {
            done = 1;
            break;
          }

          // 写入标准输出
          ret = write(1, buf, count);
          if (ret == -1) {
            perror("write");
            done = 1;
            break;
          }
        }

        if (done == 1) {
          close(events[i].data.fd);
        }
      } else if (events[i].events & EPOLLOUT) {
        // response
        int fd;
        int done = 0;
        size_t size = 512;
        ssize_t count;

        fd = open("./epoll-server.c", O_RDONLY | O_NONBLOCK);
        if (fd == -1) {
          perror("open");
          close(events[i].data.fd);
          return -1;
        }

        char *head = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
        count = write(events[i].data.fd, head, sizeof head);
        if (count == -1 && errno != EAGAIN) {
          perror("write");
          close(events[i].data.fd);
          return -1;
        }

        for (;;) {
          count = sendfile(events[i].data.fd, fd, 0, size);
          if (count == -1) {
            if (errno != EAGAIN) {
              perror("sendfile");
              done = 1;
            }
            break;
          } else if (count == 0) {
            done = 1;
            break;
          }
        }

        if (done == 1) {
          close(events[i].data.fd);
        }

      }
    }
  }

  free(events);
  return 0;
}
Esempio n. 25
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 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;
    char *iface = NULL;

    srand(time(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[] =
    {
        { "fast-open", no_argument,             0,
          0 },
        { "acl",       required_argument,       0,
          0 },
        { 0,           0,                       0,
          0 }
    };

    opterr = 0;

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uv",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGD("initialize acl...");
                acl = !init_acl(optarg);
            }
            break;
        case 's':
            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 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            udprelay = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        }
    }

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

    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 (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGD("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

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

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

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

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

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGD("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

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

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0) {
        FATAL("bind() error..");
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        FATAL("listen() error.");
    }
    setnonblocking(listenfd);
    LOGD("server listening at port %s.", local_port);

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(ss_addr_t) * remote_num);
    while (remote_num > 0) {
        int index = --remote_num;
        if (remote_addr[index].port == NULL) {
            remote_addr[index].port = remote_port;
        }
        listen_ctx.remote_addr[index] = remote_addr[index];
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.fd = listenfd;
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;
    if (!loop) {
        FATAL("ev_loop error.");
    }
    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (udprelay) {
        LOGD("udprelay enabled.");
        init_udprelay(local_addr, local_port, remote_addr[0].host,
                      remote_addr[0].port, m, listen_ctx.timeout, iface);
    }

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGD("closed nicely.");
    }

    // Clean up
    free_connections(loop);
    free_udprelay();

    ev_io_stop(loop, &listen_ctx.io);
    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}
Esempio n. 26
0
int
main (int argc, char *argv[])
{

    /* initialization code */
    cvect_t *dyn_vect = ccache_init();
    assert(dyn_vect);

    int sfd, s;
    int efd;
    struct epoll_event event;
    struct epoll_event *events;

    char buf[BUFFER_SIZE];
    char localbuf[BUFFER_SIZE];

    if (argc != 2)
    {
      fprintf (stderr, "Usage: %s [port]\n", argv[0]);
      exit (EXIT_FAILURE);
    }

    sfd = create_and_bind (argv[1]);
    if (sfd == -1) abort ();

    s = make_socket_non_blocking (sfd);
    if (s == -1) abort ();

    s = listen (sfd, SOMAXCONN);
    if (s == -1)
    {
        perror ("listen");
        abort ();
    }

    efd = epoll_create1 (0);
    if (efd == -1)
    {
      perror ("epoll_create");
      abort ();
    }

    event.data.fd = sfd;
    event.events = EPOLLIN | EPOLLET;
    s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
    if (s == -1)
    {
      perror ("epoll_ctl");
      abort ();
    }

    /* Buffer where events are returned */
    events = calloc (MAXEVENTS, sizeof event);

    /* The event loop */
    while (1)
    {
        int n, i;

        n = epoll_wait (efd, events, MAXEVENTS, -1);
        for (i = 0; i < n; i++)
        {   
        if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN)))
        {
              /* An error has occured on this fd, or the socket is not
                 ready for reading (why were we notified then?) */
            fprintf (stderr, "epoll error\n");
            close (events[i].data.fd);
            continue;
        }

        else if (sfd == events[i].data.fd)
        {
              /* We have a notification on the listening socket, which
                 means one or more incoming connections. */
                while (1)
                {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int infd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                    in_len = sizeof in_addr;
                    infd = accept (sfd, &in_addr, &in_len);
                    if (infd == -1)
                    {
                      if ((errno == EAGAIN) ||
                          (errno == EWOULDBLOCK))
                        {
                          /* We have processed all incoming
                             connections. */
                          break;
                        }
                      else
                        {
                          perror ("accept");
                          break;
                        }
                    }

                    s = getnameinfo (&in_addr, in_len,
                                   hbuf, sizeof hbuf,
                                   sbuf, sizeof sbuf,
                                   NI_NUMERICHOST | NI_NUMERICSERV);
                    if (s == 0)
                    {
                        printf("Accepted connection on descriptor %d "
                             "(host=%s, port=%s)\n", infd, hbuf, sbuf);
                    }

                  /* Make the incoming socket non-blocking and add it to the
                     list of fds to monitor. */
                    s = make_socket_non_blocking (infd);
                    if (s == -1) abort ();

                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
                    if (s == -1)
                    {
                        perror ("epoll_ctl");
                        abort ();
                    }
                }
                continue;
            }
            else
            {
              /* We have data on the fd waiting to be read. Read and
                 process it. We must read whatever data is available
                 completely, as we are running in edge-triggered mode
                 and won't get a notification again for the same
                 data. */
                int done = 0;


                while (1)
                {
                    ssize_t count;
                    bzero(buf,BUFFER_SIZE); //zero out the buffer every time 


                    count = read (events[i].data.fd, buf, sizeof buf);
                    if (count == -1)
                    {
                      /* If errno == EAGAIN, that means we have read all
                         data. So go back to the main loop. */
                        if (errno != EAGAIN)
                        {
                          perror ("read");
                          done = 1;
                        }
                        break;
                    }
                    else if (count == 0)
                    {
                      /* End of file. The remote has closed the
                         connection. */
                      done = 1;
                      break;
                    }


                    /* Process the buffered request and write the results to the output */
                    
                    buf[strlen(buf)-1] = '\0'; //remove trailing newline
                    /* Make sure this request is complete - can do special handling based on creq_type then */
                    strcpy(localbuf, buf);
                    ccmd_t type = get_creq_type(localbuf);
                    strcpy(localbuf, buf);

                    if(type == CSET) {
                        creq_t *creq = (creq_t *) malloc(sizeof(creq_t));

                        creq = ccache_req_parse(buf); //now process that actual buffer

                        /* Write Header and Footer to socket */
                        printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header));
                        if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error;

                        if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){
                            if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error;
                        }
                    }
                    /* CGET */
                    else if(type == CGET){
                        /* split multiple requests into single requests and process them */
                        char * pch;
                        int counter = 0;
                        pch = strtok(localbuf, " ");
                        while(pch != NULL){
                            
                            if(counter != 0){
                                /* formulate this new request and then skip the parsing step */
                                creq_t *creq = (creq_t *) malloc(sizeof(creq_t));
                                strcpy(creq->key, pch);
                                creq->type = CGET;

                                creq = ccache_get(creq);
                                        
                                /* Write Header and Footer to socket */
                                //printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header));
                                if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error;
                               

                                if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){
                                    if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error;
                                }
                            }
                            pch = strtok(NULL, " ");
                            counter++;
                        }
                        /* now that we're done transmitting all the CGET reqs - transmit END */
                        if((s = write (events[i].data.fd, "END\r\n", strlen("END\r\n"))) == -1) goto write_error;
                    }
                    else if(type == CDELETE || type == INVALID){
                        creq_t *creq = (creq_t *) malloc(sizeof(creq_t));

                        creq = ccache_req_parse(buf); //now process that actual buffer

                        /* Write Header and Footer to socket */
                        printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header));
                        if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error;

                        if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){
                            if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error;
                            
                        }
                        /* cleanup from delete */
                        free(creq);
                    }
                    else{
                        printf("error! exiting\n");
                        exit(1);
                    }
                    
                    
                }

                if (done)
                {
                    printf ("Closed connection on descriptor %d\n",
                          events[i].data.fd);

                    /* Closing the descriptor will make epoll remove it
                     from the set of descriptors which are monitored. */
                    close (events[i].data.fd);
                }
            }
        }
    }

    free (events);

    close (sfd);

    return EXIT_SUCCESS;

    write_error:
    if (s == -1)
    {
        perror ("write");
        abort ();
    }
    return -1;
}
Esempio n. 27
0
int main(int argc, char **argv)
{
    int i, c;
    int pid_flags    = 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;

    opterr = 0;

    while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:uUvA")) != -1)
        switch (c) {
        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 'A':
            auth = 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 (auth == 0) {
            auth = conf->auth;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * 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 (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

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

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

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

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

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    // Setup keys
    LOGI("initialize 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 = 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 = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -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;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd < 0) {
            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]), 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);
    }

    ev_run(loop, 0);

    return 0;
}
Esempio n. 28
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 *key        = NULL;
    char *timeout    = NULL;
    char *method     = NULL;
    char *pid_path   = NULL;
    char *conf_path  = NULL;

    char *plugin      = NULL;
    char *plugin_opts = NULL;
    char *plugin_host = NULL;
    char *plugin_port = NULL;
    char tmp_port[8];

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

    int dscp_num   = 0;
    ss_dscp_t * dscp = NULL;

    static struct option long_options[] = {
        { "fast-open",   no_argument,       NULL, GETOPT_VAL_FAST_OPEN },
        { "mtu",         required_argument, NULL, GETOPT_VAL_MTU },
        { "mptcp",       no_argument,       NULL, GETOPT_VAL_MPTCP },
        { "plugin",      required_argument, NULL, GETOPT_VAL_PLUGIN },
        { "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
        { "reuse-port",  no_argument,       NULL, GETOPT_VAL_REUSE_PORT },
        { "no-delay",    no_argument,       NULL, GETOPT_VAL_NODELAY },
        { "password",    required_argument, NULL, GETOPT_VAL_PASSWORD },
        { "key",         required_argument, NULL, GETOPT_VAL_KEY },
        { "help",        no_argument,       NULL, GETOPT_VAL_HELP },
        { NULL,          0,                 NULL, 0 }
    };

    opterr = 0;

    USE_TTY();

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A",
                            long_options, NULL)) != -1) {
        switch (c) {
        case GETOPT_VAL_FAST_OPEN:
            fast_open = 1;
            break;
        case GETOPT_VAL_MTU:
            mtu = atoi(optarg);
            LOGI("set MTU to %d", mtu);
            break;
        case GETOPT_VAL_MPTCP:
            mptcp = 1;
            LOGI("enable multipath TCP");
            break;
        case GETOPT_VAL_NODELAY:
            no_delay = 1;
            LOGI("enable TCP no-delay");
            break;
        case GETOPT_VAL_PLUGIN:
            plugin = optarg;
            break;
        case GETOPT_VAL_PLUGIN_OPTS:
            plugin_opts = optarg;
            break;
        case GETOPT_VAL_KEY:
            key = optarg;
            break;
        case GETOPT_VAL_REUSE_PORT:
            reuse_port = 1;
            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 GETOPT_VAL_PASSWORD:
        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 GETOPT_VAL_HELP:
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        case '6':
            ipv6first = 1;
            break;
        case 'A':
            FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
            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 (key == NULL) {
            key = conf->key;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (user == NULL) {
            user = conf->user;
        }
        if (plugin == NULL) {
            plugin = conf->plugin;
        }
        if (plugin_opts == NULL) {
            plugin_opts = conf->plugin_opts;
        }
        if (mode == TCP_ONLY) {
            mode = conf->mode;
        }
        if (mtu == 0) {
            mtu = conf->mtu;
        }
        if (mptcp == 0) {
            mptcp = conf->mptcp;
        }
        if (reuse_port == 0) {
            reuse_port = conf->reuse_port;
        }
        if (disable_sni == 0) {
            disable_sni = conf->disable_sni;
        }
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
#endif
        if (ipv6first == 0) {
            ipv6first = conf->ipv6_first;
        }
	dscp_num = conf->dscp_num;
	dscp = conf->dscp;
    }

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

    if (plugin != NULL) {
        uint16_t port = get_local_port();
        if (port == 0) {
            FATAL("failed to find a free port");
        }
        snprintf(tmp_port, 8, "%d", port);
        plugin_host = "127.0.0.1";
        plugin_port = tmp_port;

        LOGI("plugin \"%s\" enabled", plugin);
    }

    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 (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
        fast_open = 0;
#endif
    }

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

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

    if (plugin != NULL) {
        int len = 0;
        size_t buf_size = 256 * remote_num;
        char *remote_str = ss_malloc(buf_size);

        snprintf(remote_str, buf_size, "%s", remote_addr[0].host);
        for (int i = 1; i < remote_num; i++) {
            snprintf(remote_str + len, buf_size - len, "|%s", remote_addr[i].host);
            len = strlen(remote_str);
        }
        int err = start_plugin(plugin, plugin_opts, remote_str,
                remote_port, plugin_host, plugin_port, MODE_CLIENT);
        if (err) {
            FATAL("failed to start the plugin");
        }
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);
    ev_signal_start(EV_DEFAULT, &sigchld_watcher);

    // Setup keys
    LOGI("initializing ciphers... %s", method);
    crypto = crypto_init(password, key, method);
    if (crypto == NULL)
        FATAL("failed to initialize ciphers");

    // Setup proxy context
    struct listen_ctx listen_ctx;
    memset(&listen_ctx, 0, sizeof(struct listen_ctx));
    listen_ctx.remote_num  = remote_num;
    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);
    memset(listen_ctx.remote_addr, 0, sizeof(struct sockaddr *) * remote_num);
    for (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;
        if (plugin != NULL) {
            host = plugin_host;
            port = plugin_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;

        if (plugin != NULL) break;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.mptcp   = mptcp;

    struct ev_loop *loop = EV_DEFAULT;

    listen_ctx_t* listen_ctx_current = &listen_ctx;
    do {
        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_current->fd = listenfd;

            ev_io_init(&listen_ctx_current->io, accept_cb, listenfd, EV_READ);
            ev_io_start(loop, &listen_ctx_current->io);
        }

        // Setup UDP
        if (mode != TCP_ONLY) {
            LOGI("UDP relay enabled");
            char *host = remote_addr[0].host;
            char *port = remote_addr[0].port == NULL ? remote_port : remote_addr[0].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");
            }
            struct sockaddr *addr = (struct sockaddr *)storage;
            init_udprelay(local_addr, local_port, addr,
                          get_sockaddr_len(addr), mtu, crypto, listen_ctx_current->timeout, NULL);
        }

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

        if(listen_ctx_current->tos) {
            LOGI("listening at %s:%s (TOS 0x%x)", local_addr, local_port, listen_ctx_current->tos);
        } else {
            LOGI("listening at %s:%s", local_addr, local_port);
        }

        // Handle additionals TOS/DSCP listening ports
        if (dscp_num > 0) {
            listen_ctx_current = (listen_ctx_t*) ss_malloc(sizeof(listen_ctx_t));
            listen_ctx_current = memcpy(listen_ctx_current, &listen_ctx, sizeof(listen_ctx_t));
            local_port = dscp[dscp_num-1].port;
            listen_ctx_current->tos = dscp[dscp_num-1].dscp << 2;
        }
    } while (dscp_num-- > 0);

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

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

    ev_run(loop, 0);

    if (plugin != NULL) {
        stop_plugin();
    }

    return 0;
}
Esempio n. 29
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;
}
Esempio n. 30
0
int main(int argc, char *argv[]) {
    if (argc != 2) {
        print_err("Arguments failure");
    }

    pid_t main_pid = fork();
    switch(main_pid) {
        case 0:
            break;
        case -1:
            print_err("Can't fork main");
        default:
            exit(0);
    }

    if(setsid()<0) {
        print_err("Can't start new session");
    }
    pid_t nsession_pid = fork();
    switch(nsession_pid) {
        case 0:
            break;
        case -1:
            print_err("Can't fork from deamon");
        default:
            return 0;
    }

    pid_t daemon_pid = getpid();
    int tmp_fd = open("/tmp/netsh.pid", O_WRONLY | O_CREAT);
    char* buf = new char[64];
    int digits = sprintf(buf, "%d\n", daemon_pid);
    ssize_t written_count = write(tmp_fd, buf, digits);
    if (written_count == -1) {
        close(tmp_fd);
        print_err("Failed to write pid to file");
    }
    close(tmp_fd);
    //Done pre part

    const int epoll_size = 32;
    struct epoll_event event;
    struct epoll_event *events;

    //prepare socket
    int socket_fd = create_and_bind(argv[1]);
    make_socket_non_blocking(socket_fd);
    if (listen(socket_fd, SOMAXCONN) == -1) {
        print_err("Can't setup listener");
    }

    //Setup epoll
    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        print_err("Can't create epoll");
    }
    event.data.fd = socket_fd;
    event.events = EPOLLIN | EPOLLET;
    int ectl_status = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event);
    if (ectl_status == -1) {
        print_err("Can't register fd in epoll");
    }

    events = calloc(epoll_size, sizeof(event));

    while (1)
    {
        int n, i;

        n = epoll_wait (epoll_fd, events, epoll_size, -1);
        for (i = 0; i < n; i++)
        {
            if ((events[i].events & EPOLLERR) ||
                (events[i].events & EPOLLHUP) ||
                (!(events[i].events & EPOLLIN)))
            {
                close (events[i].data.fd);
                continue;
            }

            else if (socket_fd == events[i].data.fd)
            {
                while (1)
                {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int infd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                    in_len = sizeof in_addr;
                    infd = accept (socket_fd, &in_addr, &in_len);
                    if (infd == -1)
                    {
                        if ((errno == EAGAIN) ||
                            (errno == EWOULDBLOCK))
                        {
                            break;
                        }
                        else
                        {
                            perror ("Can't accept");
                            break;
                        }
                    }
                    int unblock_status = make_socket_non_blocking (infd);
                    if (unblock_status == -1)
                        print_err("Can't unblock socket");

                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    int epc_status = epoll_ctl (epoll_fd, EPOLL_CTL_ADD, infd, &event);
                    if (epc_status == -1)
                    {
                        print_err("Can't add flags");
                    }
                }
                continue;
            }
            else if (events[i].events == EPOLLIN)
            {
                int done = 0;
                read_and_exec(events[i].data.fd);

                if (1)
                {
                    close (events[i].data.fd);
                }
            } else if (events[i].events == EPOLLOUT) {

            }
        }
    }
    return 0;
}