]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
probe - extend matching to src/dst host&port
authorMarkus Kötter <koetter@luis.uni-hannover.de>
Thu, 1 Nov 2018 10:34:25 +0000 (11:34 +0100)
committerMarkus Kötter <koetter@luis.uni-hannover.de>
Thu, 1 Nov 2018 10:34:25 +0000 (11:34 +0100)
Running multiple instances of mtr in udp mode will lead to incorrect
response pick ups due to sequence number re-use.
The changes address the issue by using more values to prevent incorrect
probe matches.

packet/construct_unix.c
packet/construct_unix.h
packet/deconstruct_unix.c
packet/probe.h
packet/probe_unix.c

index 9b3359625631b6e046034aad5a41c56e97a206a1..2268a224d35c0b9cb49107aa296382e1b16c5996 100644 (file)
@@ -99,15 +99,12 @@ void construct_addr_port(
 static
 void construct_ip4_header(
     const struct net_state_t *net_state,
+    const struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
-    const struct sockaddr_storage *srcaddr,
-    const struct sockaddr_storage *destaddr,
     const struct probe_param_t *param)
 {
     struct IPHeader *ip;
-    struct sockaddr_in *srcaddr4 = (struct sockaddr_in *) srcaddr;
-    struct sockaddr_in *destaddr4 = (struct sockaddr_in *) destaddr;
 
     ip = (struct IPHeader *) &packet_buffer[0];
 
@@ -118,15 +115,20 @@ void construct_ip4_header(
     ip->len = length_byte_swap(net_state, packet_size);
     ip->ttl = param->ttl;
     ip->protocol = param->protocol;
-    memcpy(&ip->saddr, &srcaddr4->sin_addr, sizeof(uint32_t));
-    memcpy(&ip->daddr, &destaddr4->sin_addr, sizeof(uint32_t));
+//    ip->id = htons(getpid());
+    memcpy(&ip->saddr,
+           sockaddr_addr_offset(&probe->local_addr),
+           sockaddr_addr_size(&probe->local_addr));
+    memcpy(&ip->daddr,
+           sockaddr_addr_offset(&probe->remote_addr),
+           sockaddr_addr_size(&probe->remote_addr));
 }
 
 /*  Construct an ICMP header for IPv4  */
 static
 void construct_icmp4_header(
     const struct net_state_t *net_state,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
     const struct probe_param_t *param)
@@ -146,7 +148,7 @@ void construct_icmp4_header(
 
     icmp->type = ICMP_ECHO;
     icmp->id = htons(getpid());
-    icmp->sequence = htons(sequence);
+    icmp->sequence = htons(probe->sequence);
     icmp->checksum = htons(compute_checksum(icmp, icmp_size));
 }
 
@@ -154,7 +156,7 @@ void construct_icmp4_header(
 static
 int construct_icmp6_packet(
     const struct net_state_t *net_state,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
     const struct probe_param_t *param)
@@ -167,7 +169,7 @@ int construct_icmp6_packet(
 
     icmp->type = ICMP6_ECHO;
     icmp->id = htons(getpid());
-    icmp->sequence = htons(sequence);
+    icmp->sequence = htons(probe->sequence);
 
     return 0;
 }
@@ -184,7 +186,7 @@ int construct_icmp6_packet(
 static
 void set_udp_ports(
     struct UDPHeader *udp,
-    int sequence,
+    struct probe_t *probe,
     const struct probe_param_t *param)
 {
     if (param->dest_port) {
@@ -192,13 +194,13 @@ void set_udp_ports(
 
         if (param->local_port) {
             udp->srcport = htons(param->local_port);
-            udp->checksum = htons(sequence);
+            udp->checksum = htons(probe->sequence);
         } else {
-            udp->srcport = htons(sequence);
+            udp->srcport = htons(probe->sequence);
             udp->checksum = 0;
         }
     } else {
-        udp->dstport = htons(sequence);
+        udp->dstport = htons(probe->sequence);
 
         if (param->local_port) {
             udp->srcport = htons(param->local_port);
@@ -208,6 +210,8 @@ void set_udp_ports(
 
         udp->checksum = 0;
     }
+    *(uint16_t *)sockaddr_port_offset(&probe->local_addr) = udp->srcport;
+    *(uint16_t *)sockaddr_port_offset(&probe->remote_addr) = udp->dstport;
 }
 
 /* Prepend pseudoheader to the udp datagram and calculate checksum */
@@ -236,11 +240,9 @@ int udp4_checksum(void *pheader, void *udata, int psize, int dsize,
 static
 void construct_udp4_header(
     const struct net_state_t *net_state,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
-    const struct sockaddr_in *src_addr,
-    const struct sockaddr_in *dst_addr,
     const struct probe_param_t *param)
 {
     struct UDPHeader *udp;
@@ -256,13 +258,13 @@ void construct_udp4_header(
 
     memset(udp, 0, sizeof(struct UDPHeader));
 
-    set_udp_ports(udp, sequence, param);
+    set_udp_ports(udp, probe, param);
     udp->length = htons(udp_size);
 
     /* calculate udp checksum */
     struct UDPPseudoHeader udph = {
-        .saddr = src_addr->sin_addr.s_addr,
-        .daddr = dst_addr->sin_addr.s_addr,
+        .saddr = *(uint32_t *)sockaddr_addr_offset(&probe->local_addr),
+        .daddr = *(uint32_t *)sockaddr_addr_offset(&probe->remote_addr),
         .zero = 0,
         .protocol = 17,
         .len = udp->length
@@ -287,7 +289,7 @@ void construct_udp4_header(
 static
 int construct_udp6_packet(
     const struct net_state_t *net_state,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
     const struct probe_param_t *param)
@@ -301,7 +303,7 @@ int construct_udp6_packet(
 
     memset(udp, 0, sizeof(struct UDPHeader));
 
-    set_udp_ports(udp, sequence, param);
+    set_udp_ports(udp, probe, param);
     udp->length = htons(udp_size);
 
     if (net_state->platform.ip6_socket_raw) {
@@ -538,11 +540,9 @@ static
 int construct_ip4_packet(
     const struct net_state_t *net_state,
     int *packet_socket,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
-    const struct sockaddr_storage *src_sockaddr,
-    const struct sockaddr_storage *dest_sockaddr,
     const struct probe_param_t *param)
 {
     int send_socket = net_state->platform.ip4_send_socket;
@@ -560,18 +560,15 @@ int construct_ip4_packet(
 #endif
     } else {
         if (net_state->platform.ip4_socket_raw) {
-            construct_ip4_header(net_state, packet_buffer, packet_size,
-                                 src_sockaddr, dest_sockaddr, param);
+            construct_ip4_header(net_state, probe, packet_buffer, packet_size,
+                                  param);
         }
         if (param->protocol == IPPROTO_ICMP) {
-            construct_icmp4_header(net_state, sequence, packet_buffer,
+            construct_icmp4_header(net_state, probe, packet_buffer,
                                    packet_size, param);
         } else if (param->protocol == IPPROTO_UDP) {
-            construct_udp4_header(net_state, sequence, packet_buffer,
-                                  packet_size,
-                                  (struct sockaddr_in *)src_sockaddr,
-                                  (struct sockaddr_in *)dest_sockaddr,
-                                  param);
+            construct_udp4_header(net_state, probe, packet_buffer,
+                                  packet_size, param);
         } else {
             errno = EINVAL;
             return -1;
@@ -580,8 +577,8 @@ int construct_ip4_packet(
 
     if (is_stream_protocol) {
         send_socket =
-            open_stream_socket(net_state, param->protocol, sequence,
-                               src_sockaddr, dest_sockaddr, param);
+            open_stream_socket(net_state, param->protocol, probe->sequence,
+                               &probe->local_addr, &probe->remote_addr, param);
 
         if (send_socket == -1) {
             return -1;
@@ -634,7 +631,7 @@ int construct_ip4_packet(
     }
 
     /*  Bind to our local address  */
-    if (bind_send_socket && bind(socket, (struct sockaddr *)src_sockaddr,
+    if (bind_send_socket && bind(socket, (struct sockaddr *)&probe->local_addr,
                 sizeof(struct sockaddr_in))) {
         return -1;
     }
@@ -667,11 +664,9 @@ static
 int construct_ip6_packet(
     const struct net_state_t *net_state,
     int *packet_socket,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_size,
-    const struct sockaddr_storage *src_sockaddr,
-    const struct sockaddr_storage *dest_sockaddr,
     const struct probe_param_t *param)
 {
     int send_socket;
@@ -694,7 +689,7 @@ int construct_ip6_packet(
         }
 
         if (construct_icmp6_packet
-            (net_state, sequence, packet_buffer, packet_size, param)) {
+            (net_state, probe, packet_buffer, packet_size, param)) {
             return -1;
         }
     } else if (param->protocol == IPPROTO_UDP) {
@@ -705,7 +700,7 @@ int construct_ip6_packet(
         }
 
         if (construct_udp6_packet
-            (net_state, sequence, packet_buffer, packet_size, param)) {
+            (net_state, probe, packet_buffer, packet_size, param)) {
             return -1;
         }
     } else {
@@ -715,8 +710,8 @@ int construct_ip6_packet(
 
     if (is_stream_protocol) {
         send_socket =
-            open_stream_socket(net_state, param->protocol, sequence,
-                               src_sockaddr, dest_sockaddr, param);
+            open_stream_socket(net_state, param->protocol, probe->sequence,
+                               &probe->local_addr, &probe->remote_addr, param);
 
         if (send_socket == -1) {
             return -1;
@@ -740,7 +735,7 @@ int construct_ip6_packet(
 
         if (net_state->platform.ip6_socket_raw) {
             if (memcmp(&current_sockaddr,
-                       src_sockaddr, sizeof(struct sockaddr_in6)) == 0) {
+                       &probe->local_addr, sizeof(struct sockaddr_in6)) == 0) {
                 bind_send_socket = false;
             }
         } else {
@@ -753,7 +748,7 @@ int construct_ip6_packet(
 
     /*  Bind to our local address  */
     if (bind_send_socket) {
-        if (bind(send_socket, (struct sockaddr *) src_sockaddr,
+        if (bind(send_socket, (struct sockaddr *) &probe->local_addr,
                  sizeof(struct sockaddr_in6))) {
             return -1;
         }
@@ -787,11 +782,9 @@ int construct_ip6_packet(
 int construct_packet(
     const struct net_state_t *net_state,
     int *packet_socket,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_buffer_size,
-    const struct sockaddr_storage *dest_sockaddr,
-    const struct sockaddr_storage *src_sockaddr,
     const struct probe_param_t *param)
 {
     int packet_size;
@@ -809,15 +802,15 @@ int construct_packet(
     memset(packet_buffer, param->bit_pattern, packet_size);
 
     if (param->ip_version == 6) {
-        if (construct_ip6_packet(net_state, packet_socket, sequence,
+        if (construct_ip6_packet(net_state, packet_socket, probe,
                                  packet_buffer, packet_size,
-                                 src_sockaddr, dest_sockaddr, param)) {
+                                 param)) {
             return -1;
         }
     } else if (param->ip_version == 4) {
-        if (construct_ip4_packet(net_state, packet_socket, sequence,
+        if (construct_ip4_packet(net_state, packet_socket, probe,
                                  packet_buffer, packet_size,
-                                 src_sockaddr, dest_sockaddr, param)) {
+                                 param)) {
             return -1;
         }
     } else {
index 39fe2829f3bbe5546fe984916b15acd2da003c80..99e1305a5256d7192c46f2e94ae9829632df59c1 100644 (file)
 int construct_packet(
     const struct net_state_t *net_state,
     int *packet_socket,
-    int sequence,
+    struct probe_t *probe,
     char *packet_buffer,
     int packet_buffer_size,
-    const struct sockaddr_storage *dest_sockaddr,
-    const struct sockaddr_storage *src_sockaddr,
     const struct probe_param_t *param);
 
 #endif
index 276f8034de0dbc5c84aa91abb15b2bb17991e30c..3c535e16a02087978b6c452a454205feb93cb2b1 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include "protocols.h"
+#include "sockaddr.h"
 
 #define MAX_MPLS_LABELS 8
 
@@ -64,6 +65,8 @@ void handle_inner_udp_packet(
     struct net_state_t *net_state,
     const struct sockaddr_storage *remote_addr,
     int icmp_result,
+    int af,
+    const void *ip,
     const struct UDPHeader *udp,
     int udp_length,
     struct timeval *timestamp,
@@ -79,11 +82,46 @@ void handle_inner_udp_packet(
     if (probe == NULL) {
         probe = find_probe(net_state, IPPROTO_UDP, 0, udp->checksum);
     }
+    if (probe == NULL)
+        return;
 
-    if (probe != NULL) {
-        receive_probe(net_state, probe, icmp_result,
-                      remote_addr, timestamp, mpls_count, mpls);
+    if (probe->remote_addr.ss_family != remote_addr->ss_family)
+        return;
+
+    if (udp->dstport != *(uint16_t *)sockaddr_port_offset(&probe->remote_addr) )
+        return;
+
+    if (udp->srcport != *(uint16_t *)sockaddr_port_offset(&probe->local_addr) )
+        return;
+
+    void *saddr, *daddr;
+    if (af == AF_INET)
+    {
+        saddr = &((struct IPHeader *)ip)->saddr;
+        daddr = &((struct IPHeader *)ip)->daddr;
+    }else
+    if (af == AF_INET6)
+    {
+        daddr = &((struct IP6Header *)ip)->daddr;
+        saddr = &((struct IP6Header *)ip)->saddr;
+    }else
+    {
+        return;
     }
+
+    if( memcmp(sockaddr_addr_offset(&probe->remote_addr),
+               daddr,
+               sockaddr_addr_size(&probe->remote_addr)) != 0 )
+            return;
+
+    if( memcmp(sockaddr_addr_offset(&probe->local_addr),
+           saddr,
+           sockaddr_addr_size(&probe->local_addr)) != 0)
+        return;
+
+    /* probe is not null */
+    receive_probe(net_state, probe, icmp_result,
+                      remote_addr, timestamp, mpls_count, mpls);
 }
 
 void handle_error_queue_packet(
@@ -96,7 +134,7 @@ void handle_error_queue_packet(
     struct timeval *timestamp)
 {
     if (proto == IPPROTO_UDP) {
-        handle_inner_udp_packet(net_state, remote_addr, ICMP_TIME_EXCEEDED,
+        handle_inner_udp_packet(net_state, remote_addr, ICMP_TIME_EXCEEDED, 0, NULL,
                 (struct UDPHeader *)packet, packet_length, timestamp, 0, NULL);
     } else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
         const struct ICMPHeader *icmp = (struct ICMPHeader *)packet;
@@ -157,7 +195,7 @@ void handle_inner_ip4_packet(
         udp = (struct UDPHeader *) (ip + 1);
         udp_length = packet_length - sizeof(struct IPHeader);
 
-        handle_inner_udp_packet(net_state, remote_addr, icmp_result, udp,
+        handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET, ip, udp,
                                 udp_length, timestamp, mpls_count, mpls);
     } else if (ip->protocol == IPPROTO_TCP) {
         if (packet_length < ip_tcp_size) {
@@ -233,7 +271,7 @@ void handle_inner_ip6_packet(
         udp = (struct UDPHeader *) (ip + 1);
         udp_length = packet_length - sizeof(struct IP6Header);
 
-        handle_inner_udp_packet(net_state, remote_addr, icmp_result, udp,
+        handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET6, ip, udp,
                                 udp_length, timestamp, mpls_count, mpls);
     } else if (ip->protocol == IPPROTO_TCP) {
         if (packet_length < ip_tcp_size) {
index ead2a4143131b182c84ba50d9b8668f940601d72..53b80373197dcef5587808e4c44df78833850ccc 100644 (file)
@@ -104,6 +104,10 @@ struct probe_t {
     /*  The address being probed  */
     struct sockaddr_storage remote_addr;
 
+    /* The local address which was used */
+    struct sockaddr_storage local_addr;
+
+
     /*  Platform specific probe tracking  */
     struct probe_platform_t platform;
 };
index 046229d3654441babaa2e277c10bdf3cef26483f..405b53cf3ea5eef285bd9c0ab7c9604cf898ff2c 100644 (file)
@@ -120,8 +120,7 @@ void check_length_order(
 {
     char packet[PACKET_BUFFER_SIZE];
     struct probe_param_t param;
-    struct sockaddr_storage dest_sockaddr;
-    struct sockaddr_storage src_sockaddr;
+    struct probe_t p0 = {.sequence = MIN_PORT };
     ssize_t bytes_sent;
     int packet_size;
 
@@ -138,8 +137,9 @@ void check_length_order(
     param.remote_address = "127.0.0.1";
     param.is_probing_byte_order = true;
 
-    if (resolve_probe_addresses(net_state, &param, &dest_sockaddr,
-                &src_sockaddr)) {
+
+    if (resolve_probe_addresses(net_state, &param, &p0.remote_addr,
+                &p0.local_addr)) {
         fprintf(stderr, "Error decoding localhost address\n");
         exit(EXIT_FAILURE);
     }
@@ -147,9 +147,9 @@ void check_length_order(
     /*  First attempt to ping the localhost with network byte order  */
     net_state->platform.ip_length_host_order = false;
 
-    packet_size = construct_packet(net_state, NULL, MIN_PORT,
+    packet_size = construct_packet(net_state, NULL, &p0,
                                    packet, PACKET_BUFFER_SIZE,
-                                   &dest_sockaddr, &src_sockaddr, &param);
+                                   &param);
     if (packet_size < 0) {
         perror("Unable to send to localhost");
         exit(EXIT_FAILURE);
@@ -157,7 +157,7 @@ void check_length_order(
 
     bytes_sent =
         send_packet(net_state, &param, MIN_PORT, packet, packet_size,
-                    &dest_sockaddr);
+                    &p0.remote_addr);
     if (bytes_sent > 0) {
         return;
     }
@@ -165,9 +165,9 @@ void check_length_order(
     /*  Since network byte order failed, try host byte order  */
     net_state->platform.ip_length_host_order = true;
 
-    packet_size = construct_packet(net_state, NULL, MIN_PORT,
+    packet_size = construct_packet(net_state, NULL, &p0,
                                    packet, PACKET_BUFFER_SIZE,
-                                   &dest_sockaddr, &src_sockaddr, &param);
+                                   &param);
     if (packet_size < 0) {
         perror("Unable to send to localhost");
         exit(EXIT_FAILURE);
@@ -175,7 +175,7 @@ void check_length_order(
 
     bytes_sent =
         send_packet(net_state, &param, MIN_PORT, packet, packet_size,
-                    &dest_sockaddr);
+                    &p0.remote_addr);
     if (bytes_sent < 0) {
         perror("Unable to send with swapped length");
         exit(EXIT_FAILURE);
@@ -551,7 +551,6 @@ void send_probe(
 {
     char packet[PACKET_BUFFER_SIZE];
     struct probe_t *probe;
-    struct sockaddr_storage src_sockaddr;
     int trytimes;
     int packet_size;
 
@@ -562,7 +561,7 @@ void send_probe(
     }
 
     if (resolve_probe_addresses(net_state, param, &probe->remote_addr,
-                &src_sockaddr)) {
+                &probe->local_addr)) {
         printf("%d invalid-argument\n", param->command_token);
         free_probe(net_state, probe);
         return;
@@ -579,9 +578,9 @@ void send_probe(
     for (trytimes=MIN_PORT; trytimes < MAX_PORT; trytimes++) {
                        
         packet_size = construct_packet(net_state, &probe->platform.socket,
-                         probe->sequence, packet, PACKET_BUFFER_SIZE,
-                         &probe->remote_addr, &src_sockaddr, param);
-        
+                         probe, packet, PACKET_BUFFER_SIZE,
+                         param);
+
         if (packet_size > 0) break; // no retry if we succeed.
 
         if ((param->protocol != IPPROTO_TCP) &&