Advertisement
Guest User

Untitled

a guest
Dec 1st, 2017
781
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.14 KB | None | 0 0
  1. /*
  2.  * netcat.c -- main project file
  3.  * Part of the GNU netcat project
  4.  *
  5.  * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
  6.  * Copyright (C) 2002 - 2003  Giovanni Giacobbi
  7.  *
  8.  * $Id: netcat.c,v 1.63 2003/08/21 15:27:18 themnemonic Exp $
  9.  */
  10.  
  11. /***************************************************************************
  12.  *                                                                         *
  13.  *   This program is free software; you can redistribute it and/or modify  *
  14.  *   it under the terms of the GNU General Public License as published by  *
  15.  *   the Free Software Foundation; either version 2 of the License, or     *
  16.  *   (at your option) any later version.                                   *
  17.  *                                                                         *
  18.  *   This program is distributed in the hope that it will be useful,       *
  19.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  20.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  21.  *   GNU General Public License for more details.                          *
  22.  *                                                                         *
  23.  ***************************************************************************/
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. #include "config.h"
  27. #endif
  28.  
  29. #include "netcat.h"
  30. #include <signal.h>
  31. #include <getopt.h>
  32. #include <time.h>       /* time(2) used as random seed */
  33.  
  34. /* int gatesidx = 0; */     /* LSRR hop count */
  35. /* int gatesptr = 4; */     /* initial LSRR pointer, settable */
  36. /* nc_host_t **gates = NULL; */ /* LSRR hop hostpoop */
  37. /* char *optbuf = NULL; */  /* LSRR or sockopts */
  38. FILE *output_fp = NULL;     /* output fd (FIXME: i don't like this) */
  39. bool use_stdin = TRUE;      /* tells wether stdin was closed or not */
  40. bool signal_handler = TRUE; /* handle the signals externally */
  41. bool got_sigterm = FALSE;   /* when this TRUE the application must exit */
  42. bool got_sigint = FALSE;    /* when this TRUE the application should exit */
  43. bool got_sigusr1 = FALSE;   /* when set, the application should print stats */
  44. bool commandline_need_newline = FALSE;  /* fancy output handling */
  45.  
  46. /* global options flags */
  47. nc_mode_t netcat_mode = 0;  /* Netcat working modality */
  48. bool opt_eofclose = FALSE;  /* close connection on EOF from stdin */
  49. bool opt_debug = FALSE;     /* debugging output */
  50. bool opt_numeric = FALSE;   /* don't resolve hostnames */
  51. bool opt_random = FALSE;    /* use random ports */
  52. bool opt_udpmode = FALSE;   /* use udp protocol instead of tcp */
  53. bool opt_telnet = FALSE;    /* answer in telnet mode */
  54. bool opt_hexdump = FALSE;   /* hexdump traffic */
  55. bool opt_zero = FALSE;      /* zero I/O mode (don't expect anything) */
  56. int opt_interval = 0;       /* delay (in seconds) between lines/ports */
  57. int opt_verbose = 0;        /* be verbose (> 1 to be MORE verbose) */
  58. int opt_wait = 0;       /* wait time */
  59. char *opt_outputfile = NULL;    /* hexdump output file */
  60. char *opt_exec = NULL;      /* program to exec after connecting */
  61. nc_proto_t opt_proto = NETCAT_PROTO_TCP; /* protocol to use for connections */
  62.  
  63.  
  64. /* signal handling */
  65.  
  66. static void got_term(int z)
  67. {
  68.   if (!got_sigterm)
  69.     ncprint(NCPRINT_VERB1, _("Terminated."));
  70.   debug_v(("_____ RECEIVED SIGTERM _____ [signal_handler=%s]",
  71.       BOOL_TO_STR(signal_handler)));
  72.   got_sigterm = TRUE;
  73.   if (signal_handler)           /* default action */
  74.     exit(EXIT_FAILURE);
  75. }
  76.  
  77. static void got_int(int z)
  78. {
  79.   if (!got_sigint)
  80.     ncprint(NCPRINT_VERB1, _("Exiting."));
  81.   debug_v(("_____ RECEIVED SIGINT _____ [signal_handler=%s]",
  82.       BOOL_TO_STR(signal_handler)));
  83.   got_sigint = TRUE;
  84.   if (signal_handler) {         /* default action */
  85.     if (commandline_need_newline)   /* if we were waiting for input */
  86.       printf("\n");
  87.     netcat_printstats(FALSE);
  88.     exit(EXIT_FAILURE);
  89.   }
  90. }
  91.  
  92. static void got_usr1(int z)
  93. {
  94.   debug_dv(("_____ RECEIVED SIGUSR1 _____ [signal_handler=%s]",
  95.        BOOL_TO_STR(signal_handler)));
  96.   if (signal_handler)           /* default action */
  97.     netcat_printstats(TRUE);
  98.   else
  99.     got_sigusr1 = TRUE;
  100. }
  101.  
  102. /* Execute an external file making its stdin/stdout/stderr the actual socket */
  103.  
  104. static void ncexec(nc_sock_t *ncsock)
  105. {
  106.   int saved_stderr;
  107.   char *p;
  108.   assert(ncsock && (ncsock->fd >= 0));
  109.  
  110.   /* save the stderr fd because we may need it later */
  111.   saved_stderr = dup(STDERR_FILENO);
  112.  
  113.   /* duplicate the socket for the child program */
  114.   dup2(ncsock->fd, STDIN_FILENO);   /* the precise order of fiddlage */
  115.   close(ncsock->fd);            /* is apparently crucial; this is */
  116.   dup2(STDIN_FILENO, STDOUT_FILENO);    /* swiped directly out of "inetd". */
  117.   dup2(STDIN_FILENO, STDERR_FILENO);    /* also duplicate the stderr channel */
  118.  
  119.   /* change the label for the executed program */
  120.   if ((p = strrchr(opt_exec, '/')))
  121.     p++;            /* shorter argv[0] */
  122.   else
  123.     p = opt_exec;
  124.  
  125.   /* replace this process with the new one */
  126. #ifndef USE_OLD_COMPAT
  127.   execl("/bin/sh", p, "-c", opt_exec, NULL);
  128. #else
  129.   execl(opt_exec, p, NULL);
  130. #endif
  131.   dup2(saved_stderr, STDERR_FILENO);
  132.   ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't execute %s: %s"),
  133.       opt_exec, strerror(errno));
  134. }               /* end of ncexec() */
  135.  
  136. /* main: handle command line arguments and listening status */
  137.  
  138. int main(int argc, char *argv[])
  139. {
  140.   int c, glob_ret = EXIT_FAILURE;
  141.   int total_ports, left_ports, accept_ret = -1, connect_ret = -1;
  142.   struct sigaction sv;
  143.   nc_port_t local_port;     /* local port specified with -p option */
  144.   nc_host_t local_host;     /* local host for bind()ing operations */
  145.   nc_host_t remote_host;
  146.   nc_sock_t listen_sock;
  147.   nc_sock_t connect_sock;
  148.   nc_sock_t stdio_sock;
  149.  
  150.   memset(&local_port, 0, sizeof(local_port));
  151.   memset(&local_host, 0, sizeof(local_host));
  152.   memset(&remote_host, 0, sizeof(remote_host));
  153.   memset(&listen_sock, 0, sizeof(listen_sock));
  154.   memset(&connect_sock, 0, sizeof(listen_sock));
  155.   memset(&stdio_sock, 0, sizeof(stdio_sock));
  156.   listen_sock.domain = PF_INET;
  157.   connect_sock.domain = PF_INET;
  158.  
  159. #ifdef ENABLE_NLS
  160.   setlocale(LC_MESSAGES, "");
  161.   bindtextdomain(PACKAGE, LOCALEDIR);
  162.   textdomain(PACKAGE);
  163. #endif
  164.  
  165.   /* set up the signal handling system */
  166.   sigemptyset(&sv.sa_mask);
  167.   sv.sa_flags = 0;
  168.   sv.sa_handler = got_int;
  169.   sigaction(SIGINT, &sv, NULL);
  170.   sv.sa_handler = got_term;
  171.   sigaction(SIGTERM, &sv, NULL);
  172.   sv.sa_handler = got_usr1;
  173.   sigaction(SIGUSR1, &sv, NULL);
  174.   /* ignore some boring signals */
  175.   sv.sa_handler = SIG_IGN;
  176.   sigaction(SIGPIPE, &sv, NULL);
  177.   sigaction(SIGURG, &sv, NULL);
  178.  
  179.   /* if no args given at all, take them from stdin and generate argv */
  180.   if (argc == 1)
  181.     netcat_commandline_read(&argc, &argv);
  182.  
  183.   /* check for command line switches */
  184.   while (TRUE) {
  185.     int option_index = 0;
  186.     static const struct option long_options[] = {
  187.     { "close",  no_argument,        NULL, 'c' },
  188.     { "debug",  no_argument,        NULL, 'd' },
  189.     { "exec",   required_argument,  NULL, 'e' },
  190.     { "gateway",    required_argument,  NULL, 'g' },
  191.     { "pointer",    required_argument,  NULL, 'G' },
  192.     { "help",   no_argument,        NULL, 'h' },
  193.     { "interval",   required_argument,  NULL, 'i' },
  194.     { "listen", no_argument,        NULL, 'l' },
  195.     { "tunnel", required_argument,  NULL, 'L' },
  196.     { "dont-resolve", no_argument,      NULL, 'n' },
  197.     { "output", required_argument,  NULL, 'o' },
  198.     { "local-port", required_argument,  NULL, 'p' },
  199.     { "tunnel-port", required_argument, NULL, 'P' },
  200.     { "randomize",  no_argument,        NULL, 'r' },
  201.     { "source", required_argument,  NULL, 's' },
  202.     { "tunnel-source", required_argument,   NULL, 'S' },
  203. #ifndef USE_OLD_COMPAT
  204.     { "tcp",    no_argument,        NULL, 't' },
  205.     { "telnet", no_argument,        NULL, 'T' },
  206. #else
  207.     { "tcp",    no_argument,        NULL, 1 },
  208.     { "telnet", no_argument,        NULL, 't' },
  209. #endif
  210.     { "udp",    no_argument,        NULL, 'u' },
  211.     { "verbose",    no_argument,        NULL, 'v' },
  212.     { "version",    no_argument,        NULL, 'V' },
  213.     { "hexdump",    no_argument,        NULL, 'x' },
  214.     { "wait",   required_argument,  NULL, 'w' },
  215.     { "zero",   no_argument,        NULL, 'z' },
  216.     { 0, 0, 0, 0 }
  217.     };
  218.  
  219.     c = getopt_long(argc, argv, "cde:g:G:hi:lL:no:p:P:rs:S:tTuvVxw:z",
  220.             long_options, &option_index);
  221.     if (c == -1)
  222.       break;
  223.  
  224.     switch (c) {
  225.     case 'c':           /* close connection on EOF from stdin */
  226.       opt_eofclose = TRUE;
  227.       break;
  228.     case 'd':           /* enable debugging */
  229.       opt_debug = TRUE;
  230.       break;
  231.     case 'e':           /* prog to exec */
  232.       if (opt_exec)
  233.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  234.         _("Cannot specify `-e' option double"));
  235.       opt_exec = strdup(optarg);
  236.       break;
  237.     case 'G':           /* srcrt gateways pointer val */
  238.       break;
  239.     case 'g':           /* srcroute hop[s] */
  240.       break;
  241.     case 'h':           /* display help and exit */
  242.       netcat_printhelp(argv[0]);
  243.       exit(EXIT_SUCCESS);
  244.     case 'i':           /* line/ports interval time (seconds) */
  245.       opt_interval = atoi(optarg);
  246.       if (opt_interval <= 0)
  247.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  248.         _("Invalid interval time \"%s\""), optarg);
  249.       break;
  250.     case 'l':           /* mode flag: listen mode */
  251.       if (netcat_mode != NETCAT_UNSPEC)
  252.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  253.         _("You can specify mode flags (`-l' and `-L') only once"));
  254.       netcat_mode = NETCAT_LISTEN;
  255.       break;
  256.     case 'L':           /* mode flag: tunnel mode */
  257.       if (netcat_mode != NETCAT_UNSPEC)
  258.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  259.         _("You can specify mode flags (`-l' and `-L') only once"));
  260.       if (opt_zero)
  261.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  262.         _("`-L' and `-z' options are incompatible"));
  263.       do {
  264.     char *div = strchr(optarg, ':');
  265.  
  266.     if (div && *(div + 1))
  267.       *div++ = '\0';
  268.     else
  269.       ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  270.         _("Invalid target string for `-L' option"));
  271.  
  272.     /* lookup the remote address and the remote port for tunneling */
  273.     if (!netcat_resolvehost(&connect_sock.host, optarg))
  274.       ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  275.           _("Couldn't resolve tunnel target host: %s"), optarg);
  276.     if (!netcat_getport(&connect_sock.port, div, 0))
  277.       ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  278.           _("Invalid tunnel target port: %s"), div);
  279.  
  280.     connect_sock.proto = opt_proto;
  281.     connect_sock.timeout = opt_wait;
  282.     netcat_mode = NETCAT_TUNNEL;
  283.       } while (FALSE);
  284.       break;
  285.     case 'n':           /* numeric-only, no DNS lookups */
  286.       opt_numeric = TRUE;
  287.       break;
  288.     case 'o':           /* output hexdump log to file */
  289.       opt_outputfile = strdup(optarg);
  290.       opt_hexdump = TRUE;   /* implied */
  291.       break;
  292.     case 'p':           /* local source port */
  293.       if (!netcat_getport(&local_port, optarg, 0))
  294.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid local port: %s"),
  295.         optarg);
  296.       break;
  297.     case 'P':           /* used only in tunnel mode (source port) */
  298.       if (!netcat_getport(&connect_sock.local_port, optarg, 0))
  299.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  300.         _("Invalid tunnel connect port: %s"), optarg);
  301.       break;
  302.     case 'r':           /* randomize various things */
  303.       opt_random = TRUE;
  304.       break;
  305.     case 's':           /* local source address */
  306.       /* lookup the source address and assign it to the connection address */
  307.       if (!netcat_resolvehost(&local_host, optarg))
  308.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  309.         _("Couldn't resolve local host: %s"), optarg);
  310.       break;
  311.     case 'S':           /* used only in tunnel mode (source ip) */
  312.       if (!netcat_resolvehost(&connect_sock.local_host, optarg))
  313.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  314.         _("Couldn't resolve tunnel local host: %s"), optarg);
  315.       break;
  316.     case 1:         /* use TCP protocol (default) */
  317. #ifndef USE_OLD_COMPAT
  318.     case 't':
  319. #endif
  320.       opt_proto = NETCAT_PROTO_TCP;
  321.       break;
  322. #ifdef USE_OLD_COMPAT
  323.     case 't':
  324. #endif
  325.     case 'T':           /* answer telnet codes */
  326.       opt_telnet = TRUE;
  327.       break;
  328.     case 'u':           /* use UDP protocol */
  329.       opt_proto = NETCAT_PROTO_UDP;
  330.       break;
  331.     case 'v':           /* be verbose (twice=more verbose) */
  332.       opt_verbose++;
  333.       break;
  334.     case 'V':           /* display version and exit */
  335.       netcat_printversion();
  336.       exit(EXIT_SUCCESS);
  337.     case 'w':           /* wait time (in seconds) */
  338.       opt_wait = atoi(optarg);
  339.       if (opt_wait <= 0)
  340.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid wait-time: %s"),
  341.         optarg);
  342.       break;
  343.     case 'x':           /* hexdump traffic */
  344.       opt_hexdump = TRUE;
  345.       break;
  346.     case 'z':           /* little or no data xfer */
  347.       if (netcat_mode == NETCAT_TUNNEL)
  348.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  349.         _("`-L' and `-z' options are incompatible"));
  350.       opt_zero = TRUE;
  351.       break;
  352.     default:
  353.       ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
  354.     }
  355.   }
  356.  
  357.   if (opt_zero && opt_exec)
  358.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  359.         _("`-e' and `-z' options are incompatible"));
  360.  
  361.   /* initialize the flag buffer to keep track of the specified ports */
  362.   netcat_flag_init(65535);
  363.  
  364. #ifndef DEBUG
  365.   /* check for debugging support */
  366.   if (opt_debug)
  367.     ncprint(NCPRINT_WARNING,
  368.         _("Debugging support not compiled, option `-d' discarded. Using maximum verbosity."));
  369. #endif
  370.  
  371.   /* randomize only if needed */
  372.   if (opt_random)
  373. #ifdef USE_RANDOM
  374.     SRAND(time(0));
  375. #else
  376.     ncprint(NCPRINT_WARNING,
  377.         _("Randomization support not compiled, option `-r' discarded."));
  378. #endif
  379.  
  380.   /* handle the -o option. exit on failure */
  381.   if (opt_outputfile) {
  382.     output_fp = fopen(opt_outputfile, "w");
  383.     if (!output_fp)
  384.       ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Failed to open output file: %s"),
  385.           strerror(errno));
  386.   }
  387.   else
  388.     output_fp = stderr;
  389.  
  390.   debug_v(("Trying to parse non-args parameters (argc=%d, optind=%d)", argc,
  391.       optind));
  392.  
  393.   /* try to get an hostname parameter */
  394.   if (optind < argc) {
  395.     char *myhost = argv[optind++];
  396.     if (!netcat_resolvehost(&remote_host, myhost))
  397.       ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't resolve host \"%s\""),
  398.           myhost);
  399.   }
  400.  
  401.   /* now loop all the other (maybe optional) parameters for port-ranges */
  402.   while (optind < argc) {
  403.     const char *get_argv = argv[optind++];
  404.     char *q, *parse = strdup(get_argv);
  405.     int port_lo = 0, port_hi = 65535;
  406.     nc_port_t port_tmp;
  407.  
  408.     if (!(q = strchr(parse, '-')))  /* simple number? */
  409.       q = strchr(parse, ':');       /* try with the other separator */
  410.  
  411.     if (!q) {
  412.       if (netcat_getport(&port_tmp, parse, 0))
  413.     netcat_flag_set(port_tmp.num, TRUE);
  414.       else
  415.     goto got_err;
  416.     }
  417.     else {      /* could be in the forms: N1-N2, -N2, N1- */
  418.       *q++ = 0;
  419.       if (*parse) {
  420.     if (netcat_getport(&port_tmp, parse, 0))
  421.       port_lo = port_tmp.num;
  422.     else
  423.       goto got_err;
  424.       }
  425.       if (*q) {
  426.     if (netcat_getport(&port_tmp, q, 0))
  427.       port_hi = port_tmp.num;
  428.     else
  429.       goto got_err;
  430.       }
  431.       if (!*parse && !*q)       /* don't accept the form '-' */
  432.     goto got_err;
  433.  
  434.       /* now update the flagset (this is int, so it's ok even if hi == 65535) */
  435.       while (port_lo <= port_hi)
  436.     netcat_flag_set(port_lo++, TRUE);
  437.     }
  438.  
  439.     free(parse);
  440.     continue;
  441.  
  442.  got_err:
  443.     free(parse);
  444.     ncprint(NCPRINT_ERROR, _("Invalid port specification: %s"), get_argv);
  445.     exit(EXIT_FAILURE);
  446.   }
  447.  
  448.   debug_dv(("Arguments parsing complete! Total ports=%d", netcat_flag_count()));
  449. #if 0
  450.   /* pure debugging code */
  451.   c = 0;
  452.   while ((c = netcat_flag_next(c))) {
  453.     printf("Got port=%d\n", c);
  454.   }
  455.   exit(0);
  456. #endif
  457.  
  458.   /* Handle listen mode and tunnel mode (whose index number is higher) */
  459.   if (netcat_mode > NETCAT_CONNECT) {
  460.     /* in tunnel mode the opt_zero flag is illegal, while on listen mode it
  461.        means that no connections should be accepted.  For UDP it means that
  462.        no remote addresses should be used as default endpoint, which means
  463.        that we can't send anything.  In both situations, stdin is no longer
  464.        useful, so close it. */
  465.     if (opt_zero) {
  466.       close(STDIN_FILENO);
  467.       use_stdin = FALSE;
  468.     }
  469.  
  470.     /* prepare the socket var and start listening */
  471.     listen_sock.proto = opt_proto;
  472.     listen_sock.timeout = opt_wait;
  473.     memcpy(&listen_sock.local_host, &local_host, sizeof(listen_sock.local_host));
  474.     memcpy(&listen_sock.local_port, &local_port, sizeof(listen_sock.local_port));
  475.     memcpy(&listen_sock.host, &remote_host, sizeof(listen_sock.host));
  476.     accept_ret = core_listen(&listen_sock);
  477.  
  478.     /* in zero I/O mode the core_tcp_listen() call will always return -1
  479.        (ETIMEDOUT) since no connections are accepted, because of this our job
  480.        is completed now. */
  481.     if (accept_ret < 0) {
  482.       /* since i'm planning to make `-z' compatible with `-L' I need to check
  483.          the exact error that caused this failure. */
  484.       if (opt_zero && (errno == ETIMEDOUT))
  485.     exit(0);
  486.  
  487.       ncprint(NCPRINT_VERB1 | NCPRINT_EXIT, _("Listen mode failed: %s"),
  488.           strerror(errno));
  489.     }
  490.  
  491.     /* if we are in listen mode, run the core loop and exit when it returns.
  492.        otherwise now it's the time to connect to the target host and tunnel
  493.        them together (which means passing to the next section. */
  494.     if (netcat_mode == NETCAT_LISTEN) {
  495.       if (opt_exec) {
  496.     ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
  497.     ncexec(&listen_sock);       /* this won't return */
  498.       }
  499.       core_readwrite(&listen_sock, &stdio_sock);
  500.       debug_dv(("Listen: EXIT"));
  501.     }
  502.     else {
  503.       /* otherwise we are in tunnel mode.  The connect_sock var was already
  504.          initialized by the command line arguments. */
  505.       assert(netcat_mode == NETCAT_TUNNEL);
  506.       connect_ret = core_connect(&connect_sock);
  507.  
  508.       /* connection failure? (we cannot get this in UDP mode) */
  509.       if (connect_ret < 0) {
  510.     assert(opt_proto != NETCAT_PROTO_UDP);
  511.     ncprint(NCPRINT_VERB1, "%s: %s",
  512.         netcat_strid(&connect_sock.host, &connect_sock.port),
  513.         strerror(errno));
  514.       }
  515.       else {
  516.     glob_ret = EXIT_SUCCESS;
  517.     core_readwrite(&listen_sock, &connect_sock);
  518.     debug_dv(("Tunnel: EXIT (ret=%d)", glob_ret));
  519.       }
  520.     }
  521.  
  522.     /* all jobs should be ok, go to the cleanup */
  523.     goto main_exit;
  524.   }             /* end of listen and tunnel mode handling */
  525.  
  526.   /* we need to connect outside, this is the connect mode */
  527.   netcat_mode = NETCAT_CONNECT;
  528.  
  529.   /* first check that a host parameter was given */
  530.   if (!remote_host.iaddrs[0].s_addr) {
  531.     /* FIXME: The Networking specifications state that host address "0" is a
  532.        valid host to connect to but this broken check will assume as not
  533.        specified. */
  534.     ncprint(NCPRINT_NORMAL, _("%s: missing hostname argument"), argv[0]);
  535.     ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
  536.   }
  537.  
  538.   /* since ports are the second argument, checking ports might be enough */
  539.   total_ports = netcat_flag_count();
  540.   if (total_ports == 0)
  541.     ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
  542.         _("No ports specified for connection"));
  543.  
  544.   c = 0;            /* must be set to 0 for netcat_flag_next() */
  545.   left_ports = total_ports;
  546.   while (left_ports > 0) {
  547.     /* `c' is the port number independently of the sorting method (linear
  548.        or random).  While in linear mode it is also used to fetch the next
  549.        port number */
  550.     if (opt_random)
  551.       c = netcat_flag_rand();
  552.     else
  553.       c = netcat_flag_next(c);
  554.     left_ports--;       /* decrease the total ports number to try */
  555.  
  556.     /* since we are nonblocking now, we can start as many connections as we want
  557.        but it's not a great idea connecting more than one host at time */
  558.     connect_sock.proto = opt_proto;
  559.     connect_sock.timeout = opt_wait;
  560.     memcpy(&connect_sock.local_host, &local_host,
  561.        sizeof(connect_sock.local_host));
  562.     memcpy(&connect_sock.local_port, &local_port,
  563.        sizeof(connect_sock.local_port));
  564.     memcpy(&connect_sock.host, &remote_host, sizeof(connect_sock.host));
  565.     netcat_getport(&connect_sock.port, NULL, c);
  566.  
  567.     /* FIXME: in udp mode and NETCAT_CONNECT, opt_zero is senseless */
  568.     connect_ret = core_connect(&connect_sock);
  569.  
  570.     /* connection failure? (we cannot get this in UDP mode) */
  571.     if (connect_ret < 0) {
  572.       int ncprint_flags = NCPRINT_VERB1;
  573.       assert(connect_sock.proto != NETCAT_PROTO_UDP);
  574.  
  575.       /* if we are portscanning or multiple connecting show only open
  576.          ports with verbosity level 1. */
  577.       if (total_ports > 1)
  578.     ncprint_flags = NCPRINT_VERB2;
  579.  
  580.       ncprint(ncprint_flags, "%s: %s",
  581.           netcat_strid(&connect_sock.host, &connect_sock.port),
  582.           strerror(errno));
  583.       continue;         /* go with next port */
  584.     }
  585.  
  586.     /* when portscanning (or checking a single port) we are happy if AT LEAST
  587.        ONE port is available. */
  588.     glob_ret = EXIT_SUCCESS;
  589.  
  590.     if (opt_zero) {
  591.       shutdown(connect_ret, 2);
  592.       close(connect_ret);
  593.     }
  594.     else {
  595.       if (opt_exec) {
  596.     ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
  597.     ncexec(&connect_sock);      /* this won't return */
  598.       }
  599.       core_readwrite(&connect_sock, &stdio_sock);
  600.       /* FIXME: add a small delay */
  601.       debug_v(("Connect: EXIT"));
  602.  
  603.       /* both signals are handled inside core_readwrite(), but while the
  604.          SIGINT signal is fully handled, the SIGTERM requires some action
  605.          from outside that function, because of this that flag is not
  606.          cleared. */
  607.       if (got_sigterm)
  608.     break;
  609.     }
  610.   }         /* end of while (left_ports > 0) */
  611.  
  612.   /* all basic modes should return here for the final cleanup */
  613.  main_exit:
  614.   debug_v(("Main: EXIT (cleaning up)"));
  615.  
  616.   netcat_printstats(FALSE);
  617.   return glob_ret;
  618. }               /* end of main() */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement