]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
report: preflight multiple target families 586/head
authorDarafei Praliaskouski <me@komzpa.net>
Thu, 7 May 2026 20:29:31 +0000 (00:29 +0400)
committerDarafei Praliaskouski <me@komzpa.net>
Thu, 7 May 2026 20:29:31 +0000 (00:29 +0400)
man/mtr.8.in
ui/mtr.c

index 5101094497b275ad37acf111483359092aea9ee4..8e6084443a9b4d5b1d87e0e5215336b45a6bcf0d 100644 (file)
@@ -184,6 +184,14 @@ generates a significant amount of network traffic.  Using
 .B mtr
 to measure the quality of your network may result in decreased
 network performance.
+.PP
+Report mode can process multiple hosts in sequence. All hosts in one
+invocation must resolve to the same address family; use separate invocations
+or force an address family with
+.B \-4
+or
+.B \-6
+when tracing mixed IPv4 and IPv6 targets.
 .TP
 .B \-w\fR, \fB\-\-report\-wide
 This option puts
index 6886bce346c52adb60868055f9331c567dcf4e14..64ca431ac976c43311767a21aba8db456488b5c0 100644 (file)
--- a/ui/mtr.c
+++ b/ui/mtr.c
@@ -749,6 +749,61 @@ int get_addrinfo_from_name(
 }
 
 
+static int count_names(
+    names_t *names)
+{
+    int count = 0;
+
+    while (names != NULL) {
+        count++;
+        names = names->next;
+    }
+
+    return count;
+}
+
+
+static int validate_report_targets(
+    struct mtr_ctl *ctl,
+    names_t *names)
+{
+    struct mtr_ctl lookup_ctl = *ctl;
+
+    while (names != NULL) {
+        int gai_error;
+        struct addrinfo hints;
+        struct addrinfo *res = NULL;
+
+        memset(&hints, 0, sizeof hints);
+        hints.ai_family = lookup_ctl.af;
+        hints.ai_socktype = SOCK_DGRAM;
+        gai_error = getaddrinfo(names->name, NULL, &hints, &res);
+        if (gai_error) {
+            if (gai_error == EAI_SYSTEM) {
+                error(0, 0, "Failed to resolve host: %s", names->name);
+            } else {
+                error(0, 0, "Failed to resolve host: %s: %s", names->name,
+                      gai_strerror(gai_error));
+            }
+#if defined(ENABLE_IPV6) && defined(EAI_ADDRFAMILY)
+            if (gai_error == EAI_ADDRFAMILY && lookup_ctl.af != AF_UNSPEC) {
+                error(0, 0,
+                      "multiple report targets must use the same address family");
+            }
+#endif
+            return -1;
+        }
+
+        lookup_ctl.af = res->ai_family;
+        freeaddrinfo(res);
+        names = names->next;
+    }
+
+    ctl->af = lookup_ctl.af;
+    return 0;
+}
+
+
 int main(
     int argc,
     char **argv)
@@ -825,6 +880,11 @@ int main(
     if (!names_head)
         append_to_names(&names_head, "localhost");
 
+    if (!ctl.Interactive && count_names(names_head) > 1 &&
+        validate_report_targets(&ctl, names_head) != 0) {
+        return EXIT_FAILURE;
+    }
+
     names_walk = names_head;
     while (names_walk != NULL) {