On Fri, Sep 03, 2010 at 06:45:19PM -0700, Matthew Dempsky wrote:
> On Tue, Sep 07, 2010 at 04:40:38PM +0200, Claudio Jeker wrote:
> > +                   if (objhdr.ieo_ctype & 0x02) {
> > +                           /* interface name */
> > +                           if (olen < buf[0]) {
> > +                                   printf("|)");
> > +                                   return;
> > +                           }
> > +                           name = strndup(buf + 1, buf[0]);
> > +                           olen -= buf[0];
> > +                           buf += buf[0];
> > +                   }
> 
> buf[0] is the length of the entire sub-object not just the interface
> name, so I think we should a) check that it's in the range [1,64] and
> b) replace strndup(buf + 1, buf[0]) with strndup(buf + 1, buf[0] - 1).
> 
> There's also a memory leak that name might not be free(3)'d before
> return if the MTU field is truncated.
> 

Ugh, you're right. Fixed diff attached. I will commit the
non-ICMP_EXT_IFINFO part somewhen soon since the MPLS output is much
nicer.

traceroute to 192.168.237.242 (192.168.237.242), 64 hops max, 40 byte packets
 1  192.168.237.2 (192.168.237.2)  1.426 ms  0.257 ms  0.195 ms
 2  10.42.3.1 (10.42.3.1)  2.903 ms  1.741 ms  1.108 ms [MPLS Label 23, 666]
 3  10.42.7.1 (10.42.7.1)  2.95 ms  1.515 ms  1.310 ms [MPLS Label 23, 666]
 4  10.42.42.2 (10.42.42.2)  2.210 ms  1.520 ms  1.79 ms [MPLS Label 16, 666]
 5  192.168.237.242 (192.168.237.242)  2.883 ms  1.334 ms  1.74 ms

instead of

traceroute to 192.168.237.242 (192.168.237.242), 64 hops max, 40 byte packets
 1  192.168.237.2 (192.168.237.2)  3.31 ms  0.382 ms  0.256 ms
 2  10.42.3.1 (10.42.3.1)  3.434 ms  1.235 ms  1.62 ms [MPLS: Label 23 Exp 0, 
Label 666 Exp 0]
 3  10.42.7.1 (10.42.7.1)  2.148 ms  1.184 ms  1.551 ms [MPLS: Label 23 Exp 0, 
Label 666 Exp 0]
 4  10.42.42.2 (10.42.42.2)  2.103 ms  1.151 ms  1 ms [MPLS: Label 16 Exp 0, 
Label 666 Exp 0]
 5  192.168.237.242 (192.168.237.242)  2.140 ms  1.253 ms  1.39 ms

-- 
:wq Claudio

Index: traceroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/traceroute/traceroute.c,v
retrieving revision 1.72
diff -u -p -r1.72 traceroute.c
--- traceroute.c        9 Jul 2010 12:27:09 -0000       1.72
+++ traceroute.c        7 Sep 2010 14:37:48 -0000
@@ -728,7 +728,9 @@ print_exthdr(u_char *buf, int cc)
        struct ip *ip;
        struct icmp *icp;
        int hlen, first;
-       u_int32_t label;
+       u_int32_t label, ifindex, mtu;
+       struct in_addr addr;
+       char *name;
        u_int16_t off, olen;
        u_int8_t type;
                        
@@ -805,13 +807,14 @@ print_exthdr(u_char *buf, int cc)
                                        olen -= sizeof(u_int32_t);
                                        
                                        if (first == 0) {
-                                               printf(" [MPLS: ");
+                                               printf(" [MPLS Label ");
                                                first++;
                                        } else
                                                printf(", ");
-                                       printf("Label %d Exp %d",
-                                               MPLS_LABEL(label), 
-                                               MPLS_EXP(label));
+                                       printf("%d", MPLS_LABEL(label));
+                                       if (MPLS_EXP(label))
+                                               printf(" (Exp %x)",
+                                                   MPLS_EXP(label));
                                }
                                if (olen > 0) {
                                        printf("|]");
@@ -826,6 +829,91 @@ print_exthdr(u_char *buf, int cc)
                        }
                        break;
                case ICMP_EXT_IFINFO:
+                       /* RFC 5837: Extending ICMP for Interface and Next-Hop
+                        * Identification */
+                       mtu = 0;
+                       ifindex = 0;
+                       addr.s_addr = INADDR_ANY;
+                       name = NULL;
+                       if (objhdr.ieo_ctype & 0x80)
+                               printf("(fwd");
+                       else
+                               printf("(recv");
+                       /* must parse in this order */
+                       if (objhdr.ieo_ctype & 0x08) {
+                               /* ifIndex */
+                               if (olen < sizeof(u_int32_t)) {
+                                       printf("|)");
+                                       return;
+                               }
+                               memcpy(&ifindex, buf, sizeof(u_int32_t));
+                               ifindex = ntohl(ifindex);
+                               buf += sizeof(u_int32_t);
+                               olen -= sizeof(u_int32_t);
+                       }
+                       if (objhdr.ieo_ctype & 0x04) {
+                               /* IPAddr */
+                               u_int16_t afi;
+
+                               if (olen < sizeof(u_int32_t)) {
+                                       printf("|)");
+                                       return;
+                               }
+                               memcpy(&afi, buf, sizeof(u_int16_t));
+                               afi = ntohs(afi);
+                               if (afi != 1 /* AFI_IPv4 */) {
+                                       printf("afi|)");
+                                       return;
+                               }
+                               buf += sizeof(u_int32_t);
+                               olen -= sizeof(u_int32_t);
+
+                               if (olen < sizeof(u_int32_t)) {
+                                       printf("|)");
+                                       return;
+                               }
+                               memcpy(&addr, buf, sizeof(u_int32_t));
+                               buf += sizeof(u_int32_t);
+                               olen -= sizeof(u_int32_t);
+                       }
+                       if (objhdr.ieo_ctype & 0x02) {
+                               /* interface name */
+                               if (olen < buf[0]) {
+                                       printf("|)");
+                                       return;
+                               }
+                               name = strndup(buf + 1, buf[0]);
+                               olen -= buf[0];
+                               buf += buf[0];
+                       }
+                       if (objhdr.ieo_ctype & 0x01) {
+                               /* MTU */
+                               if (olen < sizeof(u_int32_t)) {
+                                       printf("|)");
+                                       return;
+                               }
+
+                               memcpy(&mtu, buf, sizeof(u_int32_t));
+                               mtu = ntohl(mtu);
+
+                               buf += sizeof(u_int32_t);
+                               olen -= sizeof(u_int32_t);
+                       }
+
+                       if (ifindex && name == NULL)
+                               asprintf(&name, " ifidx %d", ifindex);
+
+                       if (name)
+                               printf("%s", name);
+                       if (addr.s_addr != INADDR_ANY)
+                               printf("%s%s", name ? ": " : " ",
+                                   inet_ntoa(addr));
+                       if (mtu)
+                               printf("MTU %d", mtu);
+                       printf(")");
+
+                       free(name);
+                       break;
                default:
                        buf += olen;
                        break;

Reply via email to