Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
      3  *      The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code distributions
      7  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  * distributions including binary code include the above copyright notice and
      9  * this paragraph in its entirety in the documentation or other materials
     10  * provided with the distribution, and (3) all advertising materials mentioning
     11  * features or use of this software display the following acknowledgement:
     12  * ``This product includes software developed by the University of California,
     13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  * the University nor the names of its contributors may be used to endorse
     15  * or promote products derived from this software without specific prior
     16  * written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  *
     21  * PPTP support contributed by Motonori Shindo (mshindo (at) mshindo.net)
     22  */
     23 
     24 #include <sys/cdefs.h>
     25 #ifndef lint
     26 __RCSID("$NetBSD: print-pptp.c,v 1.8 2024/09/02 16:15:32 christos Exp $");
     27 #endif
     28 
     29 /* \summary: Point-to-Point Tunnelling Protocol (PPTP) printer */
     30 
     31 /* specification: RFC 2637 */
     32 
     33 #include <config.h>
     34 
     35 #include "netdissect-stdinc.h"
     36 
     37 #include "netdissect.h"
     38 #include "extract.h"
     39 
     40 
     41 #define PPTP_MSG_TYPE_CTRL	1	/* Control Message */
     42 #define PPTP_MSG_TYPE_MGMT	2	/* Management Message (currently not used */
     43 #define PPTP_MAGIC_COOKIE	0x1a2b3c4d	/* for sanity check */
     44 
     45 #define PPTP_CTRL_MSG_TYPE_SCCRQ	1
     46 #define PPTP_CTRL_MSG_TYPE_SCCRP	2
     47 #define PPTP_CTRL_MSG_TYPE_StopCCRQ	3
     48 #define PPTP_CTRL_MSG_TYPE_StopCCRP	4
     49 #define PPTP_CTRL_MSG_TYPE_ECHORQ	5
     50 #define PPTP_CTRL_MSG_TYPE_ECHORP	6
     51 #define PPTP_CTRL_MSG_TYPE_OCRQ		7
     52 #define PPTP_CTRL_MSG_TYPE_OCRP		8
     53 #define PPTP_CTRL_MSG_TYPE_ICRQ		9
     54 #define PPTP_CTRL_MSG_TYPE_ICRP		10
     55 #define PPTP_CTRL_MSG_TYPE_ICCN		11
     56 #define PPTP_CTRL_MSG_TYPE_CCRQ		12
     57 #define PPTP_CTRL_MSG_TYPE_CDN		13
     58 #define PPTP_CTRL_MSG_TYPE_WEN		14
     59 #define PPTP_CTRL_MSG_TYPE_SLI		15
     60 
     61 #define PPTP_FRAMING_CAP_ASYNC_MASK	0x00000001      /* Asynchronous */
     62 #define PPTP_FRAMING_CAP_SYNC_MASK	0x00000002      /* Synchronous */
     63 
     64 #define PPTP_BEARER_CAP_ANALOG_MASK	0x00000001      /* Analog */
     65 #define PPTP_BEARER_CAP_DIGITAL_MASK	0x00000002      /* Digital */
     66 
     67 static const char *pptp_message_type_string[] = {
     68 	"NOT_DEFINED",		/* 0  Not defined in the RFC2637 */
     69 	"SCCRQ",		/* 1  Start-Control-Connection-Request */
     70 	"SCCRP",		/* 2  Start-Control-Connection-Reply */
     71 	"StopCCRQ",		/* 3  Stop-Control-Connection-Request */
     72 	"StopCCRP",		/* 4  Stop-Control-Connection-Reply */
     73 	"ECHORQ",		/* 5  Echo Request */
     74 	"ECHORP",		/* 6  Echo Reply */
     75 
     76 	"OCRQ",			/* 7  Outgoing-Call-Request */
     77 	"OCRP",			/* 8  Outgoing-Call-Reply */
     78 	"ICRQ",			/* 9  Incoming-Call-Request */
     79 	"ICRP",			/* 10 Incoming-Call-Reply */
     80 	"ICCN",			/* 11 Incoming-Call-Connected */
     81 	"CCRQ",			/* 12 Call-Clear-Request */
     82 	"CDN",			/* 13 Call-Disconnect-Notify */
     83 
     84 	"WEN",			/* 14 WAN-Error-Notify */
     85 
     86 	"SLI"			/* 15 Set-Link-Info */
     87 #define PPTP_MAX_MSGTYPE_INDEX	16
     88 };
     89 
     90 /* common for all PPTP control messages */
     91 struct pptp_hdr {
     92 	nd_uint16_t length;
     93 	nd_uint16_t msg_type;
     94 	nd_uint32_t magic_cookie;
     95 	nd_uint16_t ctrl_msg_type;
     96 	nd_uint16_t reserved0;
     97 };
     98 
     99 struct pptp_msg_sccrq {
    100 	nd_uint16_t proto_ver;
    101 	nd_uint16_t reserved1;
    102 	nd_uint32_t framing_cap;
    103 	nd_uint32_t bearer_cap;
    104 	nd_uint16_t max_channel;
    105 	nd_uint16_t firm_rev;
    106 	nd_byte     hostname[64];
    107 	nd_byte     vendor[64];
    108 };
    109 
    110 struct pptp_msg_sccrp {
    111 	nd_uint16_t proto_ver;
    112 	nd_uint8_t  result_code;
    113 	nd_uint8_t  err_code;
    114 	nd_uint32_t framing_cap;
    115 	nd_uint32_t bearer_cap;
    116 	nd_uint16_t max_channel;
    117 	nd_uint16_t firm_rev;
    118 	nd_byte     hostname[64];
    119 	nd_byte     vendor[64];
    120 };
    121 
    122 struct pptp_msg_stopccrq {
    123 	nd_uint8_t  reason;
    124 	nd_uint8_t  reserved1;
    125 	nd_uint16_t reserved2;
    126 };
    127 
    128 struct pptp_msg_stopccrp {
    129 	nd_uint8_t  result_code;
    130 	nd_uint8_t  err_code;
    131 	nd_uint16_t reserved1;
    132 };
    133 
    134 struct pptp_msg_echorq {
    135 	nd_uint32_t id;
    136 };
    137 
    138 struct pptp_msg_echorp {
    139 	nd_uint32_t id;
    140 	nd_uint8_t  result_code;
    141 	nd_uint8_t  err_code;
    142 	nd_uint16_t reserved1;
    143 };
    144 
    145 struct pptp_msg_ocrq {
    146 	nd_uint16_t call_id;
    147 	nd_uint16_t call_ser;
    148 	nd_uint32_t min_bps;
    149 	nd_uint32_t max_bps;
    150 	nd_uint32_t bearer_type;
    151 	nd_uint32_t framing_type;
    152 	nd_uint16_t recv_winsiz;
    153 	nd_uint16_t pkt_proc_delay;
    154 	nd_uint16_t phone_no_len;
    155 	nd_uint16_t reserved1;
    156 	nd_byte     phone_no[64];
    157 	nd_byte     subaddr[64];
    158 };
    159 
    160 struct pptp_msg_ocrp {
    161 	nd_uint16_t call_id;
    162 	nd_uint16_t peer_call_id;
    163 	nd_uint8_t  result_code;
    164 	nd_uint8_t  err_code;
    165 	nd_uint16_t cause_code;
    166 	nd_uint32_t conn_speed;
    167 	nd_uint16_t recv_winsiz;
    168 	nd_uint16_t pkt_proc_delay;
    169 	nd_uint32_t phy_chan_id;
    170 };
    171 
    172 struct pptp_msg_icrq {
    173 	nd_uint16_t call_id;
    174 	nd_uint16_t call_ser;
    175 	nd_uint32_t bearer_type;
    176 	nd_uint32_t phy_chan_id;
    177 	nd_uint16_t dialed_no_len;
    178 	nd_uint16_t dialing_no_len;
    179 	nd_byte     dialed_no[64];		/* DNIS */
    180 	nd_byte     dialing_no[64];		/* CLID */
    181 	nd_byte     subaddr[64];
    182 };
    183 
    184 struct pptp_msg_icrp {
    185 	nd_uint16_t call_id;
    186 	nd_uint16_t peer_call_id;
    187 	nd_uint8_t  result_code;
    188 	nd_uint8_t  err_code;
    189 	nd_uint16_t recv_winsiz;
    190 	nd_uint16_t pkt_proc_delay;
    191 	nd_uint16_t reserved1;
    192 };
    193 
    194 struct pptp_msg_iccn {
    195 	nd_uint16_t peer_call_id;
    196 	nd_uint16_t reserved1;
    197 	nd_uint32_t conn_speed;
    198 	nd_uint16_t recv_winsiz;
    199 	nd_uint16_t pkt_proc_delay;
    200 	nd_uint32_t framing_type;
    201 };
    202 
    203 struct pptp_msg_ccrq {
    204 	nd_uint16_t call_id;
    205 	nd_uint16_t reserved1;
    206 };
    207 
    208 struct pptp_msg_cdn {
    209 	nd_uint16_t call_id;
    210 	nd_uint8_t  result_code;
    211 	nd_uint8_t  err_code;
    212 	nd_uint16_t cause_code;
    213 	nd_uint16_t reserved1;
    214 	nd_byte     call_stats[128];
    215 };
    216 
    217 struct pptp_msg_wen {
    218 	nd_uint16_t peer_call_id;
    219 	nd_uint16_t reserved1;
    220 	nd_uint32_t crc_err;
    221 	nd_uint32_t framing_err;
    222 	nd_uint32_t hardware_overrun;
    223 	nd_uint32_t buffer_overrun;
    224 	nd_uint32_t timeout_err;
    225 	nd_uint32_t align_err;
    226 };
    227 
    228 struct pptp_msg_sli {
    229 	nd_uint16_t peer_call_id;
    230 	nd_uint16_t reserved1;
    231 	nd_uint32_t send_accm;
    232 	nd_uint32_t recv_accm;
    233 };
    234 
    235 /* attributes that appear more than once in above messages:
    236 
    237    Number of
    238    occurrence    attributes
    239   --------------------------------------
    240       2         uint32_t bearer_cap;
    241       2         uint32_t bearer_type;
    242       6         uint16_t call_id;
    243       2         uint16_t call_ser;
    244       2         uint16_t cause_code;
    245       2         uint32_t conn_speed;
    246       6         uint8_t err_code;
    247       2         uint16_t firm_rev;
    248       2         uint32_t framing_cap;
    249       2         uint32_t framing_type;
    250       2         u_char hostname[64];
    251       2         uint32_t id;
    252       2         uint16_t max_channel;
    253       5         uint16_t peer_call_id;
    254       2         uint32_t phy_chan_id;
    255       4         uint16_t pkt_proc_delay;
    256       2         uint16_t proto_ver;
    257       4         uint16_t recv_winsiz;
    258       2         uint8_t reserved1;
    259       9         uint16_t reserved1;
    260       6         uint8_t result_code;
    261       2         u_char subaddr[64];
    262       2         u_char vendor[64];
    263 
    264   so I will prepare print out functions for these attributes (except for
    265   reserved*).
    266 */
    267 
    268 #define PRINT_RESERVED_IF_NOT_ZERO_1(reserved) \
    269         if (GET_U_1(reserved)) \
    270 		ND_PRINT(" [ERROR: reserved=%u must be zero]", \
    271 			 GET_U_1(reserved));
    272 
    273 #define PRINT_RESERVED_IF_NOT_ZERO_2(reserved) \
    274         if (GET_BE_U_2(reserved)) \
    275 		ND_PRINT(" [ERROR: reserved=%u must be zero]", \
    276 			 GET_BE_U_2(reserved));
    277 
    278 /******************************************/
    279 /* Attribute-specific print out functions */
    280 /******************************************/
    281 
    282 static void
    283 pptp_bearer_cap_print(netdissect_options *ndo,
    284                       const nd_uint32_t bearer_cap)
    285 {
    286 	ND_PRINT(" BEARER_CAP(%s%s)",
    287 	          GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_DIGITAL_MASK ? "D" : "",
    288 	          GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_ANALOG_MASK ? "A" : "");
    289 }
    290 
    291 static const struct tok pptp_btype_str[] = {
    292 	{ 1, "A"   }, /* Analog */
    293 	{ 2, "D"   }, /* Digital */
    294 	{ 3, "Any" },
    295 	{ 0, NULL }
    296 };
    297 
    298 static void
    299 pptp_bearer_type_print(netdissect_options *ndo,
    300                        const nd_uint32_t bearer_type)
    301 {
    302 	ND_PRINT(" BEARER_TYPE(%s)",
    303 	          tok2str(pptp_btype_str, "?", GET_BE_U_4(bearer_type)));
    304 }
    305 
    306 static void
    307 pptp_call_id_print(netdissect_options *ndo,
    308                    const nd_uint16_t call_id)
    309 {
    310 	ND_PRINT(" CALL_ID(%u)", GET_BE_U_2(call_id));
    311 }
    312 
    313 static void
    314 pptp_call_ser_print(netdissect_options *ndo,
    315                     const nd_uint16_t call_ser)
    316 {
    317 	ND_PRINT(" CALL_SER_NUM(%u)", GET_BE_U_2(call_ser));
    318 }
    319 
    320 static void
    321 pptp_cause_code_print(netdissect_options *ndo,
    322                       const nd_uint16_t cause_code)
    323 {
    324 	ND_PRINT(" CAUSE_CODE(%u)", GET_BE_U_2(cause_code));
    325 }
    326 
    327 static void
    328 pptp_conn_speed_print(netdissect_options *ndo,
    329                       const nd_uint32_t conn_speed)
    330 {
    331 	ND_PRINT(" CONN_SPEED(%u)", GET_BE_U_4(conn_speed));
    332 }
    333 
    334 static const struct tok pptp_errcode_str[] = {
    335 	{ 0, "None"          },
    336 	{ 1, "Not-Connected" },
    337 	{ 2, "Bad-Format"    },
    338 	{ 3, "Bad-Value"     },
    339 	{ 4, "No-Resource"   },
    340 	{ 5, "Bad-Call-ID"   },
    341 	{ 6, "PAC-Error"     },
    342 	{ 0, NULL }
    343 };
    344 
    345 static void
    346 pptp_err_code_print(netdissect_options *ndo,
    347                     const nd_uint8_t err_code)
    348 {
    349 	ND_PRINT(" ERR_CODE(%u", GET_U_1(err_code));
    350 	if (ndo->ndo_vflag) {
    351 		ND_PRINT(":%s",
    352 			 tok2str(pptp_errcode_str, "?", GET_U_1(err_code)));
    353 	}
    354 	ND_PRINT(")");
    355 }
    356 
    357 static void
    358 pptp_firm_rev_print(netdissect_options *ndo,
    359                     const nd_uint16_t firm_rev)
    360 {
    361 	ND_PRINT(" FIRM_REV(%u)", GET_BE_U_2(firm_rev));
    362 }
    363 
    364 static void
    365 pptp_framing_cap_print(netdissect_options *ndo,
    366                        const nd_uint32_t framing_cap)
    367 {
    368 	ND_PRINT(" FRAME_CAP(");
    369 	if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_ASYNC_MASK) {
    370                 ND_PRINT("A");		/* Async */
    371         }
    372         if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_SYNC_MASK) {
    373                 ND_PRINT("S");		/* Sync */
    374         }
    375 	ND_PRINT(")");
    376 }
    377 
    378 static const struct tok pptp_ftype_str[] = {
    379 	{ 1, "A" }, /* Async */
    380 	{ 2, "S" }, /* Sync */
    381 	{ 3, "E" }, /* Either */
    382 	{ 0, NULL }
    383 };
    384 
    385 static void
    386 pptp_framing_type_print(netdissect_options *ndo,
    387                         const nd_uint32_t framing_type)
    388 {
    389 	ND_PRINT(" FRAME_TYPE(%s)",
    390 	          tok2str(pptp_ftype_str, "?", GET_BE_U_4(framing_type)));
    391 }
    392 
    393 static void
    394 pptp_hostname_print(netdissect_options *ndo,
    395                     const u_char *hostname)
    396 {
    397 	ND_PRINT(" HOSTNAME(");
    398 	nd_printjnp(ndo, hostname, 64);
    399 	ND_PRINT(")");
    400 }
    401 
    402 static void
    403 pptp_id_print(netdissect_options *ndo,
    404               const nd_uint32_t id)
    405 {
    406 	ND_PRINT(" ID(%u)", GET_BE_U_4(id));
    407 }
    408 
    409 static void
    410 pptp_max_channel_print(netdissect_options *ndo,
    411                        const nd_uint16_t max_channel)
    412 {
    413 	ND_PRINT(" MAX_CHAN(%u)", GET_BE_U_2(max_channel));
    414 }
    415 
    416 static void
    417 pptp_peer_call_id_print(netdissect_options *ndo,
    418                         const nd_uint16_t peer_call_id)
    419 {
    420 	ND_PRINT(" PEER_CALL_ID(%u)", GET_BE_U_2(peer_call_id));
    421 }
    422 
    423 static void
    424 pptp_phy_chan_id_print(netdissect_options *ndo,
    425                        const nd_uint32_t phy_chan_id)
    426 {
    427 	ND_PRINT(" PHY_CHAN_ID(%u)", GET_BE_U_4(phy_chan_id));
    428 }
    429 
    430 static void
    431 pptp_pkt_proc_delay_print(netdissect_options *ndo,
    432                           const nd_uint16_t pkt_proc_delay)
    433 {
    434 	ND_PRINT(" PROC_DELAY(%u)", GET_BE_U_2(pkt_proc_delay));
    435 }
    436 
    437 static void
    438 pptp_proto_ver_print(netdissect_options *ndo,
    439                      const nd_uint16_t proto_ver)
    440 {
    441 	ND_PRINT(" PROTO_VER(%u.%u)",	/* Version.Revision */
    442 	       GET_BE_U_2(proto_ver) >> 8,
    443 	       GET_BE_U_2(proto_ver) & 0xff);
    444 }
    445 
    446 static void
    447 pptp_recv_winsiz_print(netdissect_options *ndo,
    448                        const nd_uint16_t recv_winsiz)
    449 {
    450 	ND_PRINT(" RECV_WIN(%u)", GET_BE_U_2(recv_winsiz));
    451 }
    452 
    453 static const struct tok pptp_scrrp_str[] = {
    454 	{ 1, "Successful channel establishment"                           },
    455 	{ 2, "General error"                                              },
    456 	{ 3, "Command channel already exists"                             },
    457 	{ 4, "Requester is not authorized to establish a command channel" },
    458 	{ 5, "The protocol version of the requester is not supported"     },
    459 	{ 0, NULL }
    460 };
    461 
    462 static const struct tok pptp_echorp_str[] = {
    463 	{ 1, "OK" },
    464 	{ 2, "General Error" },
    465 	{ 0, NULL }
    466 };
    467 
    468 static const struct tok pptp_ocrp_str[] = {
    469 	{ 1, "Connected"     },
    470 	{ 2, "General Error" },
    471 	{ 3, "No Carrier"    },
    472 	{ 4, "Busy"          },
    473 	{ 5, "No Dial Tone"  },
    474 	{ 6, "Time-out"      },
    475 	{ 7, "Do Not Accept" },
    476 	{ 0, NULL }
    477 };
    478 
    479 static const struct tok pptp_icrp_str[] = {
    480 	{ 1, "Connect"       },
    481 	{ 2, "General Error" },
    482 	{ 3, "Do Not Accept" },
    483 	{ 0, NULL }
    484 };
    485 
    486 static const struct tok pptp_cdn_str[] = {
    487 	{ 1, "Lost Carrier"   },
    488 	{ 2, "General Error"  },
    489 	{ 3, "Admin Shutdown" },
    490 	{ 4, "Request"        },
    491 	{ 0, NULL }
    492 };
    493 
    494 static void
    495 pptp_result_code_print(netdissect_options *ndo,
    496                        const nd_uint8_t result_code, int ctrl_msg_type)
    497 {
    498 	ND_PRINT(" RESULT_CODE(%u", GET_U_1(result_code));
    499 	if (ndo->ndo_vflag) {
    500 		const struct tok *dict =
    501 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_SCCRP    ? pptp_scrrp_str :
    502 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_StopCCRP ? pptp_echorp_str :
    503 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ECHORP   ? pptp_echorp_str :
    504 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_OCRP     ? pptp_ocrp_str :
    505 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ICRP     ? pptp_icrp_str :
    506 			ctrl_msg_type == PPTP_CTRL_MSG_TYPE_CDN      ? pptp_cdn_str :
    507 			NULL; /* assertion error */
    508 		if (dict != NULL)
    509 			ND_PRINT(":%s",
    510 				 tok2str(dict, "?", GET_U_1(result_code)));
    511 	}
    512 	ND_PRINT(")");
    513 }
    514 
    515 static void
    516 pptp_subaddr_print(netdissect_options *ndo,
    517                    const u_char *subaddr)
    518 {
    519 	ND_PRINT(" SUB_ADDR(");
    520 	nd_printjnp(ndo, subaddr, 64);
    521 	ND_PRINT(")");
    522 }
    523 
    524 static void
    525 pptp_vendor_print(netdissect_options *ndo,
    526                   const u_char *vendor)
    527 {
    528 	ND_PRINT(" VENDOR(");
    529 	nd_printjnp(ndo, vendor, 64);
    530 	ND_PRINT(")");
    531 }
    532 
    533 /************************************/
    534 /* PPTP message print out functions */
    535 /************************************/
    536 static void
    537 pptp_sccrq_print(netdissect_options *ndo,
    538                  const u_char *dat)
    539 {
    540 	const struct pptp_msg_sccrq *ptr = (const struct pptp_msg_sccrq *)dat;
    541 
    542 	pptp_proto_ver_print(ndo, ptr->proto_ver);
    543 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    544 	pptp_framing_cap_print(ndo, ptr->framing_cap);
    545 	pptp_bearer_cap_print(ndo, ptr->bearer_cap);
    546 	pptp_max_channel_print(ndo, ptr->max_channel);
    547 	pptp_firm_rev_print(ndo, ptr->firm_rev);
    548 	pptp_hostname_print(ndo, ptr->hostname);
    549 	pptp_vendor_print(ndo, ptr->vendor);
    550 }
    551 
    552 static void
    553 pptp_sccrp_print(netdissect_options *ndo,
    554                  const u_char *dat)
    555 {
    556 	const struct pptp_msg_sccrp *ptr = (const struct pptp_msg_sccrp *)dat;
    557 
    558 	pptp_proto_ver_print(ndo, ptr->proto_ver);
    559 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_SCCRP);
    560 	pptp_err_code_print(ndo, ptr->err_code);
    561 	pptp_framing_cap_print(ndo, ptr->framing_cap);
    562 	pptp_bearer_cap_print(ndo, ptr->bearer_cap);
    563 	pptp_max_channel_print(ndo, ptr->max_channel);
    564 	pptp_firm_rev_print(ndo, ptr->firm_rev);
    565 	pptp_hostname_print(ndo, ptr->hostname);
    566 	pptp_vendor_print(ndo, ptr->vendor);
    567 }
    568 
    569 static void
    570 pptp_stopccrq_print(netdissect_options *ndo,
    571                     const u_char *dat)
    572 {
    573 	const struct pptp_msg_stopccrq *ptr = (const struct pptp_msg_stopccrq *)dat;
    574 
    575 	ND_PRINT(" REASON(%u", GET_U_1(ptr->reason));
    576 	if (ndo->ndo_vflag) {
    577 		switch (GET_U_1(ptr->reason)) {
    578 		case 1:
    579 			ND_PRINT(":None");
    580 			break;
    581 		case 2:
    582 			ND_PRINT(":Stop-Protocol");
    583 			break;
    584 		case 3:
    585 			ND_PRINT(":Stop-Local-Shutdown");
    586 			break;
    587 		default:
    588 			ND_PRINT(":?");
    589 			break;
    590 		}
    591 	}
    592 	ND_PRINT(")");
    593 	PRINT_RESERVED_IF_NOT_ZERO_1(ptr->reserved1);
    594 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved2);
    595 }
    596 
    597 static void
    598 pptp_stopccrp_print(netdissect_options *ndo,
    599                     const u_char *dat)
    600 {
    601 	const struct pptp_msg_stopccrp *ptr = (const struct pptp_msg_stopccrp *)dat;
    602 
    603 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_StopCCRP);
    604 	pptp_err_code_print(ndo, ptr->err_code);
    605 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    606 }
    607 
    608 static void
    609 pptp_echorq_print(netdissect_options *ndo,
    610                   const u_char *dat)
    611 {
    612 	const struct pptp_msg_echorq *ptr = (const struct pptp_msg_echorq *)dat;
    613 
    614 	pptp_id_print(ndo, ptr->id);
    615 }
    616 
    617 static void
    618 pptp_echorp_print(netdissect_options *ndo,
    619                   const u_char *dat)
    620 {
    621 	const struct pptp_msg_echorp *ptr = (const struct pptp_msg_echorp *)dat;
    622 
    623 	pptp_id_print(ndo, ptr->id);
    624 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ECHORP);
    625 	pptp_err_code_print(ndo, ptr->err_code);
    626 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    627 }
    628 
    629 static void
    630 pptp_ocrq_print(netdissect_options *ndo,
    631                 const u_char *dat)
    632 {
    633 	const struct pptp_msg_ocrq *ptr = (const struct pptp_msg_ocrq *)dat;
    634 
    635 	pptp_call_id_print(ndo, ptr->call_id);
    636 	pptp_call_ser_print(ndo, ptr->call_ser);
    637 	ND_PRINT(" MIN_BPS(%u)", GET_BE_U_4(ptr->min_bps));
    638 	ND_PRINT(" MAX_BPS(%u)", GET_BE_U_4(ptr->max_bps));
    639 	pptp_bearer_type_print(ndo, ptr->bearer_type);
    640 	pptp_framing_type_print(ndo, ptr->framing_type);
    641 	pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
    642 	pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
    643 	ND_PRINT(" PHONE_NO_LEN(%u)", GET_BE_U_2(ptr->phone_no_len));
    644 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    645 	ND_PRINT(" PHONE_NO(");
    646 	nd_printjnp(ndo, ptr->phone_no,
    647 		    ND_MIN(64, GET_BE_U_2(ptr->phone_no_len)));
    648 	ND_PRINT(")");
    649 	pptp_subaddr_print(ndo, ptr->subaddr);
    650 }
    651 
    652 static void
    653 pptp_ocrp_print(netdissect_options *ndo,
    654                 const u_char *dat)
    655 {
    656 	const struct pptp_msg_ocrp *ptr = (const struct pptp_msg_ocrp *)dat;
    657 
    658 	pptp_call_id_print(ndo, ptr->call_id);
    659 	pptp_peer_call_id_print(ndo, ptr->peer_call_id);
    660 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_OCRP);
    661 	pptp_err_code_print(ndo, ptr->err_code);
    662 	pptp_cause_code_print(ndo, ptr->cause_code);
    663 	pptp_conn_speed_print(ndo, ptr->conn_speed);
    664 	pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
    665 	pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
    666 	pptp_phy_chan_id_print(ndo, ptr->phy_chan_id);
    667 }
    668 
    669 static void
    670 pptp_icrq_print(netdissect_options *ndo,
    671                 const u_char *dat)
    672 {
    673 	const struct pptp_msg_icrq *ptr = (const struct pptp_msg_icrq *)dat;
    674 
    675 	pptp_call_id_print(ndo, ptr->call_id);
    676 	pptp_call_ser_print(ndo, ptr->call_ser);
    677 	pptp_bearer_type_print(ndo, ptr->bearer_type);
    678 	pptp_phy_chan_id_print(ndo, ptr->phy_chan_id);
    679 	ND_PRINT(" DIALED_NO_LEN(%u)", GET_BE_U_2(ptr->dialed_no_len));
    680 	ND_PRINT(" DIALING_NO_LEN(%u)", GET_BE_U_2(ptr->dialing_no_len));
    681 	ND_PRINT(" DIALED_NO(");
    682 	nd_printjnp(ndo, ptr->dialed_no,
    683 		    ND_MIN(64, GET_BE_U_2(ptr->dialed_no_len)));
    684 	ND_PRINT(")");
    685 	ND_PRINT(" DIALING_NO(");
    686 	nd_printjnp(ndo, ptr->dialing_no,
    687 		    ND_MIN(64, GET_BE_U_2(ptr->dialing_no_len)));
    688 	ND_PRINT(")");
    689 	pptp_subaddr_print(ndo, ptr->subaddr);
    690 }
    691 
    692 static void
    693 pptp_icrp_print(netdissect_options *ndo,
    694                 const u_char *dat)
    695 {
    696 	const struct pptp_msg_icrp *ptr = (const struct pptp_msg_icrp *)dat;
    697 
    698 	pptp_call_id_print(ndo, ptr->call_id);
    699 	pptp_peer_call_id_print(ndo, ptr->peer_call_id);
    700 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ICRP);
    701 	pptp_err_code_print(ndo, ptr->err_code);
    702 	pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
    703 	pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
    704 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    705 }
    706 
    707 static void
    708 pptp_iccn_print(netdissect_options *ndo,
    709                 const u_char *dat)
    710 {
    711 	const struct pptp_msg_iccn *ptr = (const struct pptp_msg_iccn *)dat;
    712 
    713 	pptp_peer_call_id_print(ndo, ptr->peer_call_id);
    714 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    715 	pptp_conn_speed_print(ndo, ptr->conn_speed);
    716 	pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
    717 	pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
    718 	pptp_framing_type_print(ndo, ptr->framing_type);
    719 }
    720 
    721 static void
    722 pptp_ccrq_print(netdissect_options *ndo,
    723                 const u_char *dat)
    724 {
    725 	const struct pptp_msg_ccrq *ptr = (const struct pptp_msg_ccrq *)dat;
    726 
    727 	pptp_call_id_print(ndo, ptr->call_id);
    728 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    729 }
    730 
    731 static void
    732 pptp_cdn_print(netdissect_options *ndo,
    733                const u_char *dat)
    734 {
    735 	const struct pptp_msg_cdn *ptr = (const struct pptp_msg_cdn *)dat;
    736 
    737 	pptp_call_id_print(ndo, ptr->call_id);
    738 	pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_CDN);
    739 	pptp_err_code_print(ndo, ptr->err_code);
    740 	pptp_cause_code_print(ndo, ptr->cause_code);
    741 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    742 	ND_PRINT(" CALL_STATS(");
    743 	nd_printjnp(ndo, ptr->call_stats, 128);
    744 	ND_PRINT(")");
    745 }
    746 
    747 static void
    748 pptp_wen_print(netdissect_options *ndo,
    749                const u_char *dat)
    750 {
    751 	const struct pptp_msg_wen *ptr = (const struct pptp_msg_wen *)dat;
    752 
    753 	pptp_peer_call_id_print(ndo, ptr->peer_call_id);
    754 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    755 	ND_PRINT(" CRC_ERR(%u)", GET_BE_U_4(ptr->crc_err));
    756 	ND_PRINT(" FRAMING_ERR(%u)", GET_BE_U_4(ptr->framing_err));
    757 	ND_PRINT(" HARDWARE_OVERRUN(%u)", GET_BE_U_4(ptr->hardware_overrun));
    758 	ND_PRINT(" BUFFER_OVERRUN(%u)", GET_BE_U_4(ptr->buffer_overrun));
    759 	ND_PRINT(" TIMEOUT_ERR(%u)", GET_BE_U_4(ptr->timeout_err));
    760 	ND_PRINT(" ALIGN_ERR(%u)", GET_BE_U_4(ptr->align_err));
    761 }
    762 
    763 static void
    764 pptp_sli_print(netdissect_options *ndo,
    765                const u_char *dat)
    766 {
    767 	const struct pptp_msg_sli *ptr = (const struct pptp_msg_sli *)dat;
    768 
    769 	pptp_peer_call_id_print(ndo, ptr->peer_call_id);
    770 	PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
    771 	ND_PRINT(" SEND_ACCM(0x%08x)", GET_BE_U_4(ptr->send_accm));
    772 	ND_PRINT(" RECV_ACCM(0x%08x)", GET_BE_U_4(ptr->recv_accm));
    773 }
    774 
    775 void
    776 pptp_print(netdissect_options *ndo,
    777            const u_char *dat)
    778 {
    779 	const struct pptp_hdr *hdr;
    780 	uint32_t mc;
    781 	uint16_t ctrl_msg_type;
    782 
    783 	ndo->ndo_protocol = "pptp";
    784 	ND_PRINT(": ");
    785 	nd_print_protocol(ndo);
    786 
    787 	hdr = (const struct pptp_hdr *)dat;
    788 
    789 	if (ndo->ndo_vflag) {
    790 		ND_PRINT(" Length=%u", GET_BE_U_2(hdr->length));
    791 	}
    792 	if (ndo->ndo_vflag) {
    793 		switch(GET_BE_U_2(hdr->msg_type)) {
    794 		case PPTP_MSG_TYPE_CTRL:
    795 			ND_PRINT(" CTRL-MSG");
    796 			break;
    797 		case PPTP_MSG_TYPE_MGMT:
    798 			ND_PRINT(" MGMT-MSG");
    799 			break;
    800 		default:
    801 			ND_PRINT(" UNKNOWN-MSG-TYPE");
    802 			break;
    803 		}
    804 	}
    805 
    806 	mc = GET_BE_U_4(hdr->magic_cookie);
    807 	if (mc != PPTP_MAGIC_COOKIE) {
    808 		ND_PRINT(" UNEXPECTED Magic-Cookie!!(%08x)", mc);
    809 	}
    810 	if (ndo->ndo_vflag || mc != PPTP_MAGIC_COOKIE) {
    811 		ND_PRINT(" Magic-Cookie=%08x", mc);
    812 	}
    813 	ctrl_msg_type = GET_BE_U_2(hdr->ctrl_msg_type);
    814 	if (ctrl_msg_type < PPTP_MAX_MSGTYPE_INDEX) {
    815 		ND_PRINT(" CTRL_MSGTYPE=%s",
    816 		       pptp_message_type_string[ctrl_msg_type]);
    817 	} else {
    818 		ND_PRINT(" UNKNOWN_CTRL_MSGTYPE(%u)", ctrl_msg_type);
    819 	}
    820 	PRINT_RESERVED_IF_NOT_ZERO_2(hdr->reserved0);
    821 
    822 	dat += 12;
    823 
    824 	switch(ctrl_msg_type) {
    825 	case PPTP_CTRL_MSG_TYPE_SCCRQ:
    826 		pptp_sccrq_print(ndo, dat);
    827 		break;
    828 	case PPTP_CTRL_MSG_TYPE_SCCRP:
    829 		pptp_sccrp_print(ndo, dat);
    830 		break;
    831 	case PPTP_CTRL_MSG_TYPE_StopCCRQ:
    832 		pptp_stopccrq_print(ndo, dat);
    833 		break;
    834 	case PPTP_CTRL_MSG_TYPE_StopCCRP:
    835 		pptp_stopccrp_print(ndo, dat);
    836 		break;
    837 	case PPTP_CTRL_MSG_TYPE_ECHORQ:
    838 		pptp_echorq_print(ndo, dat);
    839 		break;
    840 	case PPTP_CTRL_MSG_TYPE_ECHORP:
    841 		pptp_echorp_print(ndo, dat);
    842 		break;
    843 	case PPTP_CTRL_MSG_TYPE_OCRQ:
    844 		pptp_ocrq_print(ndo, dat);
    845 		break;
    846 	case PPTP_CTRL_MSG_TYPE_OCRP:
    847 		pptp_ocrp_print(ndo, dat);
    848 		break;
    849 	case PPTP_CTRL_MSG_TYPE_ICRQ:
    850 		pptp_icrq_print(ndo, dat);
    851 		break;
    852 	case PPTP_CTRL_MSG_TYPE_ICRP:
    853 		pptp_icrp_print(ndo, dat);
    854 		break;
    855 	case PPTP_CTRL_MSG_TYPE_ICCN:
    856 		pptp_iccn_print(ndo, dat);
    857 		break;
    858 	case PPTP_CTRL_MSG_TYPE_CCRQ:
    859 		pptp_ccrq_print(ndo, dat);
    860 		break;
    861 	case PPTP_CTRL_MSG_TYPE_CDN:
    862 		pptp_cdn_print(ndo, dat);
    863 		break;
    864 	case PPTP_CTRL_MSG_TYPE_WEN:
    865 		pptp_wen_print(ndo, dat);
    866 		break;
    867 	case PPTP_CTRL_MSG_TYPE_SLI:
    868 		pptp_sli_print(ndo, dat);
    869 		break;
    870 	default:
    871 		/* do nothing */
    872 		break;
    873 	}
    874 }
    875