Diff for /embedaddon/mtr/ui/mtr.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2019/10/21 14:25:31 version 1.1.1.3, 2023/09/27 11:18:58
Line 11 Line 11
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.      GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License    You should have received a copy of the GNU General Public License along
    along with this program; if not, write to the Free Software    with this program; if not, write to the Free Software Foundation, Inc.,
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */  */
   
 #include "config.h"  #include "config.h"
Line 38 Line 38
 #include <sys/limits.h>  #include <sys/limits.h>
 #endif  #endif
   
 #include <netdb.h>  
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <ctype.h>  #include <ctype.h>
Line 63 Line 62
 #include "portability/getopt.h"  #include "portability/getopt.h"
 #endif  #endif
   
#ifdef ENABLE_IPV6char *myname;
#define DEFAULT_AF AF_UNSPEC 
#else 
#define DEFAULT_AF AF_INET 
#endif 
   
   
 const struct fields data_fields[MAXFLD] = {  const struct fields data_fields[MAXFLD] = {
     /* key, Remark, Header, Format, Width, CallBackFunc */      /* key, Remark, Header, Format, Width, CallBackFunc */
     {' ', "<sp>: Space between fields", " ", " ", 1, &net_drop},      {' ', "<sp>: Space between fields", " ", " ", 1, &net_drop},
Line 110  static void __attribute__ ((__noreturn__)) usage(FILE  Line 104  static void __attribute__ ((__noreturn__)) usage(FILE 
           out);            out);
     fputs(" -T, --tcp                  use TCP instead of ICMP echo\n",      fputs(" -T, --tcp                  use TCP instead of ICMP echo\n",
           out);            out);
       fputs(" -I, --interface NAME       use named network interface\n",
            out);
     fputs      fputs
         (" -a, --address ADDRESS      bind the outgoing socket to ADDRESS\n",          (" -a, --address ADDRESS      bind the outgoing socket to ADDRESS\n",
          out);           out);
Line 146  static void __attribute__ ((__noreturn__)) usage(FILE  Line 142  static void __attribute__ ((__noreturn__)) usage(FILE 
     fputs(" -w, --report-wide          output wide report\n", out);      fputs(" -w, --report-wide          output wide report\n", out);
     fputs(" -c, --report-cycles COUNT  set the number of pings sent\n",      fputs(" -c, --report-cycles COUNT  set the number of pings sent\n",
           out);            out);
   #ifdef HAVE_JANSSON
     fputs(" -j, --json                 output json\n", out);      fputs(" -j, --json                 output json\n", out);
   #endif
     fputs(" -x, --xml                  output xml\n", out);      fputs(" -x, --xml                  output xml\n", out);
     fputs(" -C, --csv                  output comma separated values\n",      fputs(" -C, --csv                  output comma separated values\n",
           out);            out);
Line 161  static void __attribute__ ((__noreturn__)) usage(FILE  Line 159  static void __attribute__ ((__noreturn__)) usage(FILE 
 #ifdef HAVE_GTK  #ifdef HAVE_GTK
     fputs(" -g, --gtk                  use GTK+ xwindow interface\n", out);      fputs(" -g, --gtk                  use GTK+ xwindow interface\n", out);
 #endif  #endif
    fputs(" -n, --no-dns               do not resove host names\n", out);    fputs(" -n, --no-dns               do not resolve host names\n", out);
     fputs(" -b, --show-ips             show IP numbers and host names\n",      fputs(" -b, --show-ips             show IP numbers and host names\n",
           out);            out);
     fputs(" -o, --order FIELDS         select output fields\n", out);      fputs(" -o, --order FIELDS         select output fields\n", out);
Line 295  static void init_fld_options( Line 293  static void init_fld_options(
 {  {
     int i;      int i;
   
    memset(ctl->fld_index, -1, FLD_INDEX_SZ);    memset(ctl->fld_index, -1, FLD_INDEX_SZ*sizeof(ctl->fld_index[0]));
   
     for (i = 0; data_fields[i].key != 0; i++) {      for (i = 0; data_fields[i].key != 0; i++) {
         ctl->available_options[i] = data_fields[i].key;          ctl->available_options[i] = data_fields[i].key;
         ctl->fld_index[data_fields[i].key] = i;          ctl->fld_index[data_fields[i].key] = i;
     }      }
       ctl->available_options[i++] = '_';
     ctl->available_options[i] = 0;      ctl->available_options[i] = 0;
 }  }
   
Line 344  static void parse_arg( Line 343  static void parse_arg(
 #endif  #endif
         {"raw", 0, NULL, 'l'},          {"raw", 0, NULL, 'l'},
         {"csv", 0, NULL, 'C'},          {"csv", 0, NULL, 'C'},
   #ifdef HAVE_JANSSON
         {"json", 0, NULL, 'j'},          {"json", 0, NULL, 'j'},
   #endif
         {"displaymode", 1, NULL, OPT_DISPLAYMODE},          {"displaymode", 1, NULL, OPT_DISPLAYMODE},
         {"split", 0, NULL, 'p'},        /* BL */          {"split", 0, NULL, 'p'},        /* BL */
         /* maybe above should change to -d 'x' */          /* maybe above should change to -d 'x' */
Line 363  static void parse_arg( Line 364  static void parse_arg(
         {"bitpattern", 1, NULL, 'B'},   /* overload B>255, ->rand(0,255) */          {"bitpattern", 1, NULL, 'B'},   /* overload B>255, ->rand(0,255) */
         {"tos", 1, NULL, 'Q'},  /* typeof service (0,255) */          {"tos", 1, NULL, 'Q'},  /* typeof service (0,255) */
         {"mpls", 0, NULL, 'e'},          {"mpls", 0, NULL, 'e'},
           {"interface", 1, NULL, 'I'},
         {"address", 1, NULL, 'a'},          {"address", 1, NULL, 'a'},
         {"first-ttl", 1, NULL, 'f'},    /* -f & -m are borrowed from traceroute */          {"first-ttl", 1, NULL, 'f'},    /* -f & -m are borrowed from traceroute */
         {"max-ttl", 1, NULL, 'm'},          {"max-ttl", 1, NULL, 'm'},
Line 439  static void parse_arg( Line 441  static void parse_arg(
         case 'C':          case 'C':
             ctl->DisplayMode = DisplayCSV;              ctl->DisplayMode = DisplayCSV;
             break;              break;
   #ifdef HAVE_JANSSON
         case 'j':          case 'j':
             ctl->DisplayMode = DisplayJSON;              ctl->DisplayMode = DisplayJSON;
             break;              break;
   #endif
         case 'x':          case 'x':
             ctl->DisplayMode = DisplayXML;              ctl->DisplayMode = DisplayXML;
             break;              break;
Line 462  static void parse_arg( Line 466  static void parse_arg(
             ctl->cpacketsize =              ctl->cpacketsize =
                 strtonum_or_err(optarg, "invalid argument", STRTO_INT);                  strtonum_or_err(optarg, "invalid argument", STRTO_INT);
             break;              break;
           case 'I':
               ctl->InterfaceName = optarg;
               break;
         case 'a':          case 'a':
             ctl->InterfaceAddress = optarg;              ctl->InterfaceAddress = optarg;
             break;              break;
Line 476  static void parse_arg( Line 483  static void parse_arg(
             if (ctl->WaitTime <= 0.0) {              if (ctl->WaitTime <= 0.0) {
                 error(EXIT_FAILURE, 0, "wait time must be positive");                  error(EXIT_FAILURE, 0, "wait time must be positive");
             }              }
            if (getuid() != 0 && ctl->WaitTime < 1.0) {            if (!running_as_root() && ctl->WaitTime < 1.0) {
                 error(EXIT_FAILURE, 0,                  error(EXIT_FAILURE, 0,
                       "non-root users cannot request an interval < 1.0 seconds");                        "non-root users cannot request an interval < 1.0 seconds");
             }              }
Line 635  static void parse_arg( Line 642  static void parse_arg(
   
     if (ctl->DisplayMode == DisplayReport ||      if (ctl->DisplayMode == DisplayReport ||
         ctl->DisplayMode == DisplayTXT ||          ctl->DisplayMode == DisplayTXT ||
   #ifdef HAVE_JANSSON
         ctl->DisplayMode == DisplayJSON ||          ctl->DisplayMode == DisplayJSON ||
   #endif
         ctl->DisplayMode == DisplayXML ||          ctl->DisplayMode == DisplayXML ||
         ctl->DisplayMode == DisplayRaw || ctl->DisplayMode == DisplayCSV)          ctl->DisplayMode == DisplayRaw || ctl->DisplayMode == DisplayCSV)
         ctl->Interactive = 0;          ctl->Interactive = 0;
Line 681  static void init_rand( Line 690  static void init_rand(
     srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);      srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
 }  }
   
   /*
       For historical reasons, we need a hostent structure to represent
       our remote target for probing.  The obsolete way of doing this
       would be to use gethostbyname().  We'll use getaddrinfo() instead
       to generate the hostent.
   */
   int get_addrinfo_from_name(
       struct mtr_ctl *ctl,
       struct addrinfo **res,
       const char *name)
   {
       int gai_error;
       struct addrinfo hints;
   
       /* gethostbyname2() is deprecated so we'll use getaddrinfo() instead. */
       memset(&hints, 0, sizeof hints);
       hints.ai_family = ctl->af;
       hints.ai_socktype = SOCK_DGRAM;
       gai_error = getaddrinfo(name, NULL, &hints, res);
       if (gai_error) {
           if (gai_error == EAI_SYSTEM)
               error(0, 0, "Failed to resolve host: %s", name);
           else
               error(0, 0, "Failed to resolve host: %s: %s", name,
                     gai_strerror(gai_error));
   
           return -1;
       }
   
       ctl->af = (*res)->ai_family;
       return 0;
   }
   
   
 int main(  int main(
     int argc,      int argc,
     char **argv)      char **argv)
 {  {
     struct hostent *host = NULL;  
     struct addrinfo hints, *res;  
     int gai_error;  
     struct hostent trhost;  
     char *alptr[2];  
     struct sockaddr_in *sa4;  
 #ifdef ENABLE_IPV6  
     struct sockaddr_in6 *sa6;  
 #endif  
     names_t *names_head = NULL;      names_t *names_head = NULL;
     names_t *names_walk;      names_t *names_walk;
   
       myname = argv[0];
     struct mtr_ctl ctl;      struct mtr_ctl ctl;
     memset(&ctl, 0, sizeof(ctl));      memset(&ctl, 0, sizeof(ctl));
     /* initialize non-null values */      /* initialize non-null values */
Line 761  int main( Line 796  int main(
                      sizeof(ctl.LocalHostname));                       sizeof(ctl.LocalHostname));
         }          }
   
        /* gethostbyname2() is deprecated so we'll use getaddrinfo() instead. */        struct addrinfo *res = NULL;
        memset(&hints, 0, sizeof hints);        if (get_addrinfo_from_name(&ctl, &res, ctl.Hostname) != 0) {
        hints.ai_family = ctl.af; 
        hints.ai_socktype = SOCK_DGRAM; 
        gai_error = getaddrinfo(ctl.Hostname, NULL, &hints, &res); 
        if (gai_error) { 
            if (gai_error == EAI_SYSTEM) 
                error(0, 0, "Failed to resolve host: %s", ctl.Hostname); 
            else 
                error(0, 0, "Failed to resolve host: %s: %s", ctl.Hostname, 
                      gai_strerror(gai_error)); 
 
             if (ctl.Interactive)              if (ctl.Interactive)
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
             else {              else {
Line 780  int main( Line 805  int main(
                 continue;                  continue;
             }              }
         }          }
         /* Convert the first addrinfo into a hostent. */  
         host = &trhost;  
         memset(host, 0, sizeof trhost);  
         host->h_name = res->ai_canonname;  
         host->h_aliases = NULL;  
         host->h_addrtype = res->ai_family;  
         ctl.af = res->ai_family;  
         host->h_length = res->ai_addrlen;  
         host->h_addr_list = alptr;  
         switch (ctl.af) {  
         case AF_INET:  
             sa4 = (struct sockaddr_in *) res->ai_addr;  
             alptr[0] = (void *) &(sa4->sin_addr);  
             break;  
 #ifdef ENABLE_IPV6  
         case AF_INET6:  
             sa6 = (struct sockaddr_in6 *) res->ai_addr;  
             alptr[0] = (void *) &(sa6->sin6_addr);  
             break;  
 #endif  
         default:  
             error(0, 0, "unknown address type");  
             if (ctl.Interactive)  
                 exit(EXIT_FAILURE);  
             else {  
                 names_walk = names_walk->next;  
                 continue;  
             }  
         }  
         alptr[1] = NULL;  
   
        if (net_open(&ctl, host) != 0) {        if (net_open(&ctl, res) != 0) {
             error(0, 0, "Unable to start net module");              error(0, 0, "Unable to start net module");
             if (ctl.Interactive)              if (ctl.Interactive)
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
Line 821  int main( Line 816  int main(
             }              }
         }          }
   
           freeaddrinfo(res);
   
         lock(stdout);          lock(stdout);
        dns_open(&ctl);        dns_open();
         display_open(&ctl);          display_open(&ctl);
   
         display_loop(&ctl);          display_loop(&ctl);

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>