Diff for /embedaddon/mtr/packet/probe.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2019/10/21 14:25:31 version 1.1.1.2, 2021/03/17 00:07:30
Line 11 Line 11
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.      GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License    You should have received a copy of the GNU General Public License along
    along with this program; if not, write to the Free Software    with this program; if not, write to the Free Software Foundation, Inc.,
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */  */
   
 #include "probe.h"  #include "probe.h"
Line 21 Line 21
 #include <arpa/inet.h>  #include <arpa/inet.h>
 #include <assert.h>  #include <assert.h>
 #include <errno.h>  #include <errno.h>
   #ifdef HAVE_ERROR_H
   #include <error.h>
   #else
   #include "portability/error.h"
   #endif
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 31 Line 36
 #include "platform.h"  #include "platform.h"
 #include "protocols.h"  #include "protocols.h"
 #include "timeval.h"  #include "timeval.h"
   #include "sockaddr.h"
   
#define IP_TEXT_LENGTH 64char *probe_err;
   
 /*  Convert the destination address from text to sockaddr  */  /*  Convert the destination address from text to sockaddr  */
 int decode_address_string(  int decode_address_string(
Line 87  int decode_address_string( Line 93  int decode_address_string(
     for the probe.      for the probe.
 */  */
 int resolve_probe_addresses(  int resolve_probe_addresses(
       struct net_state_t *net_state,
     const struct probe_param_t *param,      const struct probe_param_t *param,
     struct sockaddr_storage *dest_sockaddr,      struct sockaddr_storage *dest_sockaddr,
     struct sockaddr_storage *src_sockaddr)      struct sockaddr_storage *src_sockaddr)
 {  {
     if (decode_address_string      if (decode_address_string
         (param->ip_version, param->remote_address, dest_sockaddr)) {          (param->ip_version, param->remote_address, dest_sockaddr)) {
           probe_err = "decode address string remote";
         return -1;          return -1;
     }      }
   
     if (param->local_address) {      if (param->local_address) {
         if (decode_address_string          if (decode_address_string
             (param->ip_version, param->local_address, src_sockaddr)) {              (param->ip_version, param->local_address, src_sockaddr)) {
               probe_err = "decode address string local";
             return -1;              return -1;
         }          }
     } else {      } else {
           probe_err = "find source address";
         if (find_source_addr(src_sockaddr, dest_sockaddr)) {          if (find_source_addr(src_sockaddr, dest_sockaddr)) {
               //probe_err = "find source address";
             return -1;              return -1;
         }          }
           probe_err = "";
     }      }
       /* DGRAM ICMP id is taken from src_port not from ICMP header */
       if (param->protocol == IPPROTO_ICMP) {
           if ( (src_sockaddr->ss_family == AF_INET && !net_state->platform.ip4_socket_raw) ||
                (src_sockaddr->ss_family == AF_INET6 && !net_state->platform.ip6_socket_raw) )
               *sockaddr_port_offset(src_sockaddr) = htons(getpid());
       }
   
     return 0;      return 0;
 }  }
Line 215  void format_mpls_string( Line 233  void format_mpls_string(
         }          }
   
         snprintf(append_pos, buffer_size, "%d,%d,%d,%d",          snprintf(append_pos, buffer_size, "%d,%d,%d,%d",
                 mpls->label, mpls->experimental_use,                 mpls->label, mpls->traffic_class,
                  mpls->bottom_of_stack, mpls->ttl);                   mpls->bottom_of_stack, mpls->ttl);
   
         buffer_size -= strlen(append_pos);          buffer_size -= strlen(append_pos);
Line 236  void respond_to_probe( Line 254  void respond_to_probe(
     int mpls_count,      int mpls_count,
     const struct mpls_label_t *mpls)      const struct mpls_label_t *mpls)
 {  {
    char ip_text[IP_TEXT_LENGTH];    char ip_text[INET6_ADDRSTRLEN];
     char response[COMMAND_BUFFER_SIZE];      char response[COMMAND_BUFFER_SIZE];
     char mpls_str[COMMAND_BUFFER_SIZE];      char mpls_str[COMMAND_BUFFER_SIZE];
     int remaining_size;      int remaining_size;
     const char *result;      const char *result;
     const char *ip_argument;      const char *ip_argument;
     struct sockaddr_in *sockaddr4;  
     struct sockaddr_in6 *sockaddr6;  
     void *addr;  
   
     if (icmp_type == ICMP_TIME_EXCEEDED) {      if (icmp_type == ICMP_TIME_EXCEEDED) {
         result = "ttl-expired";          result = "ttl-expired";
       } else if (icmp_type == ICMP_DEST_UNREACH) {
           result = "no-route";
     } else {      } else {
         assert(icmp_type == ICMP_ECHOREPLY);          assert(icmp_type == ICMP_ECHOREPLY);
         result = "reply";          result = "reply";
Line 255  void respond_to_probe( Line 272  void respond_to_probe(
   
     if (remote_addr->ss_family == AF_INET6) {      if (remote_addr->ss_family == AF_INET6) {
         ip_argument = "ip-6";          ip_argument = "ip-6";
         sockaddr6 = (struct sockaddr_in6 *) remote_addr;  
         addr = &sockaddr6->sin6_addr;  
     } else {      } else {
         ip_argument = "ip-4";          ip_argument = "ip-4";
         sockaddr4 = (struct sockaddr_in *) remote_addr;  
         addr = &sockaddr4->sin_addr;  
     }      }
   
    if (inet_ntop(remote_addr->ss_family, addr, ip_text, IP_TEXT_LENGTH) ==    if (inet_ntop(remote_addr->ss_family, sockaddr_addr_offset(remote_addr), ip_text, INET6_ADDRSTRLEN) ==
         NULL) {          NULL) {
        error(EXIT_FAILURE, errno, "inet_ntop failure");
        perror("inet_ntop failure"); 
        exit(EXIT_FAILURE); 
     }      }
   
     snprintf(response, COMMAND_BUFFER_SIZE,      snprintf(response, COMMAND_BUFFER_SIZE,
Line 306  int find_source_addr( Line 317  int find_source_addr(
 {  {
     int sock;      int sock;
     int len;      int len;
     struct sockaddr_in *destaddr4;  
     struct sockaddr_in6 *destaddr6;  
     struct sockaddr_storage dest_with_port;      struct sockaddr_storage dest_with_port;
   #ifdef __linux__
       // The Linux code needs these. 
     struct sockaddr_in *srcaddr4;      struct sockaddr_in *srcaddr4;
     struct sockaddr_in6 *srcaddr6;      struct sockaddr_in6 *srcaddr6;
   #endif
   
   
     dest_with_port = *destaddr;      dest_with_port = *destaddr;
   
     /*      /*
Line 320  int find_source_addr( Line 333  int find_source_addr(
        the connect will fail.  We aren't actually sending         the connect will fail.  We aren't actually sending
        anything to the port.         anything to the port.
      */       */
    if (destaddr->ss_family == AF_INET6) {    *sockaddr_port_offset(&dest_with_port) = htons(1);
        destaddr6 = (struct sockaddr_in6 *) &dest_with_port;    len = sockaddr_size(&dest_with_port);
        destaddr6->sin6_port = htons(1); 
   
         len = sizeof(struct sockaddr_in6);  
     } else {  
         destaddr4 = (struct sockaddr_in *) &dest_with_port;  
         destaddr4->sin_port = htons(1);  
   
         len = sizeof(struct sockaddr_in);  
     }  
   
     sock = socket(destaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP);      sock = socket(destaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP);
     if (sock == -1) {      if (sock == -1) {
           probe_err = "open socket";
         return -1;          return -1;
     }      }
   
    if (connect(sock, (struct sockaddr *) &dest_with_port, len)) {    if (connect(sock, (struct sockaddr *) &dest_with_port, len) == 0) {
        close(sock);        if (getsockname(sock, (struct sockaddr *) srcaddr, &len)) {
        return -1;            close(sock);
    }            probe_err = "getsockname";
             return -1;
         }
     } else {
 #ifdef __linux__
         /* Linux doesn't require source address, so we can support
          * a case when mtr is run against unreachable host (that can become
          * reachable) */
         if (errno != EHOSTUNREACH) {
             probe_err = "not hostunreach";
             close(sock);
             return -1;
         }
   
    if (getsockname(sock, (struct sockaddr *) srcaddr, &len)) {        if (destaddr->ss_family == AF_INET6) {
             srcaddr6 = (struct sockaddr_in6 *) srcaddr;
             srcaddr6->sin6_addr = in6addr_any;
         } else {
             srcaddr4 = (struct sockaddr_in *) srcaddr;
             srcaddr4->sin_addr.s_addr = INADDR_ANY;
         }
 #else
         close(sock);          close(sock);
           probe_err = "connect failed";
         return -1;          return -1;
   #endif
     }      }
   
     close(sock);      close(sock);
Line 353  int find_source_addr( Line 379  int find_source_addr(
        Zero the port, as we may later use this address to finding, and         Zero the port, as we may later use this address to finding, and
        we don't want to use the port from the socket we just created.         we don't want to use the port from the socket we just created.
      */       */
    if (destaddr->ss_family == AF_INET6) {    *sockaddr_port_offset(srcaddr) = 0;
        srcaddr6 = (struct sockaddr_in6 *) srcaddr; 
 
        srcaddr6->sin6_port = 0; 
    } else { 
        srcaddr4 = (struct sockaddr_in *) srcaddr; 
 
        srcaddr4->sin_port = 0; 
    } 
   
     return 0;      return 0;
 }  }

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>