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