mirror of
https://github.com/traviscross/mtr.git
synced 2024-09-21 18:37:10 +00:00
a31591aa69
- Draw names in red (GTK) or bold (Curses) if host doesn't respond. source: ftp://ftp.bitwizard.nl/mtr/mtr-0.48.tar.gz
271 lines
5.9 KiB
C
271 lines
5.9 KiB
C
/*
|
|
mtr -- a network diagnostic tool
|
|
Copyright (C) 1997,1998 Matt Kimball
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "mtr-curses.h"
|
|
#include "getopt.h"
|
|
#include "display.h"
|
|
#include "dns.h"
|
|
#include "report.h"
|
|
#include "net.h"
|
|
|
|
|
|
#ifndef HAVE_SETEUID
|
|
/* HPUX doesn't have seteuid, but setuid works fine in that case for us */
|
|
#define seteuid setuid
|
|
#endif
|
|
|
|
int DisplayMode;
|
|
int display_mode;
|
|
int Interactive = 1;
|
|
int PrintVersion = 0;
|
|
int PrintHelp = 0;
|
|
int MaxPing = 16;
|
|
float WaitTime = 1.0;
|
|
char *Hostname = NULL;
|
|
char *InterfaceAddress = NULL;
|
|
char LocalHostname[128];
|
|
int dns = 1;
|
|
int packetsize = MINPACKET;
|
|
|
|
void parse_arg(int argc, char **argv) {
|
|
int opt;
|
|
static struct option long_options[] = {
|
|
{ "version", 0, 0, 'v' },
|
|
{ "help", 0, 0, 'h' },
|
|
{ "report", 0, 0, 'r' },
|
|
{ "report-cycles", 1, 0, 'c' },
|
|
{ "curses", 0, 0, 't' },
|
|
{ "gtk", 0, 0, 'g' },
|
|
{ "interval", 1, 0, 'i' },
|
|
{ "psize", 1, 0, 'p' },
|
|
{ "no-dns", 0, 0, 'n' },
|
|
{ "split", 0, 0, 's' }, /* BL */
|
|
{ "address", 1, 0, 'a' },
|
|
{ "raw", 0, 0, 'l' },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
opt = 0;
|
|
while(1) {
|
|
opt = getopt_long(argc, argv, "a:hvrc:tgklnsi:p:", long_options, NULL);
|
|
if(opt == -1)
|
|
break;
|
|
|
|
switch(opt) {
|
|
case 'v':
|
|
PrintVersion = 1;
|
|
break;
|
|
case 'h':
|
|
PrintHelp = 1;
|
|
break;
|
|
case 'r':
|
|
DisplayMode = DisplayReport;
|
|
break;
|
|
case 'c':
|
|
MaxPing = atoi (optarg);
|
|
break;
|
|
case 'p':
|
|
packetsize = atoi (optarg);
|
|
break;
|
|
case 't':
|
|
DisplayMode = DisplayCurses;
|
|
break;
|
|
case 'a':
|
|
InterfaceAddress = optarg;
|
|
break;
|
|
case 'g':
|
|
DisplayMode = DisplayGTK;
|
|
break;
|
|
case 's': /* BL */
|
|
DisplayMode = DisplaySplit;
|
|
break;
|
|
case 'l':
|
|
DisplayMode = DisplayRaw;
|
|
break;
|
|
case 'n':
|
|
dns = 0;
|
|
break;
|
|
case 'i':
|
|
WaitTime = atof (optarg);
|
|
if (WaitTime <= 0.0) {
|
|
fprintf (stderr, "mtr: wait time must be positive\n");
|
|
exit (1);
|
|
}
|
|
if (getuid() != 0 && WaitTime < 1.0)
|
|
WaitTime = 1.0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(DisplayMode == DisplayReport)
|
|
Interactive = 0;
|
|
|
|
if(optind > argc - 1)
|
|
return;
|
|
|
|
Hostname = argv[optind++];
|
|
|
|
if (argc > optind)
|
|
packetsize = atoi(argv[optind]);
|
|
|
|
}
|
|
|
|
|
|
void parse_mtr_options (char *string)
|
|
{
|
|
int argc;
|
|
char *argv[128], *p;
|
|
int i;
|
|
|
|
if (!string) return;
|
|
|
|
argv[0] = "mtr";
|
|
argc = 1;
|
|
p = strtok (string, " \t");
|
|
while (p && (argc < (sizeof(argv)/sizeof(argv[0])))) {
|
|
argv[argc++] = p;
|
|
p = strtok (NULL, " \t");
|
|
}
|
|
if (p) {
|
|
fprintf (stderr, "Warning: extra arguments ignored: %s", p);
|
|
}
|
|
|
|
parse_arg (argc, argv);
|
|
optind = 0;
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
int traddr;
|
|
struct hostent *host;
|
|
int net_preopen_result;
|
|
|
|
/* Get the raw sockets first thing, so we can drop to user euid immediately */
|
|
|
|
net_preopen_result = net_preopen ();
|
|
|
|
/* Now drop to user permissions */
|
|
if(setuid(getuid())) {
|
|
printf("mtr: Unable to drop permissions.\n");
|
|
exit(1);
|
|
}
|
|
|
|
/* Double check, just in case */
|
|
if(geteuid() != getuid()) {
|
|
printf("mtr: Unable to drop permissions.\n");
|
|
exit(1);
|
|
}
|
|
|
|
display_detect(&argc, &argv);
|
|
|
|
parse_mtr_options (getenv ("MTR_OPTIONS"));
|
|
|
|
parse_arg(argc, argv);
|
|
|
|
if(PrintVersion) {
|
|
printf("mtr " VERSION "\n");
|
|
exit(0);
|
|
}
|
|
|
|
if(PrintHelp) {
|
|
printf("usage: %s [-hvrctglsni] [--help] [--version] [--report]\n"
|
|
"\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n"
|
|
"\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */
|
|
"\t\t[--psize=bytes/-p=bytes]\n" /* ok */
|
|
"\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]);
|
|
exit(0);
|
|
}
|
|
if (Hostname == NULL) Hostname = "localhost";
|
|
|
|
if(gethostname(LocalHostname, sizeof(LocalHostname))) {
|
|
strcpy(LocalHostname, "UNKNOWNHOST");
|
|
}
|
|
|
|
if(net_preopen_result != 0) {
|
|
printf("mtr: Unable to get raw socket. (Executable not suid?)\n");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
if(InterfaceAddress) { /* Mostly borrowed from ping(1) code */
|
|
struct sockaddr_in source;
|
|
int i1, i2, i3, i4;
|
|
char dummy;
|
|
extern int sendsock; /* from net.c:115 */
|
|
|
|
source.sin_family = AF_INET;
|
|
source.sin_port = 0;
|
|
|
|
if(sscanf(InterfaceAddress, "%u.%u.%u.%u%c", &i1, &i2, &i3, &i4, &dummy) != 4) {
|
|
printf("mtr: bad interface address: %s\n", InterfaceAddress);
|
|
exit(1);
|
|
} else {
|
|
unsigned char*ptr;
|
|
ptr = (unsigned char*)&source.sin_addr;
|
|
ptr[0] = i1;
|
|
ptr[1] = i2;
|
|
ptr[2] = i3;
|
|
ptr[3] = i4;
|
|
}
|
|
|
|
if(bind(sendsock, (struct sockaddr*)&source, sizeof(source)) == -1) {
|
|
perror("mtr: failed to bind to interface");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
host = gethostbyname(Hostname);
|
|
if(host == NULL) {
|
|
#ifndef NO_HERROR
|
|
herror("mtr");
|
|
#else
|
|
printf("mtr: error looking up \"%s\"\n", Hostname);
|
|
#endif
|
|
exit(1);
|
|
}
|
|
|
|
traddr = *(int *)host->h_addr;
|
|
|
|
if(net_open(traddr) != 0) {
|
|
printf("mtr: Unable to get raw socket. (Executable not suid?)\n");
|
|
exit(1);
|
|
}
|
|
|
|
display_open();
|
|
dns_open();
|
|
|
|
display_mode = 0;
|
|
display_loop();
|
|
|
|
net_end_transit();
|
|
display_close();
|
|
net_close();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|