Beispiel #1
0
int serv_loop()
{
  int    cs, ss = 0;
  struct sockaddr_storage cl;
  fd_set readable;
  int    i, n, len;
  char   cl_addr[NI_MAXHOST];
  char   cl_name[NI_MAXHOST];
  int    error;
  pid_t  pid;

#ifdef USE_THREAD
  if (threading) {
    blocksignal(SIGHUP);
    blocksignal(SIGINT);
    blocksignal(SIGUSR1);
  }
#endif

  for (;;) {
    readable = allsock;

    MUTEX_LOCK(mutex_select);
    n = select(maxsock+1, &readable, 0, 0, 0);
    if (n <= 0) {
      if (n < 0 && errno != EINTR) {
        msg_out(warn, "select: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

#ifdef USE_THREAD
    if ( ! threading ) {
#endif
      /* handle any queued signal flags */
      if (FD_ISSET(sig_queue[0], &readable)) {
        if (ioctl(sig_queue[0], FIONREAD, &i) != 0) {
          msg_out(crit, "ioctl: %m");
          exit(-1);
        }
        while (--i >= 0) {
          char c;
          if (read(sig_queue[0], &c, 1) != 1) {
            msg_out(crit, "read: %m");
            exit(-1);
          }
          switch(c) {
          case 'H': /* sighup */
            reload();
            break;
          case 'C': /* sigchld */
            reapchild();
            break;
          case 'T': /* sigterm */
            cleanup();
            break;
          default:
            break;
          }
        }
      }
#ifdef USE_THREAD
    }
#endif

    for ( i = 0; i < serv_sock_ind; i++ ) {
      if (FD_ISSET(serv_sock[i], &readable)) {
	n--;
	break;
      }
    }
    if ( n < 0 || i >= serv_sock_ind ) {
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

    len = sizeof(struct sockaddr_storage);
    cs = accept(serv_sock[i], (struct sockaddr *)&cl, (socklen_t *)&len);
    if (cs < 0) {
      if (errno == EINTR
#ifdef SOLARIS
	  || errno == EPROTO
#endif
	  || errno == EWOULDBLOCK
	  || errno == ECONNABORTED) {
	; /* ignore */
      } else {
	/* real accept error */
	msg_out(warn, "accept: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }
    MUTEX_UNLOCK(mutex_select);

#ifdef USE_THREAD
    if ( !threading ) {
#endif
      if (max_child > 0 && cur_child >= max_child) {
	msg_out(warn, "child: cur %d; exeedeing max(%d)",
		          cur_child, max_child);
	close(cs);
	continue;
      }
#ifdef USE_THREAD
    }
#endif

    error = getnameinfo((struct sockaddr *)&cl, len,
			cl_addr, sizeof(cl_addr),
			NULL, 0,
			NI_NUMERICHOST);
    if (resolv_client) {
      error = getnameinfo((struct sockaddr *)&cl, len,
			  cl_name, sizeof(cl_name),
			  NULL, 0, 0);
      msg_out(norm, "%s[%s] connected", cl_name, cl_addr);
    } else {
      msg_out(norm, "%s connected", cl_addr);
      strncpy(cl_name, cl_addr, sizeof(cl_name));
    }

    i = validate_access(cl_addr, cl_name);
    if (i < 1) {
      /* access denied */
      close(cs);
      continue;
    }

    set_blocking(cs);

#ifdef USE_THREAD
    if (!threading ) {
#endif
      blocksignal(SIGHUP);
      blocksignal(SIGCHLD);
      pid = fork();
      switch (pid) {
        case -1:  /* fork child failed */
            printf("\nfork failed\n");
            break;
        case 0:   /* i am child */
            for ( i = 0; i < serv_sock_ind; i++ ) {
              close(serv_sock[i]);
            }
            setsignal(SIGCHLD, SIG_DFL);
                setsignal(SIGHUP, SIG_DFL);
                releasesignal(SIGCHLD);
                releasesignal(SIGHUP);
            ss = proto_socks(cs);
            if ( ss == -1 ) {
              close(cs);  /* may already be closed */
              exit(1);
            }
            printf("\nrelaying\n");
            relay(cs, ss);
            exit(0);
      default: /* may be parent */
            printf("\nadding proc\n");
            proclist_add(pid);
            break;
      }
      close(cs);
      releasesignal(SIGHUP);
      releasesignal(SIGCHLD);
#ifdef USE_THREAD
    } else {
      ss = proto_socks(cs);
      if ( ss == -1 ) {
        close(cs);  /* may already be closed */
        continue;
      }
      relay(cs, ss);
    }
#endif
  }
}
Beispiel #2
0
int serv_loop()
{

  SOCKS_STATE	state;
  SOCK_INFO	si;
  CL_INFO	client;

  int    cs;
  fd_set readable;
  int    i, n, len;
  int    error;
  pid_t  pid;

  memset(&state, 0, sizeof(state));
  memset(&si, 0, sizeof(si));
  memset(&client, 0, sizeof(client));
  state.si = &si;

#ifdef USE_THREAD
  if (threading) {
    blocksignal(SIGHUP);
    blocksignal(SIGINT);
    blocksignal(SIGUSR1);
  }
#endif

  for (;;) {
    readable = allsock;

    MUTEX_LOCK(mutex_select);
    n = select(maxsock+1, &readable, 0, 0, 0);
    if (n <= 0) {
      if (n < 0 && errno != EINTR) {
        msg_out(warn, "select: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

#ifdef USE_THREAD
    if ( ! threading ) {
#endif
      /* handle any queued signal flags */
      if (FD_ISSET(sig_queue[0], &readable)) {
        if (ioctl(sig_queue[0], FIONREAD, &i) != 0) {
          msg_out(crit, "ioctl: %m");
          exit(-1);
        }
        while (--i >= 0) {
          char c;
          if (read(sig_queue[0], &c, 1) != 1) {
            msg_out(crit, "read: %m");
            exit(-1);
          }
          switch(c) {
          case 'H': /* sighup */
            reload();
            break;
          case 'C': /* sigchld */
            reapchild();
            break;
          case 'T': /* sigterm */
            cleanup();
            break;
          default:
            break;
          }
        }
      }
#ifdef USE_THREAD
    }
#endif

    for ( i = 0; i < serv_sock_ind; i++ ) {
      if (FD_ISSET(serv_sock[i], &readable)) {
	n--;
	break;
      }
    }
    if ( n < 0 || i >= serv_sock_ind ) {
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

    len = SS_LEN;
    cs = accept(serv_sock[i], &si.prc.addr.sa, (socklen_t *)&len);
    si.prc.len = len;
    if (cs < 0) {
      if (errno == EINTR
#ifdef SOLARIS
	  || errno == EPROTO
#endif
	  || errno == EWOULDBLOCK
	  || errno == ECONNABORTED) {
	; /* ignore */
      } else {
	/* real accept error */
	msg_out(warn, "accept: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }
    MUTEX_UNLOCK(mutex_select);

#ifdef USE_THREAD
    if ( !threading ) {
#endif
      if (max_child > 0 && cur_child >= max_child) {
	msg_out(warn, "child: cur %d; exeedeing max(%d)",
		          cur_child, max_child);
	close(cs);
	continue;
      }
#ifdef USE_THREAD
    }
#endif

    /* get downstream-side socket name */
    len = SS_LEN;
    getsockname(cs, &si.myc.addr.sa, (socklen_t *)&len);
    si.myc.len = len;

    error = getnameinfo(&si.prc.addr.sa, si.prc.len,
			client.addr, sizeof(client.addr),
			NULL, 0,
			NI_NUMERICHOST);
    if (resolv_client) {
      error = getnameinfo(&si.prc.addr.sa, si.prc.len,
			  client.name, sizeof(client.name),
			  NULL, 0, 0);
      msg_out(norm, "%s[%s] connected", client.name, client.addr);
    } else {
      msg_out(norm, "%s connected", client.addr);
      strncpy(client.name, client.addr, sizeof(client.name));
    }

    i = validate_access(&client);
    if (i < 1) {
      /* access denied */
      close(cs);
      continue;
    }

    set_blocking(cs);
    state.s = cs;

#ifdef USE_THREAD
    if (!threading ) {
#endif
      blocksignal(SIGHUP);
      blocksignal(SIGCHLD);
      pid = fork();
      switch (pid) {
      case -1:  /* fork child failed */
	break;
      case 0:   /* i am child */
	for ( i = 0; i < serv_sock_ind; i++ ) {
	  close(serv_sock[i]);
	}
	setsignal(SIGCHLD, SIG_DFL);
        setsignal(SIGHUP, SIG_DFL);
        releasesignal(SIGCHLD);
        releasesignal(SIGHUP);
	error = proto_socks(&state);
	if ( error == -1 ) {
	  close(state.s);  /* may already be closed */
	  exit(1);
	}
	relay(&state);
	exit(0);
      default: /* may be parent */
	proclist_add(pid);
	break;
      }
      close(state.s);
      releasesignal(SIGHUP);
      releasesignal(SIGCHLD);
#ifdef USE_THREAD
    } else {
      error = proto_socks(&state);
      if ( error == -1 ) {
	close(state.s);  /* may already be closed */
	/* udp may be dynamically allocated */
	if (state.sr.udp != NULL)
	  free(state.sr.udp);
	continue;
      }
      relay(&state);
    }
#endif
  }
}