Exemplo n.º 1
0
/* Un client  */
static void* repeater(void* sck)
{
	int sckt = (int) sck;
    char buf[MAX_BUFFER];
    int nbc, i;
    const char WELCOME[] = "mtcs : bienvenu\n";

    pgrs_in();
    write(sckt, WELCOME, strlen(WELCOME));

    pgrs("enregistrement d'une socket");
    add_socket(sckt);
    
    while (1) {
	pgrs("attente read");
	nbc = read(sckt, buf, MAX_BUFFER);
	if (nbc <= 0) {
	    pgrs("fin lecture client");
	    pgrs("desenregistrement d'une socket");
	    del_socket(sckt);
	    close(sckt);
            pgrs_out();
	    return NULL;
	}
	pgrs("boucle ecriture");
	for(i=0; i<MAX_CONNECTION; i++)
	    if (sockets[i])
		write(sockets[i], buf, nbc);
	pgrs("fin boucle ecriture");
    }
    return NULL;
}
Exemplo n.º 2
0
static void serv (void *arg)
{
  int h = *(int *) arg;
  BINKD_CONFIG *config;
#if defined(WITH_PERL) && defined(HAVE_THREADS)
  void *cperl;
#endif

#if defined(HAVE_FORK) && !defined(HAVE_THREADS) && !defined(DEBUGCHILD)
  int curfd;
  pidcmgr = 0;
  for (curfd=0; curfd<sockfd_used; curfd++)
    soclose(sockfd[curfd]);
#endif

  config = lock_current_config();
#if defined(WITH_PERL) && defined(HAVE_THREADS)
  cperl = perl_init_clone(config);
#endif
  protocol (h, h, NULL, NULL, NULL, NULL, NULL, config);
  Log (5, "downing server...");
#if defined(WITH_PERL) && defined(HAVE_THREADS)
  perl_done_clone(cperl);
#endif
  del_socket(h);
  soclose (h);
  free (arg);
  unlock_config_structure(config, 0);
  rel_grow_handles (-6);
#ifdef HAVE_THREADS
  threadsafe(--n_servers);
  PostSem(&eothread);
  ENDTHREAD();
#elif defined(DOS) || defined(DEBUGCHILD)
  --n_servers;
#endif
}
Exemplo n.º 3
0
int RawSocket::open(uint32_t dip, uint16_t dp, uint16_t sp)
{
   int n = 1;
   
   del_socket();
   create_socket();
   
   dst_sin_.sin_family = PF_INET;
   dst_sin_.sin_port = htons(dp);
   dst_sin_.sin_addr.s_addr = dip;
   
   bind_sp(sp);
   if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n)) == -1) 
   {
      logger->PrintErr("[%s:%d] set IP_HDRINCL failed: %s\n", __FILE__, __LINE__, strerror(errno));
      return -1;
   }
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) 
   {
      logger->PrintErr("[%s:%d] set SO_REUSEADDR failed: %s", __FILE__, __LINE__, strerror(errno));
      return -1;
   }
   return 0;
}
Exemplo n.º 4
0
/* destructor */
RawSocket::~RawSocket()
{
   del_socket();
}
Exemplo n.º 5
0
static int call0 (FTN_NODE *node, BINKD_CONFIG *config)
{
  int sockfd = INVALID_SOCKET;
  int sock_out;
  char szDestAddr[FTN_ADDR_SZ + 1];
  int i, rc, pid = -1;
  char host[BINKD_FQDNLEN + 5 + 1];       /* current host/port */
  char addrbuf[BINKD_FQDNLEN + 1];
  char servbuf[MAXSERVNAME + 1];
  char *hosts;
  char *port;
  char *dst_host = host;
  const char *save_err;
#ifdef HTTPS
  int use_proxy;
  char *proxy, *socks;
  struct addrinfo *aiProxyHead;
#endif
  struct addrinfo *ai, *aiNodeHead, *aiHead, hints;
  int aiErr;

  /* setup hints for getaddrinfo */
  memset((void *)&hints, 0, sizeof(hints));
  hints.ai_family = node->IP_afamily;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

#ifdef WITH_PERL
  hosts = xstrdup(node->hosts);
#ifdef HTTPS
  proxy = xstrdup(config->proxy);
  socks = xstrdup(config->socks);
#endif
  if (!perl_on_call(node, config, &hosts
#ifdef HTTPS
                    , &proxy, &socks
#endif
                    )) {
    Log(1, "call aborted by Perl on_call()");
    return 0;
  }
#else
  hosts = node->hosts;
#ifdef HTTPS
  proxy = config->proxy;
  socks = config->socks;
#endif
#endif

  ftnaddress_to_str (szDestAddr, &node->fa);
  Log (2, "call to %s", szDestAddr);
  setproctitle ("call to %s", szDestAddr);

#ifdef HTTPS
  use_proxy = (node->NP_flag != NP_ON) && (!node->pipe || !node->pipe[0]) && (proxy[0] || socks[0]);
  if (use_proxy)
  {
    char *sp, *sport;
    strncpy(host, proxy[0] ? proxy : socks, sizeof(host));
    if ((sp=strchr(host, ':')) != NULL)
    {
      *sp++ = '\0';
      sport = sp;
      if ((sp=strchr(sp, '/')) != NULL)
	*sp++ = '\0';
    }
    else
    {
      if ((sp=strchr(host, '/')) != NULL)
	*sp++ = '\0';
      sport = proxy[0] ? "squid" : "socks"; /* default port */
    }
    /* resolve proxy host */
    if ( (aiErr = srv_getaddrinfo(host, sport, &hints, &aiProxyHead)) != 0)
    {
	Log(2, "Port %s not found, try default %d", sp, proxy[0] ? 3128 : 1080);
	aiErr = getaddrinfo(host, proxy[0] ? "3128" : "1080", &hints, &aiProxyHead);
    }
    if (aiErr != 0)
    {
      Log(1, "%s host %s not found", proxy[0] ? "Proxy" : "Socks", host);
#ifdef WITH_PERL
      xfree(hosts);
#ifdef HTTPS
      xfree(proxy);
      xfree(socks);
#endif
#endif
      return 0;
    }
  }
#endif

  for (i = 1; sockfd == INVALID_SOCKET
       && (rc = get_host_and_port
	   (i, host, &port, hosts, &node->fa, config)) != -1; ++i)
  {
    if (rc == 0)
    {
      Log (1, "%s: %i: error parsing host list", hosts, i);
      continue;
    }

    pid = -1;
    if (node->pipe && node->pipe[0])
    {
      char *cmdline = strdup(node->pipe);
      cmdline = ed(cmdline, "*H", host, NULL);
      cmdline = ed(cmdline, "*I", port, NULL);
      pid = run3(cmdline, &sock_out, &sockfd, NULL);
      free(cmdline);
      if (pid != -1)
      {
	Log (4, "connected");
	add_socket(sock_out);
	break;
      }
      if (!binkd_exit)
      {
	Log (1, "connection to %s failed");
	/* bad_try (&node->fa, "exec error", BAD_CALL, config); */
      }
      sockfd = INVALID_SOCKET;
      continue;
    }

#ifdef HTTPS
    if (use_proxy)
      aiHead = aiProxyHead;
    else /* don't resolve if proxy or socks specified */
#endif
    {
      aiErr = srv_getaddrinfo(host, port, &hints, &aiNodeHead);
     
      if (aiErr != 0)
      {
        bad_try(&node->fa, "Cannot getaddrinfo", BAD_CALL, config);
        continue;
      }
      aiHead = aiNodeHead;
    }

    /* Trying... */

    for (ai = aiHead; ai != NULL && sockfd == INVALID_SOCKET; ai = ai->ai_next)
    {
      if ((sockfd = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == INVALID_SOCKET)
      {
	Log (1, "socket: %s", TCPERR ());

	/* as long as there are more addresses, try those */
        if (ai != NULL) 
          continue;
        else
        {
#ifdef WITH_PERL
	  xfree(hosts);
#ifdef HTTPS
	  xfree(proxy);
	  xfree(socks);
#endif
#endif
	  freeaddrinfo(aiHead);
	  return 0;
	}
      }
      add_socket(sockfd);
      /* Was the socket created after close_sockets loop in exitfunc()? */
      if (binkd_exit)
      {
#ifdef WITH_PERL
	xfree(hosts);
#ifdef HTTPS
	xfree(proxy);
	xfree(socks);
#endif
#endif
	freeaddrinfo(aiHead);
	return 0;
      }
      rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, addrbuf, sizeof(addrbuf),
		       servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV);
      if (rc != 0) {
	Log (2, "Error in getnameinfo(): %s (%d)", gai_strerror(rc), rc);
        snprintf(addrbuf, BINKD_FQDNLEN, "invalid");
	*servbuf = '\0';
      }

#ifdef HTTPS
      if (use_proxy)
      {
	char *sp = strchr(host, ':');
	if (sp) *sp = '\0';
	if (port == config->oport)
	  Log (4, "trying %s via %s %s:%s...", host,
	       proxy[0] ? "proxy" : "socks", addrbuf, servbuf);
	else
	  Log (4, "trying %s:%s via %s %s:%s...", host, port,
	       proxy[0] ? "proxy" : "socks", addrbuf, servbuf);
	sprintf(host+strlen(host), ":%s", port);
      }
      else
#endif
      {
	if (port == config->oport)
          Log (4, "trying %s [%s]...", host, addrbuf);
	else
          Log (4, "trying %s [%s]:%s...", host, addrbuf, servbuf);
      }
      /* find bind addr with matching address family */
      if (config->bindaddr[0])
      {
	struct addrinfo *src_ai, src_hints;
	
	memset((void *)&src_hints, 0, sizeof(src_hints));
	src_hints.ai_socktype = SOCK_STREAM;
	src_hints.ai_family = ai->ai_family;
	src_hints.ai_protocol = IPPROTO_TCP;
	if ((aiErr = getaddrinfo(config->bindaddr, NULL, &src_hints, &src_ai)) == 0)
        {
          if (bind(sockfd, src_ai->ai_addr, src_ai->ai_addrlen))
	    Log(4, "bind: %s", TCPERR());
	  freeaddrinfo(src_ai);
	}
        else
	  if (aiErr == EAI_FAMILY)
	    /* address family of target and bind address don't match */
	    continue;
	  else
	    /* otherwise just warn and don't bind() */
	    Log(2, "bind -- getaddrinfo: %s (%d)", gai_strerror(aiErr), aiErr);
      }
#ifdef HAVE_FORK
      if (config->connect_timeout)
      {
	signal(SIGALRM, alrm);
	alarm(config->connect_timeout);
      }
#endif
      if (connect (sockfd, ai->ai_addr, ai->ai_addrlen) == 0)
      {
#ifdef HAVE_FORK
	alarm(0);
#endif
	Log (4, "connected");
	sock_out = sockfd;
	dst_host = addrbuf;
	break;
      }

#ifdef HAVE_FORK
      if (errno == EINTR && config->connect_timeout)
	save_err = strerror (ETIMEDOUT);
      else
	save_err = TCPERR ();
      alarm(0);
#else
      save_err = TCPERR ();
#endif
      if (!binkd_exit)
      {
	Log (1, "connection to %s failed: %s", szDestAddr, save_err);
	bad_try (&node->fa, save_err, BAD_CALL, config);
      }
      del_socket(sockfd);
      soclose (sockfd);
      sockfd = INVALID_SOCKET;
    }
#ifdef HTTPS
    if (!use_proxy)
#endif
      freeaddrinfo(aiNodeHead);
#ifdef HTTPS
    if (sockfd != INVALID_SOCKET && use_proxy) {
      if (h_connect(sockfd, host, config, proxy, socks) != 0) {
        if (!binkd_exit)
          bad_try (&node->fa, TCPERR (), BAD_CALL, config);
        del_socket(sockfd);
        soclose (sockfd);
        sockfd = INVALID_SOCKET;
      }
      else if (port == config->oport) {
        char *pp;
        if( (pp = strchr(host, ':')) ){
          *pp = '\0';
        }
      }
    }
#endif
  }
#ifdef HTTPS
  if (use_proxy)
    freeaddrinfo(aiProxyHead);
#endif
#ifdef WITH_PERL
  xfree(hosts);
#ifdef HTTPS
  xfree(proxy);
  xfree(socks);
#endif
#endif

  if (sockfd == INVALID_SOCKET)
    return 0;

  protocol (sockfd, sock_out, node, NULL, dst_host, config);
  if (pid != -1)
  {
    del_socket(sock_out);
    close(sock_out);
#ifdef HAVE_WAITPID
    if (waitpid (pid, &rc, 0) == -1)
    {
      Log (1, "waitpid(%u) error: %s", pid, strerror(errno));
    }
    else
    {
      if (WIFSIGNALED(rc))
        Log (2, "process %u exited by signal %u", pid, WTERMSIG(rc));
      else
        Log (4, "rc(%u)=%u", pid, WEXITSTATUS(rc));
    }
#endif
    close(sockfd);
  }
  else
  {
    del_socket(sockfd);
    soclose (sockfd);
  }
  return 1;
}
Exemplo n.º 6
0
static int do_server(BINKD_CONFIG *config)
{
  struct addrinfo *ai, *aiHead, hints;
  int aiErr;
  SOCKET new_sockfd;
  int pid;
  socklen_t client_addr_len;
  struct sockaddr_storage client_addr;
  int opt = 1;
  int save_errno;
  struct listenchain *listen_list;

  /* setup hints for getaddrinfo */
  memset((void *)&hints, 0, sizeof(hints));
  hints.ai_flags = AI_PASSIVE;
  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

  for (listen_list = config->listen.first; listen_list; listen_list = listen_list->next)
  {
    if ((aiErr = getaddrinfo(listen_list->addr[0] ? listen_list->addr : NULL, 
                             listen_list->port, &hints, &aiHead)) != 0)
    {
      Log(0, "servmgr getaddrinfo: %s (%d)", gai_strerror(aiErr), aiErr);
      return -1;
    }

    for (ai = aiHead; ai != NULL && sockfd_used < MAX_LISTENSOCK; ai = ai->ai_next)
    {
      sockfd[sockfd_used] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
      if (sockfd[sockfd_used] < 0)
      {
        Log (0, "servmgr socket(): %s", TCPERR ());
        continue;
      }
#ifdef UNIX /* Not sure how to set NOINHERIT flag for socket on Windows and OS/2 */
      if (fcntl(sockfd[sockfd_used], F_SETFD, FD_CLOEXEC) != 0)
        Log(1, "servmgr fcntl set FD_CLOEXEC error: %s", strerror(errno));
#endif
#ifdef IPV6_V6ONLY
      if (ai->ai_family == PF_INET6)
      {
        int v6only = 1;
        if (setsockopt(sockfd[sockfd_used], IPPROTO_IPV6, IPV6_V6ONLY, 
                 (char *) &v6only, sizeof(v6only)) == SOCKET_ERROR)
          Log(1, "servmgr setsockopt (IPV6_V6ONLY): %s", TCPERR());
      }
#endif
      if (setsockopt (sockfd[sockfd_used], SOL_SOCKET, SO_REUSEADDR,
                    (char *) &opt, sizeof opt) == SOCKET_ERROR)
        Log (1, "servmgr setsockopt (SO_REUSEADDR): %s", TCPERR ());
    
      if (bind (sockfd[sockfd_used], ai->ai_addr, ai->ai_addrlen) != 0)
      {
        Log (0, "servmgr bind(): %s", TCPERR ());
        soclose(sockfd[sockfd_used]);
        continue;
      }
      if (listen (sockfd[sockfd_used], 5) != 0)
      {
        Log(0, "servmgr listen(): %s", TCPERR ());
        soclose(sockfd[sockfd_used]);
        continue;
      }

      sockfd_used++;
    }

    Log (3, "servmgr listen on %s:%s", listen_list->addr[0] ? listen_list->addr : "*", listen_list->port);
  
    freeaddrinfo(aiHead);
  }

  if (sockfd_used == 0) {
    Log(0, "servmgr: No listen socket open");
    return -1;
  }

  setproctitle ("server manager (listen %s)", config->listen.first->port);

  for (;;)
  {
    struct timeval tv;
    int n;
    int curfd, maxfd = 0;
    fd_set r;

    FD_ZERO (&r);
    for (curfd=0; curfd<sockfd_used; curfd++)
    {
      FD_SET (sockfd[curfd], &r);
      if (sockfd[curfd] > maxfd)
        maxfd = sockfd[curfd];
    }
    tv.tv_usec = 0;
    tv.tv_sec  = CHECKCFG_INTERVAL;
    unblocksig();
    check_child(&n_servers);
    n = select(maxfd+1, &r, NULL, NULL, &tv);
    blocksig();
    switch (n)
    { case 0: /* timeout */
        if (checkcfg()) 
        {
          for (curfd=0; curfd<sockfd_used; curfd++)
            soclose(sockfd[curfd]);
          sockfd_used = 0;
          return 0;
        }
        unblocksig();
        check_child(&n_servers);
        blocksig();
        continue;
      case -1:
        save_errno = TCPERRNO;
        if (binkd_exit)
          goto accepterr;
        if (TCPERRNO == EINTR)
        {
          unblocksig();
          check_child(&n_servers);
          blocksig();
          if (checkcfg())
          {
            for (curfd=0; curfd<sockfd_used; curfd++)
              soclose(sockfd[curfd]);
            sockfd_used = 0;
            return 0;
          }
          continue;
        }
        Log (1, "servmgr select(): %s", TCPERR ());
        goto accepterr;
    }
 
    for (curfd=0; curfd<sockfd_used; curfd++)
    {
      if (!FD_ISSET(sockfd[curfd], &r))
        continue;

      client_addr_len = sizeof (client_addr);
      if ((new_sockfd = accept (sockfd[curfd], (struct sockaddr *)&client_addr,
                                &client_addr_len)) == INVALID_SOCKET)
      {
        save_errno = TCPERRNO;
        if (save_errno != EINVAL && save_errno != EINTR)
        {
          if (!binkd_exit)
            Log (1, "servmgr accept(): %s", TCPERR ());
#ifdef UNIX
          if (save_errno == ECONNRESET ||
              save_errno == ETIMEDOUT ||
              save_errno == ECONNABORTED ||
              save_errno == EHOSTUNREACH)
            continue;
#endif
        accepterr:
#ifdef OS2
          /* Buggy external process closed our socket? Or OS/2 bug? */
          if (save_errno == ENOTSOCK)
            return 0;  /* will force socket re-creation */
#endif
          return -1;
        }
      }
      else
      {
        char host[BINKD_FQDNLEN + 1];
        char service[MAXSERVNAME + 1];
        int aiErr;
  
        add_socket(new_sockfd);
        /* Was the socket created after close_sockets loop in exitfunc()? */
        if (binkd_exit)
        {
          del_socket(new_sockfd);
          soclose(new_sockfd);
          continue;
        }
        rel_grow_handles (6);
        ext_rand=rand();
        /* never resolve name in here, will be done during session */
        aiErr = getnameinfo((struct sockaddr *)&client_addr, client_addr_len,
            host, sizeof(host), service, sizeof(service),
            NI_NUMERICHOST | NI_NUMERICSERV);
        if (aiErr == 0) 
          Log (3, "incoming from %s (%s)", host, service);
        else
        {
          Log(2, "Error in getnameinfo(): %s (%d)", gai_strerror(aiErr), aiErr);
          Log(3, "incoming from unknown");
        }
  
        /* Creating a new process for the incoming connection */
        threadsafe(++n_servers);
        if ((pid = branch (serv, (void *) &new_sockfd, sizeof (new_sockfd))) < 0)
        {
          del_socket(new_sockfd);
          soclose(new_sockfd);
          rel_grow_handles (-6);
          threadsafe(--n_servers);
          PostSem(&eothread);
          Log (1, "servmgr branch(): cannot branch out");
          sleep(1);
        }
        else
        {
          Log (5, "started server #%i, id=%i", n_servers, pid);
#if defined(HAVE_FORK) && !defined(HAVE_THREADS)
          soclose (new_sockfd);
#endif
        }
      }
    }
  }
}