]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-l2tp.c
More UNALIGNED_MEM{CPY,CMP} on IP addresses.
[tcpdump] / print-l2tp.c
index c955d4b3ac12521fb3bb6d91abafc3858360ee05..ca98e9a9b8016893da21dbe764ff62663640198b 100644 (file)
  * L2TP support contributed by Motonori Shindo ([email protected])
  */
 
-#ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.10 2001-11-10 21:37:58 guy Exp $";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#include <tcpdump-stdinc.h>
+
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
-#include "l2tp.h"
 #include "interface.h"
+#include "extract.h"
 
-static char tstr[] = " [|l2tp]";
+#define L2TP_FLAG_TYPE         0x8000  /* Type (0=Data, 1=Control) */
+#define L2TP_FLAG_LENGTH       0x4000  /* Length */
+#define L2TP_FLAG_SEQUENCE     0x0800  /* Sequence */
+#define L2TP_FLAG_OFFSET       0x0200  /* Offset */
+#define L2TP_FLAG_PRIORITY     0x0100  /* Priority */
 
-#ifndef TRUE
-#define TRUE 1
-#endif
+#define L2TP_VERSION_MASK      0x000f  /* Version Mask */
+#define L2TP_VERSION_L2F       0x0001  /* L2F */
+#define L2TP_VERSION_L2TP      0x0002  /* L2TP */
 
-#ifndef FALSE
-#define FALSE 0
-#endif
+#define L2TP_AVP_HDR_FLAG_MANDATORY    0x8000  /* Mandatory Flag */
+#define L2TP_AVP_HDR_FLAG_HIDDEN       0x4000  /* Hidden Flag */
+#define L2TP_AVP_HDR_LEN_MASK          0x03ff  /* Length Mask */
+
+#define L2TP_FRAMING_CAP_SYNC_MASK     0x00000001      /* Synchronous */
+#define L2TP_FRAMING_CAP_ASYNC_MASK    0x00000002      /* Asynchronous */
+
+#define L2TP_FRAMING_TYPE_SYNC_MASK    0x00000001      /* Synchronous */
+#define L2TP_FRAMING_TYPE_ASYNC_MASK   0x00000002      /* Asynchronous */
+
+#define L2TP_BEARER_CAP_DIGITAL_MASK   0x00000001      /* Digital */
+#define L2TP_BEARER_CAP_ANALOG_MASK    0x00000002      /* Analog */
+
+#define L2TP_BEARER_TYPE_DIGITAL_MASK  0x00000001      /* Digital */
+#define L2TP_BEARER_TYPE_ANALOG_MASK   0x00000002      /* Analog */
+
+/* Authen Type */
+#define L2TP_AUTHEN_TYPE_RESERVED      0x0000  /* Reserved */
+#define L2TP_AUTHEN_TYPE_TEXTUAL       0x0001  /* Textual username/password exchange */
+#define L2TP_AUTHEN_TYPE_CHAP          0x0002  /* PPP CHAP */
+#define L2TP_AUTHEN_TYPE_PAP           0x0003  /* PPP PAP */
+#define L2TP_AUTHEN_TYPE_NO_AUTH       0x0004  /* No Authentication */
+#define L2TP_AUTHEN_TYPE_MSCHAPv1      0x0005  /* MSCHAPv1 */
+
+#define L2TP_PROXY_AUTH_ID_MASK                0x00ff
+
+static const char tstr[] = " [|l2tp]";
 
 #define        L2TP_MSGTYPE_SCCRQ      1  /* Start-Control-Connection-Request */
 #define        L2TP_MSGTYPE_SCCRP      2  /* Start-Control-Connection-Reply */
@@ -64,7 +85,7 @@ static char tstr[] = " [|l2tp]";
 #define        L2TP_MSGTYPE_WEN        15 /* WAN-Error-Notify */
 #define        L2TP_MSGTYPE_SLI        16 /* Set-Link-Info */
 
-static struct tok l2tp_msgtype2str[] = {
+static const struct tok l2tp_msgtype2str[] = {
        { L2TP_MSGTYPE_SCCRQ,   "SCCRQ" },
        { L2TP_MSGTYPE_SCCRP,   "SCCRP" },
        { L2TP_MSGTYPE_SCCCN,   "SCCCN" },
@@ -124,7 +145,7 @@ static struct tok l2tp_msgtype2str[] = {
 #define L2TP_AVP_SEQ_REQUIRED          39 /* Sequencing Required */
 #define L2TP_AVP_PPP_DISCON_CC         46 /* PPP Disconnect Cause Code */
 
-static struct tok l2tp_avp2str[] = {
+static const struct tok l2tp_avp2str[] = {
        { L2TP_AVP_MSGTYPE,             "MSGTYPE" },
        { L2TP_AVP_RESULT_CODE,         "RESULT_CODE" },
        { L2TP_AVP_PROTO_VER,           "PROTO_VER" },
@@ -145,31 +166,31 @@ static struct tok l2tp_avp2str[] = {
        { L2TP_AVP_MAXIMUM_BPS,         "MAXIMUM_BPS" },
        { L2TP_AVP_BEARER_TYPE,         "BEARER_TYPE" },
        { L2TP_AVP_FRAMING_TYPE,        "FRAMING_TYPE" },
-       { L2TP_AVP_PACKET_PROC_DELAY,   "PACKET_PROC_DELAY" },  
+       { L2TP_AVP_PACKET_PROC_DELAY,   "PACKET_PROC_DELAY" },
        { L2TP_AVP_CALLED_NUMBER,       "CALLED_NUMBER" },
        { L2TP_AVP_CALLING_NUMBER,      "CALLING_NUMBER" },
        { L2TP_AVP_SUB_ADDRESS,         "SUB_ADDRESS" },
        { L2TP_AVP_TX_CONN_SPEED,       "TX_CONN_SPEED" },
        { L2TP_AVP_PHY_CHANNEL_ID,      "PHY_CHANNEL_ID" },
        { L2TP_AVP_INI_RECV_LCP,        "INI_RECV_LCP" },
-       { L2TP_AVP_LAST_SENT_LCP,       "LAST_SENT_LCP" },      
-       { L2TP_AVP_LAST_RECV_LCP,       "LAST_RECV_LCP" },      
-       { L2TP_AVP_PROXY_AUTH_TYPE,     "PROXY_AUTH_TYPE" },    
+       { L2TP_AVP_LAST_SENT_LCP,       "LAST_SENT_LCP" },
+       { L2TP_AVP_LAST_RECV_LCP,       "LAST_RECV_LCP" },
+       { L2TP_AVP_PROXY_AUTH_TYPE,     "PROXY_AUTH_TYPE" },
        { L2TP_AVP_PROXY_AUTH_NAME,     "PROXY_AUTH_NAME" },
-       { L2TP_AVP_PROXY_AUTH_CHAL,     "PROXY_AUTH_CHAL" },    
+       { L2TP_AVP_PROXY_AUTH_CHAL,     "PROXY_AUTH_CHAL" },
        { L2TP_AVP_PROXY_AUTH_ID,       "PROXY_AUTH_ID" },
        { L2TP_AVP_PROXY_AUTH_RESP,     "PROXY_AUTH_RESP" },
        { L2TP_AVP_CALL_ERRORS,         "CALL_ERRORS" },
-       { L2TP_AVP_ACCM,                "ACCM" },               
-       { L2TP_AVP_RANDOM_VECTOR,       "RANDOM_VECTOR" },      
+       { L2TP_AVP_ACCM,                "ACCM" },
+       { L2TP_AVP_RANDOM_VECTOR,       "RANDOM_VECTOR" },
        { L2TP_AVP_PRIVATE_GRP_ID,      "PRIVATE_GRP_ID" },
-       { L2TP_AVP_RX_CONN_SPEED,       "RX_CONN_SPEED" },      
-       { L2TP_AVP_SEQ_REQUIRED,        "SEQ_REQUIRED" },       
-       { L2TP_AVP_PPP_DISCON_CC,       "PPP_DISCON_CC" },      
+       { L2TP_AVP_RX_CONN_SPEED,       "RX_CONN_SPEED" },
+       { L2TP_AVP_SEQ_REQUIRED,        "SEQ_REQUIRED" },
+       { L2TP_AVP_PPP_DISCON_CC,       "PPP_DISCON_CC" },
        { 0,                            NULL }
 };
 
-static struct tok l2tp_authentype2str[] = {
+static const struct tok l2tp_authentype2str[] = {
        { L2TP_AUTHEN_TYPE_RESERVED,    "Reserved" },
        { L2TP_AUTHEN_TYPE_TEXTUAL,     "Textual" },
        { L2TP_AUTHEN_TYPE_CHAP,        "CHAP" },
@@ -183,7 +204,7 @@ static struct tok l2tp_authentype2str[] = {
 #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER   1
 #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL  2
 
-static struct tok l2tp_cc_direction2str[] = {
+static const struct tok l2tp_cc_direction2str[] = {
        { L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,  "global error" },
        { L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER, "at peer" },
        { L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
@@ -242,19 +263,19 @@ static char *l2tp_error_code_general[] = {
 /******************************/
 /* generic print out routines */
 /******************************/
-static void 
+static void
 print_string(const u_char *dat, u_int length)
 {
-       int i;
+       u_int i;
        for (i=0; i<length; i++) {
                printf("%c", *dat++);
        }
 }
 
-static void 
+static void
 print_octets(const u_char *dat, u_int length)
 {
-       int i;
+       u_int i;
        for (i=0; i<length; i++) {
                printf("%02x", *dat++);
        }
@@ -263,13 +284,13 @@ print_octets(const u_char *dat, u_int length)
 static void
 print_16bits_val(const u_int16_t *dat)
 {
-       printf("%u", ntohs(*dat));
+       printf("%u", EXTRACT_16BITS(dat));
 }
 
 static void
 print_32bits_val(const u_int32_t *dat)
 {
-       printf("%lu", (u_long)ntohl(*dat));
+       printf("%lu", (u_long)EXTRACT_32BITS(dat));
 }
 
 /***********************************/
@@ -280,19 +301,20 @@ l2tp_msgtype_print(const u_char *dat)
 {
        u_int16_t *ptr = (u_int16_t*)dat;
 
-       printf("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u", ntohs(*ptr)));
+       printf("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
+           EXTRACT_16BITS(ptr)));
 }
 
 static void
 l2tp_result_code_print(const u_char *dat, u_int length)
 {
        u_int16_t *ptr = (u_int16_t *)dat;
-       
-       printf("%u", ntohs(*ptr++));            /* Result Code */
-       if (length > 2) {                       /* Error Code (opt) */
-               printf("/%u", ntohs(*ptr++));   
+
+       printf("%u", EXTRACT_16BITS(ptr)); ptr++;       /* Result Code */
+       if (length > 2) {                               /* Error Code (opt) */
+               printf("/%u", EXTRACT_16BITS(ptr)); ptr++;
        }
-       if (length > 4) {                       /* Error Message (opt) */
+       if (length > 4) {                               /* Error Message (opt) */
                printf(" ");
                print_string((u_char *)ptr, length - 4);
        }
@@ -301,7 +323,8 @@ l2tp_result_code_print(const u_char *dat, u_int length)
 static void
 l2tp_proto_ver_print(const u_int16_t *dat)
 {
-       printf("%u.%u", (ntohs(*dat) >> 8), (ntohs(*dat) & 0xff));
+       printf("%u.%u", (EXTRACT_16BITS(dat) >> 8),
+           (EXTRACT_16BITS(dat) & 0xff));
 }
 
 static void
@@ -309,10 +332,10 @@ l2tp_framing_cap_print(const u_char *dat)
 {
        u_int32_t *ptr = (u_int32_t *)dat;
 
-       if (ntohl(*ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
                printf("A");
        }
-       if (ntohl(*ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
                printf("S");
        }
 }
@@ -322,10 +345,10 @@ l2tp_bearer_cap_print(const u_char *dat)
 {
        u_int32_t *ptr = (u_int32_t *)dat;
 
-       if (ntohl(*ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
                printf("A");
        }
-       if (ntohl(*ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
                printf("D");
        }
 }
@@ -338,7 +361,7 @@ l2tp_q931_cc_print(const u_char *dat, u_int length)
        if (length > 3) {
                printf(" ");
                print_string(dat+3, length-3);
-       } 
+       }
 }
 
 static void
@@ -346,10 +369,10 @@ l2tp_bearer_type_print(const u_char *dat)
 {
        u_int32_t *ptr = (u_int32_t *)dat;
 
-       if (ntohl(*ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
                printf("A");
        }
-       if (ntohl(*ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
                printf("D");
        }
 }
@@ -359,10 +382,10 @@ l2tp_framing_type_print(const u_char *dat)
 {
        u_int32_t *ptr = (u_int32_t *)dat;
 
-       if (ntohl(*ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
                printf("A");
        }
-       if (ntohl(*ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
+       if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
                printf("S");
        }
 }
@@ -378,8 +401,8 @@ l2tp_proxy_auth_type_print(const u_char *dat)
 {
        u_int16_t *ptr = (u_int16_t *)dat;
 
-       printf("%s", tok2str(l2tp_authentype2str, 
-                            "AuthType-#%u", ntohs(*ptr)));
+       printf("%s", tok2str(l2tp_authentype2str,
+                            "AuthType-#%u", EXTRACT_16BITS(ptr)));
 }
 
 static void
@@ -387,7 +410,7 @@ l2tp_proxy_auth_id_print(const u_char *dat)
 {
        u_int16_t *ptr = (u_int16_t *)dat;
 
-       printf("%u", ntohs(*ptr) & L2TP_PROXY_AUTH_ID_MASK);
+       printf("%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK);
 }
 
 static void
@@ -395,31 +418,31 @@ l2tp_call_errors_print(const u_char *dat)
 {
        u_int16_t *ptr = (u_int16_t *)dat;
        u_int16_t val_h, val_l;
-       
+
        ptr++;          /* skip "Reserved" */
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("CRCErr=%u ", (val_h<<16) + val_l);
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("FrameErr=%u ", (val_h<<16) + val_l);
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("HardOver=%u ", (val_h<<16) + val_l);
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("BufOver=%u ", (val_h<<16) + val_l);
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("Timeout=%u ", (val_h<<16) + val_l);
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("AlignErr=%u ", (val_h<<16) + val_l);
 }
 
@@ -431,12 +454,12 @@ l2tp_accm_print(const u_char *dat)
 
        ptr++;          /* skip "Reserved" */
 
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("send=%08x ", (val_h<<16) + val_l);
-       
-       val_h = ntohs(*ptr++);
-       val_l = ntohs(*ptr++);
+
+       val_h = EXTRACT_16BITS(ptr); ptr++;
+       val_l = EXTRACT_16BITS(ptr); ptr++;
        printf("recv=%08x ", (val_h<<16) + val_l);
 }
 
@@ -444,10 +467,10 @@ static void
 l2tp_ppp_discon_cc_print(const u_char *dat, u_int length)
 {
        u_int16_t *ptr = (u_int16_t *)dat;
-       
-       printf("%04x, ", ntohs(*ptr++));        /* Disconnect Code */
-       printf("%04x ",  ntohs(*ptr++));        /* Control Protocol Number */
-       printf("%s", tok2str(l2tp_cc_direction2str, 
+
+       printf("%04x, ", EXTRACT_16BITS(ptr)); ptr++;   /* Disconnect Code */
+       printf("%04x ",  EXTRACT_16BITS(ptr)); ptr++;   /* Control Protocol Number */
+       printf("%s", tok2str(l2tp_cc_direction2str,
                             "Direction-#%u", *((u_char *)ptr++)));
 
        if (length > 5) {
@@ -471,33 +494,42 @@ l2tp_avp_print(const u_char *dat, int length)
        printf(" ");
 
        TCHECK(*ptr);   /* Flags & Length */
-       len = ntohs(*ptr) & L2TP_AVP_HDR_LEN_MASK;
+       len = EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_LEN_MASK;
+
+       /* If it is not long enough to contain the header, we'll give up. */
+       if (len < 6)
+               goto trunc;
 
-       /* If it is not long enough to decode the entire AVP, we'll 
-          abandon. */
+       /* If it goes past the end of the remaining length of the packet,
+          we'll give up. */
+       if (len > (u_int)length)
+               goto trunc;
+
+       /* If it goes past the end of the remaining length of the captured
+          data, we'll give up. */
        TCHECK2(*ptr, len);
        /* After this point, no need to worry about truncation */
 
-       if (ntohs(*ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
+       if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
                printf("*");
        }
-       if (ntohs(*ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
+       if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
                hidden = TRUE;
                printf("?");
        }
        ptr++;
 
-       if (ntohs(*ptr)) {
+       if (EXTRACT_16BITS(ptr)) {
                /* Vendor Specific Attribute */
-               printf("VENDOR%04x:", ntohs(*ptr++));
-               printf("ATTR%04x", ntohs(*ptr++));
+               printf("VENDOR%04x:", EXTRACT_16BITS(ptr)); ptr++;
+               printf("ATTR%04x", EXTRACT_16BITS(ptr)); ptr++;
                printf("(");
                print_octets((u_char *)ptr, len-6);
                printf(")");
        } else {
-               /* IETF-defined Attributes */ 
+               /* IETF-defined Attributes */
                ptr++;
-               attr_type = ntohs(*ptr++);
+               attr_type = EXTRACT_16BITS(ptr); ptr++;
                printf("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
                printf("(");
                if (hidden) {
@@ -534,7 +566,7 @@ l2tp_avp_print(const u_char *dat, int length)
                        case L2TP_AVP_CALLED_NUMBER:
                        case L2TP_AVP_SUB_ADDRESS:
                        case L2TP_AVP_PROXY_AUTH_NAME:
-                       case L2TP_AVP_PRIVATE_GRP_ID:   
+                       case L2TP_AVP_PRIVATE_GRP_ID:
                                print_string((u_char *)ptr, len-6);
                                break;
                        case L2TP_AVP_CHALLENGE:
@@ -604,18 +636,18 @@ l2tp_avp_print(const u_char *dat, int length)
 void
 l2tp_print(const u_char *dat, u_int length)
 {
-       const u_int16_t *ptr = (u_int16_t *)dat;
+       const u_char *ptr = dat;
        u_int cnt = 0;                  /* total octets consumed */
        u_int16_t pad;
-       int flag_t, flag_l, flag_s, flag_o, flag_p;
+       int flag_t, flag_l, flag_s, flag_o;
        u_int16_t l2tp_len;
 
-       flag_t = flag_l = flag_s = flag_o = flag_p = FALSE;
+       flag_t = flag_l = flag_s = flag_o = FALSE;
 
-       TCHECK(*ptr);   /* Flags & Version */
-       if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
+       TCHECK2(*ptr, 2);       /* Flags & Version */
+       if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
                printf(" l2tp:");
-       } else if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
+       } else if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
                printf(" l2f:");
                return;         /* nothing to do */
        } else {
@@ -624,71 +656,89 @@ l2tp_print(const u_char *dat, u_int length)
        }
 
        printf("[");
-       if (ntohs(*ptr) & L2TP_FLAG_TYPE) {
+       if (EXTRACT_16BITS(ptr) & L2TP_FLAG_TYPE) {
                flag_t = TRUE;
                printf("T");
        }
-       if (ntohs(*ptr) & L2TP_FLAG_LENGTH) {
+       if (EXTRACT_16BITS(ptr) & L2TP_FLAG_LENGTH) {
                flag_l = TRUE;
                printf("L");
        }
-       if (ntohs(*ptr) & L2TP_FLAG_SEQUENCE) {
+       if (EXTRACT_16BITS(ptr) & L2TP_FLAG_SEQUENCE) {
                flag_s = TRUE;
                printf("S");
        }
-       if (ntohs(*ptr) & L2TP_FLAG_OFFSET) {
+       if (EXTRACT_16BITS(ptr) & L2TP_FLAG_OFFSET) {
                flag_o = TRUE;
                printf("O");
        }
-       if (ntohs(*ptr) & L2TP_FLAG_PRIORITY) {
-               flag_p = TRUE;
+       if (EXTRACT_16BITS(ptr) & L2TP_FLAG_PRIORITY)
                printf("P");
-       }
        printf("]");
 
-       ptr++;
+       ptr += 2;
        cnt += 2;
-       
+
        if (flag_l) {
-               TCHECK(*ptr);   /* Length */
-               l2tp_len = ntohs(*ptr++);
+               TCHECK2(*ptr, 2);       /* Length */
+               l2tp_len = EXTRACT_16BITS(ptr);
+               ptr += 2;
                cnt += 2;
        } else {
                l2tp_len = 0;
        }
 
-       TCHECK(*ptr);           /* Tunnel ID */
-       printf("(%u/", ntohs(*ptr++));
+       TCHECK2(*ptr, 2);               /* Tunnel ID */
+       printf("(%u/", EXTRACT_16BITS(ptr));
+       ptr += 2;
        cnt += 2;
-       TCHECK(*ptr);           /* Session ID */
-       printf("%u)",  ntohs(*ptr++));
+       TCHECK2(*ptr, 2);               /* Session ID */
+       printf("%u)",  EXTRACT_16BITS(ptr));
+       ptr += 2;
        cnt += 2;
 
        if (flag_s) {
-               TCHECK(*ptr);   /* Ns */
-               printf("Ns=%u,", ntohs(*ptr++));
+               TCHECK2(*ptr, 2);       /* Ns */
+               printf("Ns=%u,", EXTRACT_16BITS(ptr));
+               ptr += 2;
                cnt += 2;
-               TCHECK(*ptr);   /* Nr */
-               printf("Nr=%u",  ntohs(*ptr++));
+               TCHECK2(*ptr, 2);       /* Nr */
+               printf("Nr=%u",  EXTRACT_16BITS(ptr));
+               ptr += 2;
                cnt += 2;
        }
 
        if (flag_o) {
-               TCHECK(*ptr);   /* Offset Size */
-               pad =  ntohs(*ptr++);
-               ptr += pad / sizeof(*ptr);
+               TCHECK2(*ptr, 2);       /* Offset Size */
+               pad =  EXTRACT_16BITS(ptr);
+               ptr += (2 + pad);
                cnt += (2 + pad);
        }
 
+       if (flag_l) {
+               if (length < l2tp_len) {
+                       printf(" Length %u larger than packet", l2tp_len);
+                       return;
+               }
+               length = l2tp_len;
+       }
+       if (length < cnt) {
+               printf(" Length %u smaller than header length", length);
+               return;
+       }
        if (flag_t) {
+               if (!flag_l) {
+                       printf(" No length");
+                       return;
+               }
                if (length - cnt == 0) {
                        printf(" ZLB");
                } else {
-                       l2tp_avp_print((u_char *)ptr, length - cnt);
+                       l2tp_avp_print(ptr, length - cnt);
                }
        } else {
                printf(" {");
-               ppp_print((u_char *)ptr, length - cnt);
+               ppp_print(ptr, length - cnt);
                printf("}");
        }
 
@@ -696,4 +746,4 @@ l2tp_print(const u_char *dat, u_int length)
 
  trunc:
        printf("%s", tstr);
-}      
+}