version 1.1, 2019/10/21 14:25:31
|
version 1.1.1.2, 2021/03/17 00:07:30
|
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 70
|
Line 70
|
#endif |
#endif |
|
|
|
|
|
char *myname; |
|
|
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 112 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 161 static void __attribute__ ((__noreturn__)) usage(FILE
|
Line 165 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 299 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 349 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 370 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 447 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 472 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 489 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 648 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 696 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. |
|
*/ |
|
static int get_hostent_from_name( |
|
struct mtr_ctl *ctl, |
|
struct hostent *host, |
|
const char *name, |
|
char **alptr) |
|
{ |
|
int gai_error; |
|
struct addrinfo hints, *res; |
|
struct sockaddr_in *sa4; |
|
#ifdef ENABLE_IPV6 |
|
struct sockaddr_in6 *sa6; |
|
#endif |
|
|
|
/* 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; |
|
} |
|
|
|
/* Convert the first addrinfo into a hostent. */ |
|
memset(host, 0, sizeof(struct hostent)); |
|
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"); |
|
|
|
errno = EINVAL; |
|
return -1; |
|
} |
|
alptr[1] = NULL; |
|
|
|
return 0; |
|
} |
|
|
|
|
int main( |
int main( |
int argc, |
int argc, |
char **argv) |
char **argv) |
{ |
{ |
struct hostent *host = NULL; |
struct hostent *host = NULL; |
struct addrinfo hints, *res; |
|
int gai_error; |
|
struct hostent trhost; |
struct hostent trhost; |
char *alptr[2]; |
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 837 int main(
|
sizeof(ctl.LocalHostname)); |
sizeof(ctl.LocalHostname)); |
} |
} |
|
|
/* 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(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) |
|
exit(EXIT_FAILURE); |
|
else { |
|
names_walk = names_walk->next; |
|
continue; |
|
} |
|
} |
|
/* Convert the first addrinfo into a hostent. */ |
|
host = &trhost; |
host = &trhost; |
memset(host, 0, sizeof trhost); | if (get_hostent_from_name(&ctl, host, ctl.Hostname, alptr) != 0) { |
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) |
if (ctl.Interactive) |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
else { |
else { |
Line 809 int main(
|
Line 846 int main(
|
continue; |
continue; |
} |
} |
} |
} |
alptr[1] = NULL; |
|
|
|
if (net_open(&ctl, host) != 0) { |
if (net_open(&ctl, host) != 0) { |
error(0, 0, "Unable to start net module"); |
error(0, 0, "Unable to start net module"); |