Skip to content
sockfilt.c 32 KiB
Newer Older
    }
    else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv6";
      use_ipv6 = TRUE;
#endif
      arg++;
    }
    else if(!strcmp("--ipv4", argv[arg])) {
      /* for completeness, we support this option as well */
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv4";
      use_ipv6 = FALSE;
#endif
    else if(!strcmp("--bindonly", argv[arg])) {
      bind_only = TRUE;
      arg++;
    }
    else if(!strcmp("--port", argv[arg])) {
      arg++;
      if(argc>arg) {
Yang Tse's avatar
 
Yang Tse committed
        char *endptr;
Yang Tse's avatar
 
Yang Tse committed
        unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
Yang Tse's avatar
 
Yang Tse committed
        if((endptr != argv[arg] + strlen(argv[arg])) ||
Yang Tse's avatar
 
Yang Tse committed
           ((ulnum != 0UL) && ((ulnum < 1025UL) || (ulnum > 65535UL)))) {
Yang Tse's avatar
 
Yang Tse committed
          fprintf(stderr, "sockfilt: invalid --port argument (%s)\n",
                  argv[arg]);
          return 0;
        }
Yang Tse's avatar
 
Yang Tse committed
        port = curlx_ultous(ulnum);
        arg++;
      }
    }
    else if(!strcmp("--connect", argv[arg])) {
      /* Asked to actively connect to the specified local port instead of
         doing a passive server-style listening. */
      arg++;
      if(argc>arg) {
Yang Tse's avatar
 
Yang Tse committed
        char *endptr;
Yang Tse's avatar
 
Yang Tse committed
        unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
Yang Tse's avatar
 
Yang Tse committed
        if((endptr != argv[arg] + strlen(argv[arg])) ||
Yang Tse's avatar
 
Yang Tse committed
           (ulnum < 1025UL) || (ulnum > 65535UL)) {
Yang Tse's avatar
 
Yang Tse committed
          fprintf(stderr, "sockfilt: invalid --connect argument (%s)\n",
                  argv[arg]);
          return 0;
        }
Yang Tse's avatar
 
Yang Tse committed
        connectport = curlx_ultous(ulnum);
    else if(!strcmp("--addr", argv[arg])) {
      /* Set an IP address to use with --connect; otherwise use localhost */
      arg++;
      if(argc>arg) {
        addr = argv[arg];
        arg++;
      }
    }
    else {
      puts("Usage: sockfilt [option]\n"
           " --version\n"
           " --logfile [file]\n"
           " --pidfile [file]\n"
           " --ipv4\n"
           " --ipv6\n"
           " --port [port]\n"
           " --connect [port]\n"
           " --addr [address]");
#ifdef WIN32
#ifdef ENABLE_IPV6
  if(!use_ipv6)
#endif
    sock = socket(AF_INET, SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
  else
    sock = socket(AF_INET6, SOCK_STREAM, 0);
#endif
  if(CURL_SOCKET_BAD == sock) {
    error = SOCKERRNO;
    logmsg("Error creating socket: (%d) %s",
           error, strerror(error));
    write_stdout("FAIL\n", 5);
    goto sockfilt_cleanup;

  if(connectport) {
    /* Active mode, we should connect to the given port number */
    mode = ACTIVE;
#ifdef ENABLE_IPV6
    if(!use_ipv6) {
#endif
      memset(&me.sa4, 0, sizeof(me.sa4));
      me.sa4.sin_family = AF_INET;
      me.sa4.sin_port = htons(connectport);
      me.sa4.sin_addr.s_addr = INADDR_ANY;
      Curl_inet_pton(AF_INET, addr, &me.sa4.sin_addr);
      rc = connect(sock, &me.sa, sizeof(me.sa4));
      memset(&me.sa6, 0, sizeof(me.sa6));
      me.sa6.sin6_family = AF_INET6;
      me.sa6.sin6_port = htons(connectport);
      Curl_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
      rc = connect(sock, &me.sa, sizeof(me.sa6));
      logmsg("Error connecting to port %hu: (%d) %s",
             connectport, error, strerror(error));
      write_stdout("FAIL\n", 5);
      goto sockfilt_cleanup;
    }
    logmsg("====> Client connect");
    msgsock = sock; /* use this as stream */
  }
  else {
    /* passive daemon style */
    sock = sockdaemon(sock, &port);
    if(CURL_SOCKET_BAD == sock) {
      write_stdout("FAIL\n", 5);
      goto sockfilt_cleanup;
    msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
  logmsg("Running %s version", ipv_inuse);
    logmsg("Connected to port %hu", connectport);
  else if(bind_only)
    logmsg("Bound without listening on port %hu", port);
    logmsg("Listening on port %hu", port);
  wrotepidfile = write_pidfile(pidname);
  if(!wrotepidfile) {
    write_stdout("FAIL\n", 5);
    goto sockfilt_cleanup;
Yang Tse's avatar
 
Yang Tse committed
  do {
    juggle_again = juggle(&msgsock, sock, &mode);
  } while(juggle_again);
sockfilt_cleanup:

  if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
    sclose(msgsock);

  if(sock != CURL_SOCKET_BAD)
    unlink(pidname);

  restore_signal_handlers();

  if(got_exit_signal) {
    logmsg("============> sockfilt exits with signal (%d)", exit_signal);
    /*
     * To properly set the return status of the process we
     * must raise the same signal SIGINT or SIGTERM that we
     * caught and let the old handler take care of it.
     */
    raise(exit_signal);
  }
  logmsg("============> sockfilt quits");