From 920b3d6870fd82594972a2234d9c63da85e7e2c2 Mon Sep 17 00:00:00 2001 From: Mats Erik Andersson Date: Mon, 22 Nov 2010 16:54:34 +0100 Subject: [PATCH 3/3] traceroute: Make immune against `RES_OPTIONS=inet6'. --- ChangeLog | 10 ++++++++++ src/traceroute.c | 28 +++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf7ab0b..e5eebd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2010-11-22 Mats Erik Andersson + * src/traceroute.c: Include "xalloc.h". + * src/traceroute.c (host): Deleted variable. + (hostname, addrstr): New variables; + (parse_opt) [ARGP_KEY_ARG]: Abolish gethostbyname. Only use + xstrdup to copy argument. + (main): Use getaddrinfo and getnameinfo for name resolving. + New variables HINTS and *RES of type `struct addrinfo'. + +2010-11-22 Mats Erik Andersson + Resolve a double free issue. Leads to segmentation faults. * src/inetd.c (nextconfig): Do not use `freeconfig' unconditionally. diff --git a/src/traceroute.c b/src/traceroute.c index 432e6e1..9caeb00 100644 --- a/src/traceroute.c +++ b/src/traceroute.c @@ -47,6 +47,7 @@ #include #include +#include "xalloc.h" #include "libinetutils.h" #define TRACE_UDP_PORT 33434 @@ -87,7 +88,8 @@ char *get_hostname (struct in_addr *addr); int stop = 0; int pid = 0; -struct hostent *host; +static char *hostname = NULL; +char addrstr[INET6_ADDRSTRLEN]; struct sockaddr_in dest; static enum trace_type opt_type = TRACE_ICMP; @@ -158,9 +160,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case ARGP_KEY_ARG: host_is_given = true; - host = gethostbyname (arg); - if (host == NULL) - error (EXIT_FAILURE, 0, "unknown host"); + hostname = xstrdup(arg); break; case ARGP_KEY_SUCCESS: @@ -180,6 +180,7 @@ static struct argp argp = {argp_options, parse_opt, args_doc, doc}; int main (int argc, char **argv) { + struct addrinfo hints, *res; trace_t trace; set_program_name (argv[0]); @@ -188,15 +189,28 @@ main (int argc, char **argv) iu_argp_init ("traceroute", program_authors); argp_parse (&argp, argc, argv, 0, NULL, NULL); + /* Hostname lookup first for better information */ + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_flags = AI_CANONNAME; + + if ((hostname == NULL) || (*hostname == '\0') + || getaddrinfo (hostname, NULL, &hints, &res)) + error (EXIT_FAILURE, 0, "unknown host"); + if (geteuid () != 0) error (EXIT_FAILURE, EPERM, "insufficient permissions"); - dest.sin_addr = *(struct in_addr *) host->h_addr; - dest.sin_family = AF_INET; + memcpy (&dest, res->ai_addr, res->ai_addrlen); dest.sin_port = htons (opt_port); + getnameinfo (res->ai_addr, res->ai_addrlen, addrstr, sizeof (addrstr), + NULL, 0, NI_NUMERICHOST); + printf ("traceroute to %s (%s), %d hops max\n", - host->h_name, inet_ntoa (dest.sin_addr), opt_max_hops); + res->ai_canonname, addrstr, opt_max_hops); + + freeaddrinfo (res); trace_init (&trace, dest, opt_type); -- 1.7.2.3