From: Robert Vollmer Date: Fri, 5 Aug 2022 07:58:41 +0000 (+0200) Subject: Set SO_BINDTODEVICE for -I X-Git-Tag: v0.96~33^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a0320038a64594c138e69b1200c30428bd1c75c;p=thirdparty%2Fmtr.git Set SO_BINDTODEVICE for -I 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. --- diff --git a/packet/command.c b/packet/command.c index b624ea6..a708841 100644 --- a/packet/command.c +++ b/packet/command.c @@ -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")) { diff --git a/packet/construct_unix.c b/packet/construct_unix.c index faca768..65f0b63 100644 --- a/packet/construct_unix.c +++ b/packet/construct_unix.c @@ -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; } diff --git a/packet/probe.h b/packet/probe.h index e7b8bee..caf1314 100644 --- a/packet/probe.h +++ b/packet/probe.h @@ -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; diff --git a/ui/cmdpipe.c b/ui/cmdpipe.c index d22b236..8017cc0 100644 --- a/ui/cmdpipe.c +++ b/ui/cmdpipe.c @@ -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);