Subject: Re: bin/22523
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Mihai CHELARU <kefren@netbsd.ro>
List: netbsd-bugs
Date: 08/18/2005 20:51:02
The following reply was made to PR bin/22523; it has been noted by GNATS.

From: Mihai CHELARU <kefren@netbsd.ro>
To: gnats-bugs@netbsd.org
Cc: ww@parc.styx.org
Subject: Re: bin/22523
Date: Thu, 18 Aug 2005 23:50:11 +0300

 Hello,
 
 I've made some changes in order to make this compile on later releases 
 (tested on 3.0_BETA).
 Here is how the output looks like:
 
 # obj/traceroute -I www.cisco.com
 traceroute to www.cisco.com (198.133.219.25), 64 hops max, 40 byte packets
  1  b2-f0-1 (193.28.151.1)  0.764 ms  0.347 ms  0.266 ms
  2  80.86.113.1 (80.86.113.1)  1.601 ms  1.360 ms  1.295 ms
  3  GE-0-2-0.B-BORDER.iNES.RO (80.86.97.61)  2.287 ms  1.913 ms  1.585 ms
  4  62.153.203.201 (62.153.203.201)  16.999 ms  16.985 ms  17.582 ms
  5  62.156.131.130 (62.156.131.130)  123.033 ms  122.373 ms  163.660 ms
  6  192.205.32.57 (192.205.32.57)  187.034 ms  384.544 ms  264.202 ms
  7  12.122.80.22 (12.122.80.22)  200.579 ms  200.115 ms  200.442 ms     
 [MPLS: Label 32433 Exp 0]
  8  tbr1-cl1.cgcil.ip.att.net (12.122.10.2)  199.812 ms  198.438 ms  
 199.435 ms [MPLS: Label 32429 Exp 0]
  9  tbr1-cl1.sffca.ip.att.net (12.122.10.6)  198.607 ms  198.557 ms  
 198.867 ms [MPLS: Label 32439 Exp 0]
 10  gbr5-p100.sffca.ip.att.net (12.122.11.74)  196.896 ms  196.612 ms  
 196.569 ms       [MPLS: Label 744 Exp 0]
 11  gar1-p360.sj2ca.ip.att.net (12.122.2.253)  197.018 ms  198.305 ms  
 199.953 ms
 12  12.127.200.82 (12.127.200.82)  200.831 ms  199.306 ms  197.921 ms
 13  sjce-dmzbb-gw1.cisco.com (128.107.239.53)  200.438 ms  199.452 ms  
 200.910 ms
 14  sjck-dmzdc-gw1.cisco.com (128.107.224.69)  198.720 ms  201.170 ms  
 199.382 ms
 15  www.cisco.com (198.133.219.25)  198.701 ms  199.690 ms  198.989 ms
 
 I prefered to print out only the label and exp in order to be consistent 
 with other implementations (cisco, linux).
 
 So, here is what made it work here:
 
 root@smtp:/usr/src/usr.sbin/traceroute# cvs diff -u -rHEAD traceroute.c
 Index: traceroute.c
 ===================================================================
 RCS file: /cvsroot/src/usr.sbin/traceroute/traceroute.c,v
 retrieving revision 1.61
 diff -u -r1.61 traceroute.c
 --- traceroute.c        22 Apr 2004 01:41:22 -0000      1.61
 +++ traceroute.c        18 Aug 2005 19:31:02 -0000
 @@ -269,6 +269,53 @@
         u_char ttl;             /* ttl packet left with */
         struct timeval tv;      /* time packet left */
  };
 +/*
 + * Support for ICMP extensions
 + *
 + * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
 + */
 +#define ICMP_EXT_OFFSET    8 /* ICMP type, code, checksum, unused */ + \
 +                         128 /* original datagram */
 +#define ICMP_EXT_VERSION 2
 +/*
 + * ICMP extensions, common header
 + */
 +struct icmp_ext_cmn_hdr {
 +#if BYTE_ORDER == BIG_ENDIAN
 +       u_char   version:4;
 +       u_char   reserved1:4;
 +#else
 +       u_char   reserved1:4;
 +       u_char   version:4;
 +#endif
 +       u_char   reserved2;
 +       u_short  checksum;
 +};
 +
 +/*
 + * ICMP extensions, object header
 + */
 +struct icmp_ext_obj_hdr {
 +    u_short length;
 +    u_char  class_num;
 +#define MPLS_STACK_ENTRY_CLASS 1
 +    u_char  c_type;
 +#define MPLS_STACK_ENTRY_C_TYPE 1
 +};
 +
 +struct mpls_header {
 +#if BYTE_ORDER == BIG_ENDIAN
 +    u_int32_t label:20;
 +    u_char  exp:3;
 +    u_char  s:1;
 +    u_char  ttl:8;
 +#else
 +    u_char  ttl:8;
 +    u_char  s:1;
 +    u_char  exp:3;
 +    u_int32_t label:20;
 +#endif
 +};
 
  u_char packet[512];            /* last inbound (icmp) packet */
 
 @@ -369,6 +416,7 @@
  void   tvsub(struct timeval *, struct timeval *);
  __dead void usage(void);
  int    wait_for_reply(int, struct sockaddr_in *, struct timeval *);
 +void   decode_extensions(u_char *buf, int ip_len);
  void   frag_err(void);
  int    find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
  #ifdef IPSEC
 @@ -1000,7 +1048,9 @@
                                 break;
                         }
                         if (cc == 0)
 -                               Printf(" *");
 +                               Printf(" *"); else
 +                       if (cc && probe == nprobes-1)
 +                               decode_extensions(packet, cc);
                         (void)fflush(stdout);
                 }
                 putchar('\n');
 @@ -1052,6 +1102,119 @@
  }
 
  void
 +decode_extensions(u_char *buf, int ip_len)
 +{
 +       struct icmp_ext_cmn_hdr *cmn_hdr;
 +       struct icmp_ext_obj_hdr *obj_hdr;
 +       union {
 +               struct mpls_header mpls;
 +               u_int32_t mpls_h;
 +       } mpls;
 +       int datalen, obj_len;
 +       struct ip *ip;
 +
 +       ip = (struct ip *)buf;
 +
 +       if (ip_len <= sizeof(struct ip) + ICMP_EXT_OFFSET) {
 +           /*
 +            * No support for ICMP extensions on this host
 +            */
 +           return;
 +       }
 +
 +       /*
 +        * Move forward to the start of the ICMP extensions, if present
 +        */
 +       buf += (ip->ip_hl << 2) + ICMP_EXT_OFFSET;
 +       cmn_hdr = (struct icmp_ext_cmn_hdr *)buf;
 +
 +       if (cmn_hdr->version != ICMP_EXT_VERSION) {
 +           /*
 +            * Unknown version
 +            */
 +           return;
 +       }
 +
 +       datalen = ip_len - ((u_char *)cmn_hdr - (u_char *)ip);
 +
 +       /*
 +        * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
 +        * done by sender.
 +        *
 +        * If the checksum is ok, we'll get 0, as the checksum is calculated
 +        * with the checksum field being 0'd.
 +        */
 +       if (ntohs(cmn_hdr->checksum) &&
 +           in_cksum((u_short *)cmn_hdr, datalen)) {
 +
 +           return;
 +       }
 +
 +       buf += sizeof(*cmn_hdr);
 +       datalen -= sizeof(*cmn_hdr);
 +
 +       while (datalen > 0) {
 +           obj_hdr = (struct icmp_ext_obj_hdr *)buf;
 +           obj_len = ntohs(obj_hdr->length);
 +
 +           /*
 +            * Sanity check the length field
 +            */
 +           if (obj_len > datalen) {
 +               return;
 +           }
 +
 +           datalen -= obj_len;
 +
 +           /*
 +            * Move past the object header
 +            */
 +           buf += sizeof(struct icmp_ext_obj_hdr);
 +           obj_len -= sizeof(struct icmp_ext_obj_hdr);
 +
 +           switch (obj_hdr->class_num) {
 +           case MPLS_STACK_ENTRY_CLASS:
 +               switch (obj_hdr->c_type) {
 +               case MPLS_STACK_ENTRY_C_TYPE:
 +                   while (obj_len >= sizeof(u_int32_t)) {
 +                       mpls.mpls_h = ntohl(*(u_int32_t *)buf);
 +
 +                       buf += sizeof(u_int32_t);
 +                       obj_len -= sizeof(u_int32_t);
 +
 +                       printf("\t[MPLS: Label %d Exp %d]",
 +                              mpls.mpls.label, mpls.mpls.exp);
 +                   }
 +                   if (obj_len > 0) {
 +                       /*
 +                        * Something went wrong, and we're at a unknown 
 offset
 +                        * into the packet, ditch the rest of it.
 +                        */
 +                       return;
 +                   }
 +                   break;
 +               default:
 +                   /*
 +                    * Unknown object, skip past it
 +                    */
 +                   buf += ntohs(obj_hdr->length) -
 +                       sizeof(struct icmp_ext_obj_hdr);
 +                   break;
 +               }
 +               break;
 +
 +           default:
 +               /*
 +                * Unknown object, skip past it
 +                */
 +               buf += ntohs(obj_hdr->length) -
 +                   sizeof(struct icmp_ext_obj_hdr);
 +               break;
 +           }
 +       }
 +}
 +
 +void
  dump_packet()
  {
         u_char *p;
 
 -- 
 Thanks,
 Mihai