]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
Set SO_BINDTODEVICE for -I 440/head
authorRobert Vollmer <github@robv.de>
Fri, 5 Aug 2022 07:58:41 +0000 (09:58 +0200)
committerRobert Vollmer <robert.vollmer@sap.com>
Fri, 5 Aug 2022 07:58:41 +0000 (09:58 +0200)
This is done by traceroute and other tools as well. It requires
CAP_NET_RAW, but without it the -I option doesn't seem to have any
effect.

packet/command.c
packet/construct_unix.c
packet/probe.h
ui/cmdpipe.c

index b624ea6c833db767cef0768b7ca9e940f9c95278..a7088410fd8f9d44436808ee0ce93376887bcb02 100644 (file)
@@ -189,6 +189,11 @@ bool decode_probe_argument(
         param->local_address = value;
     }
 
+    /*  Device name to send from  */
+    if (!strcmp(name, "local-device")) {
+        param->local_device = value;
+    }
+
     /*  Protocol for the probe  */
     if (!strcmp(name, "protocol")) {
         if (!strcmp(value, "icmp")) {
index faca768918d3e5c01494ccb601e83f843b743f67..65f0b633ca79df53ca8c7c83e4a36f87b582d04a 100644 (file)
@@ -398,6 +398,13 @@ int set_stream_socket_options(
     }
 #endif
 
+    if (param->local_device) {
+        if (setsockopt(stream_socket, SOL_SOCKET,
+                       SO_BINDTODEVICE, param->local_device, strlen(param->local_device))) {
+            return -1;
+        }
+    }
+
     return 0;
 }
 
@@ -614,6 +621,13 @@ int construct_ip4_packet(
     }
 #endif
 
+    if (param->local_device) {
+        if (setsockopt(send_socket, SOL_SOCKET,
+                       SO_BINDTODEVICE, param->local_device, strlen(param->local_device))) {
+            return -1;
+        }
+    }
+
     /*
        Bind src port when not using raw socket to pass in ICMP id, kernel
        get ICMP id from src_port when using DGRAM socket.
@@ -782,6 +796,14 @@ int construct_ip6_packet(
     }
 #endif
 
+    if (param->local_device) {
+        if (setsockopt(send_socket,
+                       SOL_SOCKET, SO_BINDTODEVICE, param->local_device,
+                       strlen(param->local_device))) {
+            return -1;
+        }
+    }
+
     return 0;
 }
 
index e7b8beea9cce49576369632a45a91c0ded15f9d4..caf1314b48918875b71c9712f60c7ae11899afc0 100644 (file)
@@ -53,6 +53,9 @@ struct probe_param_t {
     /*  The local address from which to send probes  */
     const char *local_address;
 
+    /*  The local device from which to send probes  */
+    const char *local_device;
+
     /*  Protocol for the probe, using the IPPROTO_* defines  */
     int protocol;
 
index d22b236f99ba731d4e511f46388379d2e97abff8..8017cc0fc298104b486adce5d823fa69f270dea2 100644 (file)
@@ -417,6 +417,22 @@ void append_command_argument(
     strncat(command, argument, remaining_size);
 }
 
+static
+void append_command_string_argument(
+    char *command,
+    int buffer_size,
+    char *name,
+    char *value)
+{
+    char argument[COMMAND_BUFFER_SIZE];
+    int remaining_size;
+
+    remaining_size = buffer_size - strlen(command) - 1;
+
+    snprintf(argument, buffer_size, " %s %s", name, value);
+    strncat(command, argument, remaining_size);
+}
+
 
 /*  Request a new probe from the "mtr-packet" child process  */
 void send_probe_command(
@@ -466,6 +482,11 @@ void send_probe_command(
     }
 #endif
 
+    if (ctl->InterfaceName) {
+        append_command_string_argument(command, COMMAND_BUFFER_SIZE,
+                                       "local-device", ctl->InterfaceName);
+    }
+
     remaining_size = COMMAND_BUFFER_SIZE - strlen(command) - 1;
     strncat(command, "\n", remaining_size);