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;