Remove all $Id$ from top of file
[metze/wireshark/wip.git] / epan / dissectors / packet-pptp.c
1 /* packet-pptp.c
2  * Routines for the Point-to-Point Tunnelling Protocol (PPTP) (RFC 2637)
3  * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
4  *
5  * 10/2010 - Rework PPTP Dissector
6  * Alexis La Goutte <alexis.lagoutte at gmail dot com>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #include "config.h"
28
29 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/expert.h>
32
33 void proto_register_pptp(void);
34 void proto_reg_handoff_pptp(void);
35
36 static int proto_pptp = -1;
37 static int hf_pptp_length = -1;
38 static int hf_pptp_message_type = -1;
39 static int hf_pptp_magic_cookie = -1;
40 static int hf_pptp_control_message_type = -1;
41 static int hf_pptp_reserved = -1;
42 static int hf_pptp_protocol_version = -1;
43 static int hf_pptp_framing_capabilities = -1;
44 static int hf_pptp_bearer_capabilities = -1;
45 static int hf_pptp_maximum_channels = -1;
46 static int hf_pptp_firmware_revision = -1;
47 static int hf_pptp_host_name = -1;
48 static int hf_pptp_vendor_name = -1;
49 static int hf_pptp_control_result = -1;
50 static int hf_pptp_error = -1;
51 static int hf_pptp_reason = -1;
52 static int hf_pptp_stop_result = -1;
53 static int hf_pptp_identifier = -1;
54 static int hf_pptp_echo_result = -1;
55 static int hf_pptp_call_id = -1;
56 static int hf_pptp_call_serial_number = -1;
57 static int hf_pptp_minimum_bps = -1;
58 static int hf_pptp_maximum_bps = -1;
59 static int hf_pptp_bearer_type = -1;
60 static int hf_pptp_framing_type = -1;
61 static int hf_pptp_packet_receive_window_size = -1;
62 static int hf_pptp_packet_processing_delay = -1;
63 static int hf_pptp_phone_number_length = -1;
64 static int hf_pptp_phone_number = -1;
65 static int hf_pptp_subaddress = -1;
66 static int hf_pptp_peer_call_id = -1;
67 static int hf_pptp_out_result = -1;
68 static int hf_pptp_cause = -1;
69 static int hf_pptp_connect_speed = -1;
70 static int hf_pptp_physical_channel_id = -1;
71 static int hf_pptp_dialed_number_length = -1;
72 static int hf_pptp_dialed_number = -1;
73 static int hf_pptp_dialing_number_length = -1;
74 static int hf_pptp_dialing_number = -1;
75 static int hf_pptp_in_result = -1;
76 static int hf_pptp_disc_result = -1;
77 static int hf_pptp_call_statistics = -1;
78 static int hf_pptp_crc_errors = -1;
79 static int hf_pptp_framing_errors = -1;
80 static int hf_pptp_hardware_overruns = -1;
81 static int hf_pptp_buffer_overruns = -1;
82 static int hf_pptp_timeout_errors = -1;
83 static int hf_pptp_alignment_errors = -1;
84 static int hf_pptp_send_accm = -1;
85 static int hf_pptp_receive_accm = -1;
86
87 static gint ett_pptp = -1;
88
89 static expert_field ei_pptp_incorrect_magic_cookie = EI_INIT;
90
91 static dissector_handle_t data_handle;
92
93 #define TCP_PORT_PPTP           1723
94
95 #define MAGIC_COOKIE            0x1A2B3C4D
96
97 #define CNTRL_REQ       0x01
98 #define CNTRL_REPLY     0x02
99 #define STOP_REQ        0x03
100 #define STOP_REPLY      0x04
101 #define ECHO_REQ        0x05
102 #define ECHO_REPLY      0x06
103 #define OUT_REQ         0x07
104 #define OUT_REPLY       0x08
105 #define IN_REQ          0x09
106 #define IN_REPLY        0x0A
107 #define IN_CONNECTED    0x0B
108 #define CLEAR_REQ       0x0C
109 #define DISC_NOTIFY     0x0D
110 #define ERROR_NOTIFY    0x0E
111 #define SET_LINK        0x0F
112
113 static const value_string control_message_type_vals[] = {
114   { CNTRL_REQ,    "Start-Control-Connection-Request" },
115   { CNTRL_REPLY,  "Start-Control-Connection-Reply" },
116   { STOP_REQ,     "Stop-Control-Connection-Request" },
117   { STOP_REPLY,   "Stop-Control-Connection-Reply" },
118   { ECHO_REQ,     "Echo-Request" },
119   { ECHO_REPLY,   "Echo-Reply" },
120   { OUT_REQ,      "Outgoing-Call-Request" },
121   { OUT_REPLY,    "Outgoing-Call-Reply" },
122   { IN_REQ,       "Incoming-Call-Request" },
123   { IN_REPLY,     "Incoming-Call-Reply" },
124   { IN_CONNECTED, "Incoming-Call-Connected" },
125   { CLEAR_REQ,    "Call-Clear-Request" },
126   { DISC_NOTIFY,  "Call-Disconnect-Notify" },
127   { ERROR_NOTIFY, "WAN-Error-Notify" },
128   { SET_LINK,     "Set-Link-Info" },
129   { 0,  NULL },
130 };
131 static const value_string msgtype_vals[] = {
132   { 1, "Control Message" },
133   { 2, "Management Message" },
134   { 0, NULL }
135 };
136
137 static const value_string frametype_vals[] = {
138   { 1, "Asynchronous Framing supported" },
139   { 2, "Synchronous Framing supported"},
140   { 3, "Either Framing supported" },
141   { 0, NULL }
142 };
143
144 static const value_string bearertype_vals[] = {
145   { 1, "Analog access supported" },
146   { 2, "Digital access supported" },
147   { 3, "Either access supported" },
148   { 0, NULL }
149 };
150
151 static const value_string control_resulttype_vals[] = {
152   { 1, "Successful channel establishment" },
153   { 2, "General error" },
154   { 3, "Command channel already exists" },
155   { 4, "Requester not authorized" },
156   { 5, "Protocol version not supported" },
157   { 0, NULL }
158 };
159
160 static const value_string errortype_vals[] = {
161   { 0, "None" },
162   { 1, "Not-Connected" },
163   { 2, "Bad-Format" },
164   { 3, "Bad-Value" },
165   { 4, "No-Resource" },
166   { 5, "Bad-Call ID" },
167   { 6, "PAC-Error" },
168   { 0, NULL }
169 };
170
171 static const value_string reasontype_vals[] = {
172   { 1, "None" },
173   { 2, "Stop-Protocol" },
174   { 3, "Stop-Local-Shutdown" },
175   { 0, NULL }
176 };
177
178 static const value_string stop_resulttype_vals[] = {
179   { 1, "OK" },
180   { 2, "General error" },
181   { 0, NULL }
182 };
183
184 static const value_string echo_resulttype_vals[] = {
185   { 1, "OK" },
186   { 2, "General error" },
187   { 0, NULL }
188 };
189
190 static const value_string out_resulttype_vals[] = {
191   { 1, "Connected" },
192   { 2, "General Error" },
193   { 3, "No Carrier" },
194   { 4, "Busy" },
195   { 5, "No Dial Tone" },
196   { 6, "Time-out" },
197   { 7, "Do Not Accept" },
198   { 0, NULL }
199 };
200
201 static const value_string in_resulttype_vals[] = {
202   { 1, "Connect" },
203   { 2, "General error" },
204   { 3, "Do Not Accept" },
205   { 0, NULL }
206 };
207
208 static const value_string disc_resulttype_vals[] = {
209   { 1, "Lost Carrier" },
210   { 2, "General Error" },
211   { 3, "Admin Shutdown" },
212   { 4, "Request" },
213   { 0, NULL }
214 };
215
216 static void
217 dissect_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
218 {
219   call_dissector(data_handle,tvb_new_subset_remaining(tvb, offset), pinfo, tree);
220 }
221
222 static void
223 dissect_cntrl_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
224 {
225   if (!tree)
226     return;
227
228   proto_tree_add_uint_format_value(tree, hf_pptp_protocol_version, tvb, offset,
229                                2, tvb_get_ntohs(tvb, offset), "%u.%u",
230                                tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
231   offset += 2;
232
233   proto_tree_add_item(tree, hf_pptp_reserved,             tvb, offset, 2, ENC_NA);
234   offset += 2;
235
236   proto_tree_add_item(tree, hf_pptp_framing_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
237   offset += 4;
238
239   proto_tree_add_item(tree, hf_pptp_bearer_capabilities,  tvb, offset, 4, ENC_BIG_ENDIAN);
240   offset += 4;
241
242   proto_tree_add_item(tree, hf_pptp_maximum_channels,     tvb, offset, 2, ENC_BIG_ENDIAN);
243   offset += 2;
244
245   proto_tree_add_item(tree, hf_pptp_firmware_revision,    tvb, offset, 2, ENC_BIG_ENDIAN);
246   offset += 2;
247
248   proto_tree_add_item(tree, hf_pptp_host_name,            tvb, offset, 64, ENC_ASCII|ENC_NA);
249   offset += 64;
250
251   proto_tree_add_item(tree, hf_pptp_vendor_name,          tvb, offset, 64, ENC_ASCII|ENC_NA);
252 }
253
254 static void
255 dissect_cntrl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
256 {
257   if (!tree)
258     return;
259
260   proto_tree_add_uint_format_value(tree, hf_pptp_protocol_version, tvb, offset,
261                                2, tvb_get_ntohs(tvb, offset), "%u.%u",
262                                tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
263   offset += 2;
264
265   proto_tree_add_item(tree, hf_pptp_control_result,       tvb, offset, 1, ENC_BIG_ENDIAN);
266   offset += 1;
267
268   proto_tree_add_item(tree, hf_pptp_error,                tvb, offset, 1, ENC_BIG_ENDIAN);
269   offset += 1;
270
271   proto_tree_add_item(tree, hf_pptp_framing_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
272   offset += 4;
273
274   proto_tree_add_item(tree, hf_pptp_bearer_capabilities,  tvb, offset, 4, ENC_BIG_ENDIAN);
275   offset += 4;
276
277   proto_tree_add_item(tree, hf_pptp_maximum_channels,     tvb, offset, 2, ENC_BIG_ENDIAN);
278   offset += 2;
279
280   proto_tree_add_item(tree, hf_pptp_firmware_revision,    tvb, offset, 2, ENC_BIG_ENDIAN);
281   offset += 2;
282
283   proto_tree_add_item(tree, hf_pptp_host_name,            tvb, offset, 64, ENC_ASCII|ENC_NA);
284   offset += 64;
285
286   proto_tree_add_item(tree, hf_pptp_vendor_name,          tvb, offset, 64, ENC_ASCII|ENC_NA);
287
288 }
289
290 static void
291 dissect_stop_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
292 {
293   if (!tree)
294     return;
295
296   proto_tree_add_item(tree, hf_pptp_reason,   tvb, offset, 1, ENC_BIG_ENDIAN);
297   offset += 1;
298
299   proto_tree_add_item(tree, hf_pptp_reserved, tvb, offset, 1, ENC_NA);
300   offset += 1;
301
302   proto_tree_add_item(tree, hf_pptp_reserved, tvb, offset, 2, ENC_NA);
303 }
304
305 static void
306 dissect_stop_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
307 {
308   if (!tree)
309     return;
310
311   proto_tree_add_item(tree, hf_pptp_stop_result, tvb, offset, 1, ENC_BIG_ENDIAN);
312   offset += 1;
313
314   proto_tree_add_item(tree, hf_pptp_error,       tvb, offset, 1, ENC_BIG_ENDIAN);
315   offset += 1;
316
317   proto_tree_add_item(tree, hf_pptp_reserved,    tvb, offset, 2, ENC_NA);
318
319 }
320
321 static void
322 dissect_echo_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
323 {
324   if (!tree)
325     return;
326
327   proto_tree_add_item(tree, hf_pptp_identifier, tvb, offset, 4, ENC_BIG_ENDIAN);
328 }
329
330 static void
331 dissect_echo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
332 {
333   if (!tree)
334     return;
335
336   proto_tree_add_item(tree, hf_pptp_identifier,  tvb, offset, 4, ENC_BIG_ENDIAN);
337   offset += 4;
338
339   proto_tree_add_item(tree, hf_pptp_echo_result, tvb, offset, 1, ENC_BIG_ENDIAN);
340   offset += 1;
341
342   proto_tree_add_item(tree, hf_pptp_error,       tvb, offset, 1, ENC_BIG_ENDIAN);
343   offset += 1;
344
345   proto_tree_add_item(tree, hf_pptp_reserved,    tvb, offset, 2, ENC_NA);
346 }
347
348 static void
349 dissect_out_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,      proto_tree *tree)
350 {
351   if (!tree)
352     return;
353
354   proto_tree_add_item(tree, hf_pptp_call_id,                    tvb, offset, 2, ENC_BIG_ENDIAN);
355   offset += 2;
356
357   proto_tree_add_item(tree, hf_pptp_call_serial_number,         tvb, offset, 2, ENC_BIG_ENDIAN);
358   offset += 2;
359
360   proto_tree_add_item(tree, hf_pptp_minimum_bps,                tvb, offset, 4, ENC_BIG_ENDIAN);
361   offset += 4;
362
363   proto_tree_add_item(tree, hf_pptp_maximum_bps,                tvb, offset, 4, ENC_BIG_ENDIAN);
364   offset += 4;
365
366   proto_tree_add_item(tree, hf_pptp_bearer_type,                tvb, offset, 4, ENC_BIG_ENDIAN);
367   offset += 4;
368
369   proto_tree_add_item(tree, hf_pptp_framing_type,               tvb, offset, 4, ENC_BIG_ENDIAN);
370   offset += 4;
371
372   proto_tree_add_item(tree, hf_pptp_packet_receive_window_size, tvb, offset, 2, ENC_BIG_ENDIAN);
373   offset += 2;
374
375   proto_tree_add_item(tree, hf_pptp_packet_processing_delay,    tvb, offset, 2, ENC_BIG_ENDIAN);
376   offset += 2;
377
378   proto_tree_add_item(tree, hf_pptp_phone_number_length,        tvb, offset, 2, ENC_BIG_ENDIAN);
379   offset += 2;
380
381   proto_tree_add_item(tree, hf_pptp_reserved,                   tvb, offset, 2, ENC_NA);
382   offset += 2;
383
384   proto_tree_add_item(tree, hf_pptp_phone_number,               tvb, offset, 64, ENC_ASCII|ENC_NA);
385   offset += 64;
386
387   proto_tree_add_item(tree, hf_pptp_subaddress,                 tvb, offset, 64, ENC_ASCII|ENC_NA);
388 }
389
390 static void
391 dissect_out_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
392 {
393   if (!tree)
394     return;
395
396   proto_tree_add_item(tree, hf_pptp_call_id,                    tvb, offset, 2, ENC_BIG_ENDIAN);
397   offset += 2;
398
399   proto_tree_add_item(tree, hf_pptp_peer_call_id,               tvb, offset, 2, ENC_BIG_ENDIAN);
400   offset += 2;
401
402   proto_tree_add_item(tree, hf_pptp_out_result,                 tvb, offset, 1, ENC_BIG_ENDIAN);
403   offset += 1;
404
405   proto_tree_add_item(tree, hf_pptp_error,                      tvb, offset, 1, ENC_BIG_ENDIAN);
406   offset += 1;
407
408   proto_tree_add_item(tree, hf_pptp_cause,                      tvb, offset, 2, ENC_BIG_ENDIAN);
409   offset += 2;
410
411   proto_tree_add_item(tree, hf_pptp_connect_speed,              tvb, offset, 4, ENC_BIG_ENDIAN);
412   offset += 4;
413
414   proto_tree_add_item(tree, hf_pptp_packet_receive_window_size, tvb, offset, 2, ENC_BIG_ENDIAN);
415   offset += 2;
416
417   proto_tree_add_item(tree, hf_pptp_packet_processing_delay,    tvb, offset, 2, ENC_BIG_ENDIAN);
418   offset += 2;
419
420   proto_tree_add_item(tree, hf_pptp_physical_channel_id,        tvb, offset, 4, ENC_BIG_ENDIAN);
421 }
422
423 static void
424 dissect_in_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
425 {
426   if (!tree)
427     return;
428
429   proto_tree_add_item(tree, hf_pptp_call_id,               tvb, offset, 2, ENC_BIG_ENDIAN);
430   offset += 2;
431
432   proto_tree_add_item(tree, hf_pptp_call_serial_number,    tvb, offset, 2, ENC_BIG_ENDIAN);
433   offset += 2;
434
435   proto_tree_add_item(tree, hf_pptp_bearer_type,           tvb, offset, 4, ENC_BIG_ENDIAN);
436   offset += 4;
437
438   proto_tree_add_item(tree, hf_pptp_physical_channel_id,   tvb, offset, 4, ENC_BIG_ENDIAN);
439   offset += 4;
440
441   proto_tree_add_item(tree, hf_pptp_dialed_number_length,  tvb, offset, 2, ENC_BIG_ENDIAN);
442   offset += 2;
443
444   proto_tree_add_item(tree, hf_pptp_dialing_number_length, tvb, offset, 2, ENC_BIG_ENDIAN);
445   offset += 2;
446
447   proto_tree_add_item(tree, hf_pptp_dialed_number,         tvb, offset, 64, ENC_ASCII|ENC_NA);
448   offset += 64;
449
450   proto_tree_add_item(tree, hf_pptp_dialing_number,        tvb, offset, 64, ENC_ASCII|ENC_NA);
451   offset += 64;
452
453   proto_tree_add_item(tree, hf_pptp_subaddress,            tvb, offset, 64, ENC_ASCII|ENC_NA);
454 }
455
456 static void
457 dissect_in_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
458 {
459   if (!tree)
460     return;
461
462   proto_tree_add_item(tree, hf_pptp_call_id,                    tvb, offset, 2, ENC_BIG_ENDIAN);
463   offset += 2;
464
465   proto_tree_add_item(tree, hf_pptp_peer_call_id,               tvb, offset, 2, ENC_BIG_ENDIAN);
466   offset += 2;
467
468   proto_tree_add_item(tree, hf_pptp_in_result,                  tvb, offset, 1, ENC_BIG_ENDIAN);
469   offset += 1;
470
471   proto_tree_add_item(tree, hf_pptp_error,                      tvb, offset, 1, ENC_BIG_ENDIAN);
472   offset += 1;
473
474   proto_tree_add_item(tree, hf_pptp_packet_receive_window_size, tvb, offset, 2, ENC_BIG_ENDIAN);
475   offset += 2;
476
477   proto_tree_add_item(tree, hf_pptp_packet_processing_delay,    tvb, offset, 2, ENC_BIG_ENDIAN);
478   offset += 2;
479
480   proto_tree_add_item(tree, hf_pptp_reserved,                   tvb, offset, 2, ENC_NA);
481 }
482
483 static void
484 dissect_in_connected(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
485 {
486   if (!tree)
487     return;
488
489   proto_tree_add_item(tree, hf_pptp_peer_call_id,               tvb, offset, 2, ENC_BIG_ENDIAN);
490   offset += 2;
491
492   proto_tree_add_item(tree, hf_pptp_reserved,                   tvb, offset, 2, ENC_NA);
493   offset += 2;
494
495   proto_tree_add_item(tree, hf_pptp_connect_speed,              tvb, offset, 4, ENC_BIG_ENDIAN);
496   offset += 4;
497
498   proto_tree_add_item(tree, hf_pptp_packet_receive_window_size, tvb, offset, 2, ENC_BIG_ENDIAN);
499   offset += 2;
500
501   proto_tree_add_item(tree, hf_pptp_packet_processing_delay,    tvb, offset, 2, ENC_BIG_ENDIAN);
502   offset += 2;
503
504   proto_tree_add_item(tree, hf_pptp_framing_type,               tvb, offset, 4, ENC_BIG_ENDIAN);
505 }
506
507 static void
508 dissect_clear_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
509 {
510   if (!tree)
511     return;
512
513   proto_tree_add_item(tree, hf_pptp_call_id,  tvb, offset, 2, ENC_BIG_ENDIAN);
514   offset += 2;
515
516   proto_tree_add_item(tree, hf_pptp_reserved, tvb, offset, 2, ENC_NA);
517 }
518
519 static void
520 dissect_disc_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
521 {
522   if (!tree)
523     return;
524
525   proto_tree_add_item(tree, hf_pptp_call_id,         tvb, offset, 2, ENC_BIG_ENDIAN);
526   offset += 2;
527
528   proto_tree_add_item(tree, hf_pptp_disc_result,     tvb, offset, 1, ENC_BIG_ENDIAN);
529   offset += 1;
530
531   proto_tree_add_item(tree, hf_pptp_error,           tvb, offset, 1, ENC_BIG_ENDIAN);
532   offset += 1;
533
534   proto_tree_add_item(tree, hf_pptp_cause,           tvb, offset, 2, ENC_BIG_ENDIAN);
535   offset += 2;
536
537   proto_tree_add_item(tree, hf_pptp_reserved,        tvb, offset, 2, ENC_NA);
538   offset += 2;
539
540   proto_tree_add_item(tree, hf_pptp_call_statistics, tvb, offset, 64, ENC_ASCII|ENC_NA);
541 }
542
543 static void
544 dissect_error_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
545 {
546   if (!tree)
547     return;
548
549   proto_tree_add_item(tree, hf_pptp_peer_call_id,      tvb, offset, 2, ENC_BIG_ENDIAN);
550   offset += 2;
551
552   proto_tree_add_item(tree, hf_pptp_reserved,          tvb, offset, 2, ENC_NA);
553   offset += 2;
554
555   proto_tree_add_item(tree, hf_pptp_crc_errors,        tvb, offset, 4, ENC_BIG_ENDIAN);
556   offset += 4;
557
558   proto_tree_add_item(tree, hf_pptp_framing_errors,    tvb, offset, 4, ENC_BIG_ENDIAN);
559   offset += 4;
560
561   proto_tree_add_item(tree, hf_pptp_hardware_overruns, tvb, offset, 4, ENC_BIG_ENDIAN);
562   offset += 4;
563
564   proto_tree_add_item(tree, hf_pptp_buffer_overruns,   tvb, offset, 4, ENC_BIG_ENDIAN);
565   offset += 4;
566
567   proto_tree_add_item(tree, hf_pptp_timeout_errors,    tvb, offset, 4, ENC_BIG_ENDIAN);
568   offset += 4;
569
570   proto_tree_add_item(tree, hf_pptp_alignment_errors,  tvb, offset, 4, ENC_BIG_ENDIAN);
571 }
572
573 static void
574 dissect_set_link(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
575 {
576   if (!tree)
577       return;
578
579   proto_tree_add_item(tree, hf_pptp_peer_call_id, tvb, offset, 2, ENC_BIG_ENDIAN);
580   offset += 2;
581
582   proto_tree_add_item(tree, hf_pptp_reserved,     tvb, offset, 2, ENC_NA);
583   offset += 2;
584
585   proto_tree_add_item(tree, hf_pptp_send_accm,    tvb, offset, 4, ENC_BIG_ENDIAN);
586   offset += 4;
587
588   proto_tree_add_item(tree, hf_pptp_receive_accm, tvb, offset, 4, ENC_BIG_ENDIAN);
589 }
590
591 static void
592 dissect_pptp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
593 {
594   proto_tree *pptp_tree = NULL;
595   proto_item *item      = NULL;
596   int         offset    = 0;
597   guint16     len;
598   guint16     control_message_type;
599
600   col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPTP");
601   col_clear(pinfo->cinfo, COL_INFO);
602
603   len        = tvb_get_ntohs(tvb, offset);
604   control_message_type = tvb_get_ntohs(tvb, offset + 8);
605
606   col_add_str(pinfo->cinfo, COL_INFO,
607               val_to_str(control_message_type, control_message_type_vals,
608                          "Unknown control type (%d)"));
609
610   if (tree) {
611     proto_item *ti;
612
613     ti = proto_tree_add_item(tree, proto_pptp, tvb, offset, len, ENC_NA);
614     pptp_tree = proto_item_add_subtree(ti, ett_pptp);
615
616     proto_tree_add_item(pptp_tree, hf_pptp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
617
618     proto_tree_add_item(pptp_tree, hf_pptp_message_type, tvb, offset+2, 2, ENC_BIG_ENDIAN);
619
620     item = proto_tree_add_item(pptp_tree, hf_pptp_magic_cookie, tvb, offset+4, 4, ENC_BIG_ENDIAN);
621   }
622
623   if (tvb_get_ntohl(tvb, offset+4) == MAGIC_COOKIE)
624     proto_item_append_text(item," (correct)");
625   else {
626     proto_item_append_text(item," (incorrect)");
627     expert_add_info(pinfo, item, &ei_pptp_incorrect_magic_cookie);
628   }
629
630   if (tree) {
631     proto_tree_add_item(pptp_tree, hf_pptp_control_message_type, tvb, offset+8, 2, ENC_BIG_ENDIAN);
632
633     proto_tree_add_item(pptp_tree, hf_pptp_reserved, tvb, offset+10, 2, ENC_NA);
634   }
635
636   offset += offset + 12;
637
638   switch(control_message_type){
639     case CNTRL_REQ: /* Start-Control-Connection-Request */
640       dissect_cntrl_req(tvb, offset, pinfo, pptp_tree);
641       break;
642     case CNTRL_REPLY: /* Start-Control-Connection-Reply */
643       dissect_cntrl_reply(tvb, offset, pinfo, pptp_tree);
644       break;
645     case STOP_REQ: /* Stop-Control-Connection-Request */
646       dissect_stop_req(tvb, offset, pinfo, pptp_tree);
647       break;
648     case STOP_REPLY: /* Stop-Control-Connection-Reply */
649       dissect_stop_reply(tvb, offset, pinfo, pptp_tree);
650       break;
651     case ECHO_REQ: /* Echo-Request */
652       dissect_echo_req(tvb, offset, pinfo, pptp_tree);
653       break;
654     case ECHO_REPLY: /* Echo-Reply */
655       dissect_echo_reply(tvb, offset, pinfo, pptp_tree);
656       break;
657     case OUT_REQ: /* Outgoing-Call-Request */
658       dissect_out_req(tvb, offset, pinfo, pptp_tree);
659       break;
660     case OUT_REPLY: /* Outgoing-Call-Reply */
661       dissect_out_reply(tvb, offset, pinfo, pptp_tree);
662       break;
663     case IN_REQ: /* Incoming-Call-Request */
664       dissect_in_req(tvb, offset, pinfo, pptp_tree);
665       break;
666     case IN_REPLY: /* Incoming-Call-Reply */
667       dissect_in_reply(tvb, offset, pinfo, pptp_tree);
668       break;
669     case IN_CONNECTED: /* Incoming-Call-Connected */
670       dissect_in_connected(tvb, offset, pinfo, pptp_tree);
671       break;
672     case CLEAR_REQ: /* Call-Clear-Request */
673       dissect_clear_req(tvb, offset, pinfo, pptp_tree);
674       break;
675     case DISC_NOTIFY: /* Call-Disconnect-Notify */
676       dissect_disc_notify(tvb, offset, pinfo, pptp_tree);
677       break;
678     case ERROR_NOTIFY: /* WAN-Error-Notify */
679       dissect_error_notify(tvb, offset, pinfo, pptp_tree);
680       break;
681     case SET_LINK: /* Set-Link-Info */
682       dissect_set_link(tvb, offset, pinfo, pptp_tree);
683       break;
684     default: /* Unknown Type... */
685       dissect_unknown(tvb, offset, pinfo, pptp_tree);
686       break;
687   }
688 }
689
690 void
691 proto_register_pptp(void)
692 {
693   static gint *ett[] = {
694     &ett_pptp,
695   };
696
697   static hf_register_info hf[] = {
698     { &hf_pptp_length,
699       { "Length", "pptp.length",
700         FT_UINT16, BASE_DEC, NULL, 0x0,
701         "Total length in octets of this PPTP message", HFILL }
702     },
703     { &hf_pptp_message_type,
704       { "Message type", "pptp.type",
705         FT_UINT16, BASE_DEC, VALS(msgtype_vals), 0x0,
706         "PPTP message type", HFILL }
707     },
708     { &hf_pptp_magic_cookie,
709       { "Magic Cookie", "pptp.magic_cookie",
710         FT_UINT32, BASE_HEX, NULL, 0x0,
711         "This constant value is used as a sanity check on received messages", HFILL }
712     },
713     { &hf_pptp_control_message_type,
714       { "Control Message Type", "pptp.control_message_type",
715         FT_UINT16, BASE_DEC, VALS(control_message_type_vals), 0x0,
716         NULL, HFILL }
717     },
718     { &hf_pptp_reserved,
719       { "Reserved", "pptp.reserved",
720         FT_BYTES, BASE_NONE, NULL, 0x0,
721         "This field MUST be 0", HFILL }
722     },
723     { &hf_pptp_protocol_version,
724       { "Protocol version", "pptp.protocol_version",
725         FT_UINT16, BASE_DEC, NULL, 0x0,
726         "The version of the PPTP protocol", HFILL }
727     },
728     { &hf_pptp_framing_capabilities,
729       { "Framing Capabilities", "pptp.framing_capabilities",
730         FT_UINT32, BASE_DEC, VALS(frametype_vals), 0x0,
731         "A set of bits indicating the type of framing", HFILL }
732     },
733     { &hf_pptp_bearer_capabilities,
734       { "Bearer Capabilities", "pptp.bearer_capabilities",
735         FT_UINT32, BASE_DEC, VALS(bearertype_vals), 0x0,
736         "A set of bits indicating the type of bearer", HFILL }
737     },
738     { &hf_pptp_maximum_channels,
739       { "Maximum Channels", "pptp.maximum_channels",
740         FT_UINT16, BASE_DEC, NULL, 0x0,
741         "The total number of individual PPP sessions this PAC can support", HFILL }
742     },
743     { &hf_pptp_firmware_revision,
744       { "Firmware Revision", "pptp.firmware_revision",
745         FT_UINT16, BASE_DEC, NULL, 0x0,
746         "This field contains the firmware revision", HFILL }
747     },
748     { &hf_pptp_host_name,
749       { "Host Name", "pptp.host_name",
750         FT_STRING, BASE_NONE, NULL, 0x0,
751         "A 64 octet field containing the DNS name", HFILL }
752     },
753     { &hf_pptp_vendor_name,
754       { "Vendor Name", "pptp.vendor_name",
755         FT_STRING, BASE_NONE, NULL, 0x0,
756         "A 64 octet field containing a vendor", HFILL }
757     },
758     { &hf_pptp_control_result,
759       { "Result Code", "pptp.control_result",
760         FT_UINT8, BASE_DEC, VALS(control_resulttype_vals), 0x0,
761         "Indicates the result of the command channel establishment attempt", HFILL }
762     },
763     { &hf_pptp_error,
764       { "Error Code", "pptp.error",
765         FT_UINT8, BASE_DEC, VALS(errortype_vals), 0x0,
766         NULL, HFILL }
767     },
768     { &hf_pptp_reason,
769       { "Reason", "pptp.reason",
770         FT_UINT8, BASE_DEC, VALS(reasontype_vals), 0x0,
771         "Indicates the reason for the control connection being close", HFILL }
772     },
773     { &hf_pptp_stop_result,
774       { "Result Code", "pptp.stop_result",
775         FT_UINT8, BASE_DEC, VALS(stop_resulttype_vals), 0x0,
776         "Indicates the result of the attempt to close the control connection", HFILL }
777     },
778     { &hf_pptp_identifier,
779       { "Identifier", "pptp.identifier",
780         FT_UINT32, BASE_DEC, NULL, 0x0,
781         NULL, HFILL }
782     },
783     { &hf_pptp_echo_result,
784       { "Result Code", "pptp.echo_result",
785         FT_UINT8, BASE_DEC, VALS(echo_resulttype_vals), 0x0,
786         "Indicates the result of the receipt of the Echo-Request", HFILL }
787     },
788     { &hf_pptp_call_id,
789       { "Call ID", "pptp.call_id",
790         FT_UINT16, BASE_DEC, NULL, 0x0,
791         "A unique identifier, unique to a particular PAC-PNS pair assigned by the PNS", HFILL }
792     },
793     { &hf_pptp_call_serial_number,
794       { "Call Serial Number", "pptp.call_serial_number",
795         FT_UINT16, BASE_DEC, NULL, 0x0,
796         "An identifier assigned by the PNS to this session for the purpose of identifying this particular session in logged session information", HFILL }
797     },
798    { &hf_pptp_minimum_bps,
799      { "Minimum BPS", "pptp.minimum_bps",
800        FT_UINT32, BASE_DEC, NULL, 0x0,
801        "The lowest acceptable line speed (in bits/second) for this session", HFILL }
802    },
803    { &hf_pptp_maximum_bps,
804      { "Maximum BPS", "pptp.maximum_bps",
805        FT_UINT32, BASE_DEC, NULL, 0x0,
806        "The highest acceptable line speed (in bits/second) for this session", HFILL }
807    },
808     { &hf_pptp_framing_type,
809       { "Framing Type", "pptp.framing_type",
810         FT_UINT32, BASE_DEC, VALS(frametype_vals), 0x0,
811         "A value indicating the type of PPP framing to be used for this outgoing call", HFILL }
812     },
813     { &hf_pptp_bearer_type,
814       { "Bearer Type", "pptp.bearer_type",
815         FT_UINT32, BASE_DEC, VALS(bearertype_vals), 0x0,
816         "A value indicating the bearer capability required for this outgoing call", HFILL }
817     },
818     { &hf_pptp_packet_receive_window_size,
819       { "Packet Receive Window Size", "pptp.packet_receive_window_size",
820         FT_UINT16, BASE_DEC, NULL, 0x0,
821         "A unique identifier, unique to a particular PAC-PNS pair assigned by the PNS", HFILL }
822     },
823     { &hf_pptp_packet_processing_delay,
824       { "Packet Processing Delay", "pptp.packet_processing_delay",
825         FT_UINT16, BASE_DEC, NULL, 0x0,
826         "A measure of the packet processing delay that might be imposed on data sent to the PNS from the PAC", HFILL }
827     },
828     { &hf_pptp_phone_number_length,
829       { "Phone Number Length", "pptp.phone_number_length",
830         FT_UINT16, BASE_DEC, NULL, 0x0,
831         "The actual number of valid digits in the Phone Number field", HFILL }
832     },
833     { &hf_pptp_phone_number,
834       { "Phone Number", "pptp.phone_number",
835         FT_STRING, BASE_NONE, NULL, 0x0,
836         "The number to be dialed to establish the outgoing session", HFILL }
837     },
838     { &hf_pptp_subaddress,
839       { "Subaddress", "pptp.subaddress",
840         FT_STRING, BASE_NONE, NULL, 0x0,
841         "A 64 octet field used to specify additional dialing information.", HFILL }
842     },
843     { &hf_pptp_peer_call_id,
844       { "Peer Call ID", "pptp.peer_call_id",
845         FT_UINT16, BASE_DEC, NULL, 0x0,
846         "This field is set to the value received in the Call ID field of the corresponding Outgoing-Call-Request message", HFILL }
847     },
848     { &hf_pptp_out_result,
849       { "Result Code", "pptp.out_result",
850         FT_UINT8, BASE_DEC, VALS(out_resulttype_vals), 0x0,
851         "Indicates the result of the receipt of the Outgoing-Call-Request attempt", HFILL }
852     },
853     { &hf_pptp_cause,
854       { "Cause Code", "pptp.cause",
855         FT_UINT16, BASE_DEC, NULL, 0x0,
856         "This field gives additional information", HFILL }
857     },
858     { &hf_pptp_connect_speed,
859       { "Connect Speed", "pptp.connect_speed",
860         FT_UINT32, BASE_DEC, NULL, 0x0,
861         "The actual connection speed used, in bits/second.", HFILL }
862     },
863     { &hf_pptp_physical_channel_id,
864       { "Physical Channel ID", "pptp.physical_channel_id",
865         FT_UINT32, BASE_DEC, NULL, 0x0,
866         "This field is set by the PAC in a vendor-specific manner to the physical channel number used to place this call", HFILL }
867     },
868     { &hf_pptp_dialed_number_length,
869       { "Dialed Number Length", "pptp.dialed_number_length",
870         FT_UINT16, BASE_DEC, NULL, 0x0,
871         "The actual number of valid digits in the Dialed Number field", HFILL }
872     },
873     { &hf_pptp_dialed_number,
874       { "Dialed Number", "pptp.dialed_number",
875         FT_STRING, BASE_NONE, NULL, 0x0,
876         "The number that was dialed by the caller", HFILL }
877     },
878
879     { &hf_pptp_dialing_number_length,
880       { "Dialing Number Length", "pptp.dialing_number_length",
881         FT_UINT16, BASE_DEC, NULL, 0x0,
882         "The actual number of valid digits in the Dialing Number field", HFILL }
883     },
884     { &hf_pptp_dialing_number,
885       { "Dialing Number", "pptp.dialing_number",
886         FT_STRING, BASE_NONE, NULL, 0x0,
887         "The number from which the call was placed", HFILL }
888     },
889     { &hf_pptp_in_result,
890       { "Result Code", "pptp.in_result",
891         FT_UINT8, BASE_DEC, VALS(in_resulttype_vals), 0x0,
892         "This value indicates the result of the Incoming-Call-Request attempt", HFILL }
893     },
894     { &hf_pptp_disc_result,
895       { "Result Code", "pptp.disc_result",
896         FT_UINT8, BASE_DEC, VALS(disc_resulttype_vals), 0x0,
897         "This value indicates the reason for the disconnect", HFILL }
898     },
899     { &hf_pptp_call_statistics,
900       { "Call Statistics", "pptp.call_Statistics",
901         FT_STRING, BASE_NONE, NULL, 0x0,
902         "This field is an ASCII string containing vendor-specific call statistics that can be logged for diagnostic purpose", HFILL }
903     },
904     { &hf_pptp_crc_errors,
905       { "CRC Errors", "pptp.crc_errors",
906         FT_UINT32, BASE_DEC, NULL, 0x0,
907         "Number of PPP frames received with CRC errors since session was established", HFILL }
908     },
909     { &hf_pptp_framing_errors,
910       { "Framing Errors", "pptp.framing_errors",
911         FT_UINT32, BASE_DEC, NULL, 0x0,
912         "Number of improperly framed PPP packets received", HFILL }
913     },
914     { &hf_pptp_hardware_overruns,
915       { "Hardware overruns", "pptp.hardware_overruns",
916         FT_UINT32, BASE_DEC, NULL, 0x0,
917         "Number of receive buffer over-runs since session was established", HFILL }
918     },
919     { &hf_pptp_buffer_overruns,
920       { "Buffer overruns", "pptp.buffer_overruns",
921         FT_UINT32, BASE_DEC, NULL, 0x0,
922         "Number of buffer over-runs detected since session was established", HFILL }
923     },
924     { &hf_pptp_timeout_errors,
925       { "Time-out Errors", "pptp.timeout_errors",
926         FT_UINT32, BASE_DEC, NULL, 0x0,
927         "Number of time-outs since call was established", HFILL }
928     },
929     { &hf_pptp_alignment_errors,
930       { "Alignment Errors", "pptp.alignment_errors",
931         FT_UINT32, BASE_DEC, NULL, 0x0,
932         "Number of Alignment errors since call was established", HFILL }
933     },
934     { &hf_pptp_send_accm,
935       { "Send ACCM", "pptp.send_accm",
936         FT_UINT32, BASE_HEX, NULL, 0x0,
937         "The send ACCM value the client should use to process outgoing PPP packets", HFILL }
938     },
939     { &hf_pptp_receive_accm,
940       { "Receive ACCM", "pptp.receive_accm",
941         FT_UINT32, BASE_HEX, NULL, 0x0,
942         "The Receive ACCM value the client should use to process incoming PPP packets", HFILL }
943     },
944   };
945
946   static ei_register_info ei[] = {
947      { &ei_pptp_incorrect_magic_cookie, { "pptp.magic_cookie.incorrect", PI_PROTOCOL, PI_WARN, "Incorrect Magic Cookie", EXPFILL }},
948   };
949
950   expert_module_t* expert_pptp;
951
952   proto_pptp = proto_register_protocol("Point-to-Point Tunnelling Protocol",
953                                        "PPTP", "pptp");
954   proto_register_field_array(proto_pptp, hf, array_length(hf));
955   proto_register_subtree_array(ett, array_length(ett));
956   expert_pptp = expert_register_protocol(proto_pptp);
957   expert_register_field_array(expert_pptp, ei, array_length(ei));
958 }
959
960 void
961 proto_reg_handoff_pptp(void)
962 {
963   dissector_handle_t pptp_handle;
964
965   pptp_handle = create_dissector_handle(dissect_pptp, proto_pptp);
966   dissector_add_uint("tcp.port", TCP_PORT_PPTP, pptp_handle);
967   data_handle = find_dissector("data");
968 }