]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ldp.c
remove tcpdump's own CVS keywords
[tcpdump] / print-ldp.c
index c73022b576627167fc1a845ae019b076b38bf7ba..bff0455f005c189a967b9d8132439f0e50f9bd9c 100644 (file)
  *  and Steinar Haug ([email protected])
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.7 2004-05-27 21:20:50 guy Exp $";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -34,6 +29,9 @@ static const char rcsid[] _U_ =
 #include "extract.h"
 #include "addrtoname.h"
 
+#include "l2vpn.h"
+#include "af.h"
+
 /*
  * ldp common header
  *
@@ -88,8 +86,8 @@ struct ldp_msg_header {
     u_int8_t id[4];
 };
 
-#define        LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff) 
-#define        LDP_MASK_U_BIT(x)     ((x)&0x8000) 
+#define        LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff)
+#define        LDP_MASK_U_BIT(x)     ((x)&0x8000)
 
 #define        LDP_MSG_NOTIF                0x0001
 #define        LDP_MSG_HELLO                0x0100
@@ -114,7 +112,7 @@ static const struct tok ldp_msg_values[] = {
     { LDP_MSG_INIT,                 "Initialization" },
     { LDP_MSG_KEEPALIVE,             "Keepalive" },
     { LDP_MSG_ADDRESS,              "Address" },
-    { LDP_MSG_ADDRESS_WITHDRAW,             "Address Widthdraw" },
+    { LDP_MSG_ADDRESS_WITHDRAW,             "Address Withdraw" },
     { LDP_MSG_LABEL_MAPPING,        "Label Mapping" },
     { LDP_MSG_LABEL_REQUEST,        "Label Request" },
     { LDP_MSG_LABEL_WITHDRAW,       "Label Withdraw" },
@@ -123,11 +121,12 @@ static const struct tok ldp_msg_values[] = {
     { 0, NULL}
 };
 
-#define        LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff) 
-#define        LDP_MASK_F_BIT(x) ((x)&0x4000) 
+#define        LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff)
+#define        LDP_MASK_F_BIT(x) ((x)&0x4000)
 
 #define        LDP_TLV_FEC                  0x0100
 #define        LDP_TLV_ADDRESS_LIST         0x0101
+#define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
 #define        LDP_TLV_HOP_COUNT            0x0103
 #define        LDP_TLV_PATH_VECTOR          0x0104
 #define        LDP_TLV_GENERIC_LABEL        0x0200
@@ -146,6 +145,7 @@ static const struct tok ldp_msg_values[] = {
 #define        LDP_TLV_FR_SESSION_PARM      0x0502
 #define LDP_TLV_FT_SESSION          0x0503
 #define        LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
+#define LDP_TLV_MTU                  0x0601 /* rfc 3988 */
 
 static const struct tok ldp_tlv_values[] = {
     { LDP_TLV_FEC,                  "FEC" },
@@ -168,13 +168,14 @@ static const struct tok ldp_tlv_values[] = {
     { LDP_TLV_FR_SESSION_PARM,       "Frame-Relay Session Parameters" },
     { LDP_TLV_FT_SESSION,            "Fault-Tolerant Session Parameters" },
     { LDP_TLV_LABEL_REQUEST_MSG_ID,  "Label Request Message ID" },
+    { LDP_TLV_MTU,                   "MTU" },
     { 0, NULL}
 };
 
 #define LDP_FEC_WILDCARD       0x01
 #define LDP_FEC_PREFIX         0x02
 #define LDP_FEC_HOSTADDRESS    0x03
-/* From draft-martini-l2circuit-trans-mpls-13.txt */
+/* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
 #define LDP_FEC_MARTINI_VC     0x80
 
 static const struct tok ldp_fec_values[] = {
@@ -185,43 +186,37 @@ static const struct tok ldp_fec_values[] = {
     { 0, NULL}
 };
 
-/* From draft-martini-l2circuit-trans-mpls-13.txt */
-#define LDP_MARTINI_VCTYPE_FR_DLCI     0x0001
-#define LDP_MARTINI_VCTYPE_ATM_AAL5    0x0002
-#define LDP_MARTINI_VCTYPE_ATM_CELL    0x0003
-#define LDP_MARTINI_VCTYPE_ETH_VLAN    0x0004
-#define LDP_MARTINI_VCTYPE_ETHERNET    0x0005
-#define LDP_MARTINI_VCTYPE_HDLC                0x0006
-#define LDP_MARTINI_VCTYPE_PPP         0x0007
-#define LDP_MARTINI_VCTYPE_CEM         0x0008
-#define LDP_MARTINI_VCTYPE_ATM_VCC     0x0009
-#define LDP_MARTINI_VCTYPE_ATM_VPC     0x000A
-
-/* Overlaps print-bgp.c bgp_l2vpn_encaps_values */
-static const struct tok ldp_vctype_values[] = {
-    { LDP_MARTINI_VCTYPE_FR_DLCI,      "Frame Relay DLCI" },
-    { LDP_MARTINI_VCTYPE_ATM_AAL5,     "ATM AAL5 VCC transport" },
-    { LDP_MARTINI_VCTYPE_ATM_CELL,     "ATM transparent cell transport" },
-    { LDP_MARTINI_VCTYPE_ETH_VLAN,     "Ethernet VLAN" },
-    { LDP_MARTINI_VCTYPE_ETHERNET,     "Ethernet" },
-    { LDP_MARTINI_VCTYPE_HDLC,         "HDLC" },
-    { LDP_MARTINI_VCTYPE_PPP,          "PPP" },
-    { LDP_MARTINI_VCTYPE_CEM,          "SONET/SDH Circuit Emulation Service" },
-    { LDP_MARTINI_VCTYPE_ATM_VCC,      "ATM VCC cell transport" },
-    { LDP_MARTINI_VCTYPE_ATM_VPC,      "ATM VPC cell transport" },
+#define LDP_FEC_MARTINI_IFPARM_MTU  0x01
+#define LDP_FEC_MARTINI_IFPARM_DESC 0x03
+#define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
+
+static const struct tok ldp_fec_martini_ifparm_values[] = {
+    { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
+    { LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
+    { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
     { 0, NULL}
 };
 
-/* RFC1700 address family numbers, same definition in print-bgp.c */
-#define AFNUM_INET     1
-#define AFNUM_INET6    2
+/* draft-ietf-pwe3-vccv-04.txt */
+static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
+    { 0x01, "PWE3 control word" },
+    { 0x02, "MPLS Router Alert Label" },
+    { 0x04, "MPLS inner label TTL = 1" },
+    { 0, NULL}
+};
 
-#define FALSE 0
-#define TRUE  1
+/* draft-ietf-pwe3-vccv-04.txt */
+static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
+    { 0x01, "ICMP Ping" },
+    { 0x02, "LSP Ping" },
+    { 0x04, "BFD" },
+    { 0, NULL}
+};
 
+int ldp_msg_print(register const u_char *);
 int ldp_tlv_print(register const u_char *);
-   
-/* 
+
+/*
  * ldp tlv header
  *
  *  0                   1                   2                   3
@@ -238,6 +233,9 @@ int ldp_tlv_print(register const u_char *);
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
+#define TLV_TCHECK(minlen) \
+    TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv;
+
 int
 ldp_tlv_print(register const u_char *tptr) {
 
@@ -249,11 +247,11 @@ ldp_tlv_print(register const u_char *tptr) {
     const struct ldp_tlv_header *ldp_tlv_header;
     u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
     u_char fec_type;
-    u_int ui;
+    u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
     char buf[100];
     int i;
 
-    ldp_tlv_header = (const struct ldp_tlv_header *)tptr;    
+    ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
     tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
     tlv_tlen=tlv_len;
     tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
@@ -273,6 +271,7 @@ ldp_tlv_print(register const u_char *tptr) {
     switch(tlv_type) {
 
     case LDP_TLV_COMMON_HELLO:
+        TLV_TCHECK(4);
         printf("\n\t      Hold Time: %us, Flags: [%s Hello%s]",
                EXTRACT_16BITS(tptr),
                (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
@@ -280,40 +279,54 @@ ldp_tlv_print(register const u_char *tptr) {
         break;
 
     case LDP_TLV_IPV4_TRANSPORT_ADDR:
+        TLV_TCHECK(4);
         printf("\n\t      IPv4 Transport Address: %s", ipaddr_string(tptr));
         break;
 #ifdef INET6
     case LDP_TLV_IPV6_TRANSPORT_ADDR:
+        TLV_TCHECK(16);
         printf("\n\t      IPv6 Transport Address: %s", ip6addr_string(tptr));
         break;
 #endif
     case LDP_TLV_CONFIG_SEQ_NUMBER:
+        TLV_TCHECK(4);
         printf("\n\t      Sequence Number: %u", EXTRACT_32BITS(tptr));
         break;
 
     case LDP_TLV_ADDRESS_LIST:
+        TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
        af = EXTRACT_16BITS(tptr);
-       tptr+=2;
-       printf("\n\t      Adress Family: ");
-       if (af == AFNUM_INET) {
-           printf("IPv4, addresses:");
-           for (i=0; i<(tlv_tlen-2)/4; i++) {
+       tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
+        tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
+       printf("\n\t      Address Family: %s, addresses",
+               tok2str(af_values, "Unknown (%u)", af));
+        switch (af) {
+        case AFNUM_INET:
+           while(tlv_tlen >= sizeof(struct in_addr)) {
+               TCHECK2(*tptr, sizeof(struct in_addr));
                printf(" %s",ipaddr_string(tptr));
-               tptr+=4;
+               tlv_tlen-=sizeof(struct in_addr);
+               tptr+=sizeof(struct in_addr);
            }
-       }
+            break;
 #ifdef INET6
-       else if (af == AFNUM_INET6) {
-           printf("IPv6, addresses:");
-           for (i=0; i<(tlv_tlen-2)/16; i++) {
+        case AFNUM_INET6:
+           while(tlv_tlen >= sizeof(struct in6_addr)) {
+               TCHECK2(*tptr, sizeof(struct in6_addr));
                printf(" %s",ip6addr_string(tptr));
-               tptr+=16;
+               tlv_tlen-=sizeof(struct in6_addr);
+               tptr+=sizeof(struct in6_addr);
            }
-       }
+            break;
 #endif
+        default:
+            /* unknown AF */
+            break;
+        }
        break;
 
     case LDP_TLV_COMMON_SESSION:
+       TLV_TCHECK(8);
        printf("\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
               EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
               (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
@@ -322,47 +335,140 @@ ldp_tlv_print(register const u_char *tptr) {
        break;
 
     case LDP_TLV_FEC:
+        TLV_TCHECK(1);
         fec_type = *tptr;
        printf("\n\t      %s FEC (0x%02x)",
               tok2str(ldp_fec_values, "Unknown", fec_type),
               fec_type);
 
        tptr+=1;
+       tlv_tlen-=1;
        switch(fec_type) {
 
        case LDP_FEC_WILDCARD:
            break;
        case LDP_FEC_PREFIX:
+           TLV_TCHECK(2);
            af = EXTRACT_16BITS(tptr);
-           tptr+=2;
+           tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
+           tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
            if (af == AFNUM_INET) {
-               i=decode_prefix4(tptr,buf,sizeof(buf));
-               printf(": IPv4 prefix %s",buf);
+               i=decode_prefix4(tptr,tlv_tlen,buf,sizeof(buf));
+               if (i == -2)
+                   goto trunc;
+               if (i == -3)
+                   printf(": IPv4 prefix (goes past end of TLV)");
+               else if (i == -1)
+                   printf(": IPv4 prefix (invalid length)");
+               else
+                   printf(": IPv4 prefix %s",buf);
            }
 #ifdef INET6
            else if (af == AFNUM_INET6) {
-               i=decode_prefix6(tptr,buf,sizeof(buf));
-               printf(": IPv6 prefix %s",buf);
+               i=decode_prefix6(tptr,tlv_tlen,buf,sizeof(buf));
+               if (i == -2)
+                   goto trunc;
+               if (i == -3)
+                   printf(": IPv4 prefix (goes past end of TLV)");
+               else if (i == -1)
+                   printf(": IPv6 prefix (invalid length)");
+               else
+                   printf(": IPv6 prefix %s",buf);
            }
 #endif
+           else
+               printf(": Address family %u prefix", af);
            break;
        case LDP_FEC_HOSTADDRESS:
            break;
        case LDP_FEC_MARTINI_VC:
-           printf(": %s, %scontrol word, VC %u",
-                  tok2str(ldp_vctype_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
+            /*
+            * According to RFC 4908, the VC info Length field can be zero,
+            * in which case not only are there no interface parameters,
+            * there's no VC ID.
+            */
+            TLV_TCHECK(7);
+            vc_info_len = *(tptr+2);
+
+            if (vc_info_len == 0) {
+                printf(": %s, %scontrol word, group-ID %u, VC-info-length: %u",
+                       tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
+                       EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
+                       EXTRACT_32BITS(tptr+3),
+                       vc_info_len);
+                break;
+            }
+
+            /* Make sure we have the VC ID as well */
+            TLV_TCHECK(11);
+           printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
+                  tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
                   EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
-                  EXTRACT_32BITS(tptr+7));
+                   EXTRACT_32BITS(tptr+3),
+                  EXTRACT_32BITS(tptr+7),
+                   vc_info_len);
+            if (vc_info_len < 4)
+                goto trunc; /* minimum 4, for the VC ID */
+            vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
+
+            /* Skip past the fixed information and the VC ID */
+            tptr+=11;
+            tlv_tlen-=11;
+            TLV_TCHECK(vc_info_len);
+
+            while (vc_info_len > 2) {
+                vc_info_tlv_type = *tptr;
+                vc_info_tlv_len = *(tptr+1);
+                if (vc_info_tlv_len < 2)
+                    break;
+                if (vc_info_len < vc_info_tlv_len)
+                    break;
+
+                printf("\n\t\tInterface Parameter: %s (0x%02x), len %u",
+                       tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
+                       vc_info_tlv_type,
+                       vc_info_tlv_len);
+
+                switch(vc_info_tlv_type) {
+                case LDP_FEC_MARTINI_IFPARM_MTU:
+                    printf(": %u",EXTRACT_16BITS(tptr+2));
+                    break;
+
+                case LDP_FEC_MARTINI_IFPARM_DESC:
+                    printf(": ");
+                    for (idx = 2; idx < vc_info_tlv_len; idx++)
+                        safeputchar(*(tptr+idx));
+                    break;
+
+                case LDP_FEC_MARTINI_IFPARM_VCCV:
+                    printf("\n\t\t  Control Channels (0x%02x) = [%s]",
+                           *(tptr+2),
+                           bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2)));
+                    printf("\n\t\t  CV Types (0x%02x) = [%s]",
+                           *(tptr+3),
+                           bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3)));
+                    break;
+
+                default:
+                    print_unknown_data(gndo,tptr+2,"\n\t\t  ",vc_info_tlv_len-2);
+                    break;
+                }
+
+                vc_info_len -= vc_info_tlv_len;
+                tptr += vc_info_tlv_len;
+            }
            break;
        }
 
        break;
 
     case LDP_TLV_GENERIC_LABEL:
+       TLV_TCHECK(4);
        printf("\n\t      Label: %u", EXTRACT_32BITS(tptr) & 0xfffff);
        break;
 
     case LDP_TLV_STATUS:
+       TLV_TCHECK(8);
        ui = EXTRACT_32BITS(tptr);
        tptr+=4;
        printf("\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
@@ -376,6 +482,7 @@ ldp_tlv_print(register const u_char *tptr) {
        break;
 
     case LDP_TLV_FT_SESSION:
+       TLV_TCHECK(8);
        ft_flags = EXTRACT_16BITS(tptr);
        printf("\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
               ft_flags&0x8000 ? "" : "No ",
@@ -393,6 +500,11 @@ ldp_tlv_print(register const u_char *tptr) {
            printf(", Recovery Time: %ums", ui);
        break;
 
+    case LDP_TLV_MTU:
+       TLV_TCHECK(2);
+       printf("\n\t      MTU: %u", EXTRACT_16BITS(tptr));
+       break;
+
 
     /*
      *  FIXME those are the defined TLVs that lack a decoder
@@ -412,20 +524,42 @@ ldp_tlv_print(register const u_char *tptr) {
 
     default:
         if (vflag <= 1)
-            print_unknown_data(tptr,"\n\t      ",tlv_tlen);
+            print_unknown_data(gndo,tptr,"\n\t      ",tlv_tlen);
         break;
     }
     return(tlv_len+4); /* Type & Length fields not included */
+
+trunc:
+    printf("\n\t\t packet exceeded snapshot");
+    return 0;
+
+badtlv:
+    printf("\n\t\t TLV contents go past end of TLV");
+    return(tlv_len+4); /* Type & Length fields not included */
 }
 
 void
 ldp_print(register const u_char *pptr, register u_int len) {
 
+    int processed;
+    while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
+        processed = ldp_msg_print(pptr);
+        if (processed == 0)
+            return;
+        len -= processed;
+        pptr += processed;
+    }
+}
+
+
+int
+ldp_msg_print(register const u_char *pptr) {
+
     const struct ldp_common_header *ldp_com_header;
     const struct ldp_msg_header *ldp_msg_header;
     const u_char *tptr,*msg_tptr;
     u_short tlen;
-    u_short msg_len,msg_type,msg_tlen;
+    u_short pdu_len,msg_len,msg_type,msg_tlen;
     int hexdump,processed;
 
     tptr=pptr;
@@ -436,32 +570,33 @@ ldp_print(register const u_char *pptr, register u_int len) {
      * Sanity checking of the header.
      */
     if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
-       printf("LDP version %u packet not supported",
+       printf("%sLDP version %u packet not supported",
+               (vflag < 1) ? "" : "\n\t",
                EXTRACT_16BITS(&ldp_com_header->version));
-       return;
+       return 0;
     }
 
     /* print the LSR-ID, label-space & length */
-    printf("%sLDP, Label-Space-ID: %s:%u, length: %u",
+    pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length);
+    printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
            (vflag < 1) ? "" : "\n\t",
            ipaddr_string(&ldp_com_header->lsr_id),
            EXTRACT_16BITS(&ldp_com_header->label_space),
-           len);
+           pdu_len);
 
-    /* bail out if non-verbose */ 
+    /* bail out if non-verbose */
     if (vflag < 1)
-        return;
+        return 0;
 
     /* ok they seem to want to know everything - lets fully decode it */
-    tlen=EXTRACT_16BITS(ldp_com_header->pdu_length);
+    tlen=pdu_len;
 
     tptr += sizeof(const struct ldp_common_header);
     tlen -= sizeof(const struct ldp_common_header)-4;  /* Type & Length fields not included */
 
     while(tlen>0) {
         /* did we capture enough for fully decoding the msg header ? */
-        if (!TTEST2(*tptr, sizeof(struct ldp_msg_header)))
-            goto trunc;
+        TCHECK2(*tptr, sizeof(struct ldp_msg_header));
 
         ldp_msg_header = (const struct ldp_msg_header *)tptr;
         msg_len=EXTRACT_16BITS(ldp_msg_header->length);
@@ -477,22 +612,26 @@ ldp_print(register const u_char *pptr, register u_int len) {
                EXTRACT_32BITS(&ldp_msg_header->id),
                LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore");
 
+        if (msg_len == 0) /* infinite loop protection */
+            return 0;
+
         msg_tptr=tptr+sizeof(struct ldp_msg_header);
         msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */
 
         /* did we capture enough for fully decoding the message ? */
-        if (!TTEST2(*tptr, msg_len))
-            goto trunc;
+        TCHECK2(*tptr, msg_len);
         hexdump=FALSE;
 
         switch(msg_type) {
+
         case LDP_MSG_NOTIF:
         case LDP_MSG_HELLO:
         case LDP_MSG_INIT:
         case LDP_MSG_KEEPALIVE:
         case LDP_MSG_ADDRESS:
         case LDP_MSG_LABEL_MAPPING:
+        case LDP_MSG_ADDRESS_WITHDRAW:
+        case LDP_MSG_LABEL_WITHDRAW:
             while(msg_tlen >= 4) {
                 processed = ldp_tlv_print(msg_tptr);
                 if (processed == 0)
@@ -507,27 +646,32 @@ ldp_print(register const u_char *pptr, register u_int len) {
          *  you are welcome to contribute code ;-)
          */
 
-        case LDP_MSG_ADDRESS_WITHDRAW:
         case LDP_MSG_LABEL_REQUEST:
-        case LDP_MSG_LABEL_WITHDRAW:
         case LDP_MSG_LABEL_RELEASE:
         case LDP_MSG_LABEL_ABORT_REQUEST:
 
         default:
             if (vflag <= 1)
-                print_unknown_data(msg_tptr,"\n\t  ",msg_tlen);
+                print_unknown_data(gndo,msg_tptr,"\n\t  ",msg_tlen);
             break;
         }
         /* do we want to see an additionally hexdump ? */
         if (vflag > 1 || hexdump==TRUE)
-            print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t  ",
+            print_unknown_data(gndo,tptr+sizeof(struct ldp_msg_header),"\n\t  ",
                                msg_len);
 
         tptr += msg_len+4;
         tlen -= msg_len+4;
     }
-    return;
+    return pdu_len+4;
 trunc:
     printf("\n\t\t packet exceeded snapshot");
+    return 0;
 }
 
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */