Reduce the CinemaScope-like proportions of the preferences dialog by
[obnox/wireshark/wip.git] / 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  * $Id: packet-pptp.c,v 1.19 2001/06/18 02:17:50 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <stdio.h>
36
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40
41 #include <glib.h>
42 #include "packet.h"
43
44 static int proto_pptp = -1;
45 static int hf_pptp_message_type = -1;
46
47 static gint ett_pptp = -1;
48
49 #define TCP_PORT_PPTP                   1723
50
51 #define MAGIC_COOKIE            0x1A2B3C4D
52
53 static const value_string msgtype_vals[] = {
54   { 1, "CONTROL-MESSAGE" },
55   { 2, "MANAGEMENT-MESSAGE" },
56   { 0, NULL }
57 };
58
59 #define NUM_FRAME_TYPES         4
60 #define frametype2str(t)        \
61   ((t < NUM_FRAME_TYPES) ? frametypestr[t] : "UNKNOWN-FRAMING-TYPE")
62
63 static const char *frametypestr[NUM_FRAME_TYPES] = {
64   "UNKNOWN-FRAMING-TYPE",
65   "ASYNCHRONOUS",
66   "SYNCHRONOUS",
67   "EITHER"
68 };
69
70 #define NUM_BEARER_TYPES        4
71 #define bearertype2str(t)       \
72   ((t < NUM_BEARER_TYPES) ? bearertypestr[t] : "UNKNOWN-BEARER-TYPE")
73
74 static const char *bearertypestr[NUM_BEARER_TYPES] = {
75   "UNKNOWN-BEARER-TYPE",
76   "ANALOG",
77   "DIGITAL",
78   "EITHER"
79 };
80
81 #define NUM_CNTRLRESULT_TYPES   6
82 #define cntrlresulttype2str(t)  \
83   ((t < NUM_CNTRLRESULT_TYPES) ? cntrlresulttypestr[t] : "UNKNOWN-CNTRLRESULT-TYPE")
84
85 static const char *cntrlresulttypestr[NUM_CNTRLRESULT_TYPES] = {
86   "UNKNOWN-CNTRLRESULT-TYPE",
87   "SUCCESS",
88   "GENERAL-ERROR",
89   "COMMAND-CHANNEL-EXISTS",
90   "NOT-AUTHORIZED",
91   "VERSION-NOT-SUPPORTED"
92 };
93
94 #define NUM_ERROR_TYPES         7
95 #define errortype2str(t)        \
96   ((t < NUM_ERROR_TYPES) ? errortypestr[t] : "UNKNOWN-ERROR-TYPE")
97
98 static const char *errortypestr[NUM_ERROR_TYPES] = {
99   "NONE",
100   "NOT-CONNECTED",
101   "BAD-FORMAT",
102   "BAD-VALUE",
103   "NO-RESOURCE",
104   "BAD-CALL-ID",
105   "PAC-ERROR"
106 };
107
108 #define NUM_REASON_TYPES        4
109 #define reasontype2str(t)       \
110   ((t < NUM_REASON_TYPES) ? reasontypestr[t] : "UNKNOWN-REASON-TYPE")
111
112 static const char *reasontypestr[NUM_REASON_TYPES] = {
113   "UNKNOWN-REASON-TYPE",
114   "NONE",
115   "STOP-PROTOCOL",
116   "STOP-LOCAL-SHUTDOWN"
117 };
118
119 #define NUM_STOPRESULT_TYPES    3
120 #define stopresulttype2str(t)   \
121   ((t < NUM_STOPRESULT_TYPES) ? stopresulttypestr[t] : "UNKNOWN-STOPRESULT-TYPE")
122
123 static const char *stopresulttypestr[NUM_STOPRESULT_TYPES] = {
124   "UNKNOWN-STOPRESULT-TYPE",
125   "SUCCESS",
126   "GENERAL-ERROR"
127 };
128
129 #define NUM_ECHORESULT_TYPES    3
130 #define echoresulttype2str(t)   \
131   ((t < NUM_ECHORESULT_TYPES) ? echoresulttypestr[t] : "UNKNOWN-ECHORESULT-TYPE")
132
133 static const char *echoresulttypestr[NUM_ECHORESULT_TYPES] = {
134   "UNKNOWN-ECHORESULT-TYPE",
135   "SUCCESS",
136   "GENERAL-ERROR"
137 };
138
139 #define NUM_OUTRESULT_TYPES     8
140 #define outresulttype2str(t)    \
141   ((t < NUM_OUTRESULT_TYPES) ? outresulttypestr[t] : "UNKNOWN-OUTRESULT-TYPE")
142
143 static const char *outresulttypestr[NUM_OUTRESULT_TYPES] = {
144   "UNKNOWN-OUTRESULT-TYPE",
145   "CONNECTED",
146   "GENERAL-ERROR",
147   "NO-CARRIER",
148   "BUSY",
149   "NO-DIAL-TONE",
150   "TIME-OUT",
151   "DO-NOT-ACCEPT"
152 };
153
154 #define NUM_INRESULT_TYPES      4
155 #define inresulttype2str(t)     \
156   ((t < NUM_INRESULT_TYPES) ? inresulttypestr[t] : "UNKNOWN-INRESULT-TYPE")
157
158 static const char *inresulttypestr[NUM_INRESULT_TYPES] = {
159   "UNKNOWN-INRESULT-TYPE",
160   "CONNECT",
161   "GENERAL-ERROR",
162   "DO-NOT-ACCEPT"
163 };
164
165 #define NUM_DISCRESULT_TYPES    5
166 #define discresulttype2str(t)   \
167   ((t < NUM_DISCRESULT_TYPES) ? discresulttypestr[t] : "UNKNOWN-DISCRESULT-TYPE")
168
169 static const char *discresulttypestr[NUM_DISCRESULT_TYPES] = {
170   "UNKNOWN-DISCRESULT-TYPE",
171   "LOST-CARRIER",
172   "GENERAL-ERROR",
173   "ADMIN-SHUTDOWN",
174   "REQUEST"
175 };
176
177 static void dissect_unknown(tvbuff_t *, int, packet_info *, proto_tree *);
178 static void dissect_cntrl_req(tvbuff_t *, int, packet_info *, proto_tree *);
179 static void dissect_cntrl_reply(tvbuff_t *, int, packet_info *, proto_tree *);
180 static void dissect_stop_req(tvbuff_t *, int, packet_info *, proto_tree *);
181 static void dissect_stop_reply(tvbuff_t *, int, packet_info *, proto_tree *);
182 static void dissect_echo_req(tvbuff_t *, int, packet_info *, proto_tree *);
183 static void dissect_echo_reply(tvbuff_t *, int, packet_info *, proto_tree *);
184 static void dissect_out_req(tvbuff_t *, int, packet_info *, proto_tree *);
185 static void dissect_out_reply(tvbuff_t *, int, packet_info *, proto_tree *);
186 static void dissect_in_req(tvbuff_t *, int, packet_info *, proto_tree *);
187 static void dissect_in_reply(tvbuff_t *, int, packet_info *, proto_tree *);
188 static void dissect_in_connected(tvbuff_t *, int, packet_info *, proto_tree *);
189 static void dissect_clear_req(tvbuff_t *, int, packet_info *, proto_tree *);
190 static void dissect_disc_notify(tvbuff_t *, int, packet_info *, proto_tree *);
191 static void dissect_error_notify(tvbuff_t *, int, packet_info *, proto_tree *);
192 static void dissect_set_link(tvbuff_t *, int, packet_info *, proto_tree *);
193
194 #define NUM_CNTRL_TYPES         16
195 #define cntrltype2str(t)        \
196   ((t < NUM_CNTRL_TYPES) ? strfuncs[t].str : "UNKNOWN-CONTROL-TYPE")
197
198 static struct strfunc {
199   const char *  str;
200   void          (*func)(tvbuff_t *, int, packet_info *, proto_tree *);
201 } strfuncs[NUM_CNTRL_TYPES] = {
202   {"UNKNOWN-CONTROL-TYPE",    dissect_unknown      },
203   {"START-CONTROL-REQUEST",   dissect_cntrl_req    },
204   {"START-CONTROL-REPLY",     dissect_cntrl_reply  },
205   {"STOP-CONTROL-REQUEST",    dissect_stop_req     },
206   {"STOP-CONTROL-REPLY",      dissect_stop_reply   },
207   {"ECHO-REQUEST",            dissect_echo_req     },
208   {"ECHO-REPLY",              dissect_echo_reply   },
209   {"OUTGOING-CALL-REQUEST",   dissect_out_req      },
210   {"OUTGOING-CALL-REPLY",     dissect_out_reply    },
211   {"INCOMING-CALL-REQUEST",   dissect_in_req       },
212   {"INCOMING-CALL-REPLY",     dissect_in_reply     },
213   {"INCOMING-CALL-CONNECTED", dissect_in_connected },
214   {"CLEAR-CALL-REQUEST",      dissect_clear_req    },
215   {"DISCONNECT-NOTIFY",       dissect_disc_notify  },
216   {"ERROR-NOTIFY",            dissect_error_notify },
217   {"SET-LINK",                dissect_set_link     }
218 };
219
220 /*
221  * Length of host name and vendor name strings in control requests and
222  * replies.
223  */
224 #define HOSTLEN         64
225 #define VENDORLEN       64
226
227 /*
228  * Length of phone number(s) and subaddress in call requests.
229  */
230 #define PHONELEN        64
231 #define SUBADDRLEN      64
232
233 /*
234  * Length of statistics in a Call-Disconnect-Notify message.
235  */
236 #define STATSLEN        128
237
238 static void
239 dissect_pptp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
240 {
241   int                   offset = 0;
242   guint16               len;
243   guint16               cntrl_type;
244
245   if (check_col(pinfo->fd, COL_PROTOCOL))
246     col_set_str(pinfo->fd, COL_PROTOCOL, "PPTP");
247   if (check_col(pinfo->fd, COL_INFO))
248     col_clear(pinfo->fd, COL_INFO);
249   
250   len        = tvb_get_ntohs(tvb, offset);
251   cntrl_type = tvb_get_ntohs(tvb, offset + 8);
252
253   if (check_col(pinfo->fd, COL_INFO))
254     col_add_fstr(pinfo->fd, COL_INFO, "%s", cntrltype2str(cntrl_type));
255
256   if (tree) {
257     guint32             cookie;
258     proto_item *        ti;
259     proto_tree *        pptp_tree;
260
261     ti = proto_tree_add_item(tree, proto_pptp, tvb, offset, len, FALSE);
262     pptp_tree = proto_item_add_subtree(ti, ett_pptp);
263     
264     proto_tree_add_text(pptp_tree, tvb, offset, 2, "Length: %u", len);
265     offset += 2;
266
267     proto_tree_add_item(pptp_tree, hf_pptp_message_type, tvb,
268                                offset, 2, FALSE);
269     offset += 2;
270
271     cookie = tvb_get_ntohl(tvb, offset);
272
273     if (cookie == MAGIC_COOKIE)
274       proto_tree_add_text(pptp_tree, tvb, offset, 4,
275                           "Cookie: %#08x (correct)", cookie);
276     else
277       proto_tree_add_text(pptp_tree, tvb, offset, 4,
278                           "Cookie: %#08x (incorrect)", cookie);
279     offset += 4;
280     
281     proto_tree_add_text(pptp_tree, tvb, offset, 2,
282                         "Control type: %s (%u)", cntrltype2str(cntrl_type), cntrl_type);
283     offset += 2;
284
285     proto_tree_add_text(pptp_tree, tvb, offset, 2,
286                         "Reserved: %u", tvb_get_ntohs(tvb, offset));
287     offset += 2;
288
289     if (cntrl_type < NUM_CNTRL_TYPES)
290       ( *(strfuncs[cntrl_type].func))(tvb, offset, pinfo, pptp_tree);
291     else
292       dissect_data(tvb, offset, pinfo, pptp_tree);
293   }
294 }
295
296 static void
297 dissect_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo,
298                 proto_tree *tree)
299 {
300   dissect_data(tvb, offset, pinfo, tree);
301 }
302
303 static void
304 dissect_cntrl_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
305                   proto_tree *tree)
306 {
307   guint8                major_ver;
308   guint8                minor_ver;
309   guint32               frame;
310   guint32               bearer;
311   guint8                host[HOSTLEN+1];
312   guint8                vendor[VENDORLEN+1];
313
314   major_ver = tvb_get_guint8(tvb, offset);
315   minor_ver = tvb_get_guint8(tvb, offset + 1);
316   proto_tree_add_text(tree, tvb, offset, 2, 
317                       "Protocol version: %u.%u", major_ver, minor_ver);
318   offset += 2;
319
320   proto_tree_add_text(tree, tvb, offset, 2,
321                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
322   offset += 2;
323
324   frame = tvb_get_ntohl(tvb, offset);
325   proto_tree_add_text(tree, tvb, offset, 4,
326                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
327   offset += 4;
328
329   bearer = tvb_get_ntohl(tvb, offset);
330   proto_tree_add_text(tree, tvb, offset, 4,
331                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
332   offset += 4;
333
334   proto_tree_add_text(tree, tvb, offset, 2,
335                       "Maximum channels: %u", tvb_get_ntohs(tvb, offset));
336   offset += 2;
337   
338   proto_tree_add_text(tree, tvb, offset, 2,
339                       "Firmware revision: %u", tvb_get_ntohs(tvb, offset));
340   offset += 2;
341   
342   tvb_get_nstringz0(tvb, offset, HOSTLEN, host);
343   proto_tree_add_text(tree, tvb, offset, HOSTLEN,
344                       "Hostname: %s", host);
345   offset += HOSTLEN;
346   
347   tvb_get_nstringz0(tvb, offset, VENDORLEN, vendor);
348   proto_tree_add_text(tree, tvb, offset, VENDORLEN,
349                       "Vendor: %s", vendor);
350 }
351
352 static void
353 dissect_cntrl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
354                     proto_tree *tree)
355 {
356   guint8                major_ver;
357   guint8                minor_ver;
358   guint8                result;
359   guint8                error;
360   guint32               frame;
361   guint32               bearer;
362   guint8                host[HOSTLEN+1];
363   guint8                vendor[VENDORLEN+1];
364
365   major_ver = tvb_get_guint8(tvb, offset);
366   minor_ver = tvb_get_guint8(tvb, offset + 1);
367   proto_tree_add_text(tree, tvb, offset, 2, 
368                       "Protocol version: %u.%u", major_ver, minor_ver);
369   offset += 2;
370
371   result = tvb_get_guint8(tvb, offset);
372   proto_tree_add_text(tree, tvb, offset, 1,
373                       "Result: %s (%u)", cntrlresulttype2str(result), result);
374   offset += 1;
375   
376   error = tvb_get_guint8(tvb, offset);
377   proto_tree_add_text(tree, tvb, offset, 1,
378                       "Error: %s (%u)", errortype2str(error), error);
379   offset += 1;
380   
381   frame = tvb_get_ntohl(tvb, offset);
382   proto_tree_add_text(tree, tvb, offset, 4,
383                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
384   offset += 4;
385
386   bearer = tvb_get_ntohl(tvb, offset);
387   proto_tree_add_text(tree, tvb, offset, 4,
388                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
389   offset += 4;
390
391   proto_tree_add_text(tree, tvb, offset, 2,
392                       "Maximum channels: %u", tvb_get_ntohs(tvb, offset));
393   offset += 2;
394   
395   proto_tree_add_text(tree, tvb, offset, 2,
396                       "Firmware revision: %u", tvb_get_ntohs(tvb, offset));
397   offset += 2;
398   
399   tvb_get_nstringz0(tvb, offset, HOSTLEN, host);
400   proto_tree_add_text(tree, tvb, offset, HOSTLEN,
401                       "Hostname: %s", host);
402   offset += HOSTLEN;
403   
404   tvb_get_nstringz0(tvb, offset, VENDORLEN, vendor);
405   proto_tree_add_text(tree, tvb, offset, VENDORLEN,
406                       "Vendor: %s", vendor);
407 }
408
409 static void
410 dissect_stop_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
411                  proto_tree *tree)
412 {
413   guint8                reason;
414
415   reason = tvb_get_guint8(tvb, offset);
416   proto_tree_add_text(tree, tvb, offset, 1,
417                       "Reason: %s (%u)", reasontype2str(reason), reason);
418   offset += 1;
419   
420   proto_tree_add_text(tree, tvb, offset, 1,
421                       "Reserved: %u", tvb_get_guint8(tvb, offset));
422   offset += 1;
423   
424   proto_tree_add_text(tree, tvb, offset, 2,
425                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
426 }
427
428 static void
429 dissect_stop_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
430                    proto_tree *tree)
431 {
432   guint8                result;
433   guint8                error;
434
435   result = tvb_get_guint8(tvb, offset);
436   proto_tree_add_text(tree, tvb, offset, 1,
437                       "Result: %s (%u)", stopresulttype2str(result), result);
438   offset += 1;
439   
440   error = tvb_get_guint8(tvb, offset);
441   proto_tree_add_text(tree, tvb, offset, 1,
442                       "Error: %s (%u)", errortype2str(error), error);
443   offset += 1;
444   
445   proto_tree_add_text(tree, tvb, offset, 2,
446                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
447 }
448
449 static void
450 dissect_echo_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
451                  proto_tree *tree)
452 {
453   proto_tree_add_text(tree, tvb, offset, 4,
454                       "Identifier: %u", tvb_get_ntohl(tvb, offset));
455 }
456
457 static void
458 dissect_echo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
459                    proto_tree *tree)
460 {
461   guint8                result;
462   guint8                error;
463
464   proto_tree_add_text(tree, tvb, offset, 4,
465                       "Identifier: %u", tvb_get_ntohl(tvb, offset));
466   offset += 4;
467   
468   result = tvb_get_guint8(tvb, offset);
469   proto_tree_add_text(tree, tvb, offset, 1,
470                       "Result: %s (%u)", echoresulttype2str(result), result);
471   offset += 1;
472   
473   error = tvb_get_guint8(tvb, offset);
474   proto_tree_add_text(tree, tvb, offset, sizeof(error),
475                       "Error: %s (%u)", errortype2str(error), error);
476   offset += 1;
477   
478   proto_tree_add_text(tree, tvb, offset, 2,
479                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
480 }
481
482 static void
483 dissect_out_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
484                 proto_tree *tree)
485 {
486   guint32               bearer;
487   guint32               frame;
488   guint8                phone[PHONELEN+1];
489   guint8                subaddr[SUBADDRLEN+1];
490
491   proto_tree_add_text(tree, tvb, offset, 2,
492                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
493   offset += 2;
494   
495   proto_tree_add_text(tree, tvb, offset, 2,
496                       "Call Serial Number: %u", tvb_get_ntohs(tvb, offset));
497   offset += 2;
498   
499   proto_tree_add_text(tree, tvb, offset, 4,
500                       "Minimum BPS: %u", tvb_get_ntohl(tvb, offset));
501   offset += 4;
502   
503   proto_tree_add_text(tree, tvb, offset, 4,
504                       "Maximum BPS: %u", tvb_get_ntohl(tvb, offset));
505   offset += 4;
506   
507   bearer = tvb_get_ntohl(tvb, offset);
508   proto_tree_add_text(tree, tvb, offset, 4,
509                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
510   offset += 4;
511
512   frame = tvb_get_ntohl(tvb, offset);
513   proto_tree_add_text(tree, tvb, offset, 4,
514                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
515   offset += 4;
516
517   proto_tree_add_text(tree, tvb, offset, 2,
518                       "Receive window size: %u", tvb_get_ntohs(tvb, offset));
519   offset += 2;
520
521   proto_tree_add_text(tree, tvb, offset, 2,
522                       "Processing delay: %u", tvb_get_ntohs(tvb, offset));
523   offset += 2;
524   
525   proto_tree_add_text(tree, tvb, offset, 2,
526                       "Phone number length: %u", tvb_get_ntohs(tvb, offset));
527   offset += 2;
528   
529   proto_tree_add_text(tree, tvb, offset, 2,
530                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
531   offset += 2;
532   
533   tvb_get_nstringz0(tvb, offset, PHONELEN, phone);
534   proto_tree_add_text(tree, tvb, offset, PHONELEN,
535                       "Phone number: %s", phone);
536   offset += PHONELEN;
537
538   tvb_get_nstringz0(tvb, offset, SUBADDRLEN, subaddr);
539   proto_tree_add_text(tree, tvb, offset, SUBADDRLEN,
540                       "Subaddress: %s", subaddr);
541 }
542
543 static void
544 dissect_out_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
545                   proto_tree *tree)
546 {
547   guint8                result;
548   guint8                error;
549
550   proto_tree_add_text(tree, tvb, offset, 2,
551                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
552   offset += 2;
553   
554   proto_tree_add_text(tree, tvb, offset, 2,
555                       "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
556   offset += 2;
557
558   result = tvb_get_guint8(tvb, offset);
559   proto_tree_add_text(tree, tvb, offset, 1,
560                       "Result: %s (%u)", outresulttype2str(result), result);
561   offset += 1;
562   
563   error = tvb_get_guint8(tvb, offset);
564   proto_tree_add_text(tree, tvb, offset, 1,
565                       "Error: %s (%u)", errortype2str(error), error);
566   offset += 1;
567
568   proto_tree_add_text(tree, tvb, offset, 2,
569                       "Cause code: %u", tvb_get_ntohs(tvb, offset));
570   offset += 2;
571   
572   proto_tree_add_text(tree, tvb, offset, 4,
573                       "Connect speed: %u", tvb_get_ntohl(tvb, offset));
574   offset += 4;
575
576   proto_tree_add_text(tree, tvb, offset, 2,
577                       "Receive window size: %u", tvb_get_ntohs(tvb, offset));
578   offset += 2;
579
580   proto_tree_add_text(tree, tvb, offset, 2,
581                       "Processing delay: %u", tvb_get_ntohs(tvb, offset));
582   offset += 2;
583   
584   proto_tree_add_text(tree, tvb, offset, 4,
585                       "Physical channel ID: %u", tvb_get_ntohl(tvb, offset));
586 }
587
588 static void
589 dissect_in_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
590                proto_tree *tree)
591 {
592   guint32               bearer;
593   guint8                dialed[PHONELEN+1];
594   guint8                dialing[PHONELEN+1];
595   guint8                subaddr[SUBADDRLEN+1];
596
597   proto_tree_add_text(tree, tvb, offset, 2,
598                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
599   offset += 2;
600   
601   proto_tree_add_text(tree, tvb, offset, 2,
602                       "Call serial number: %u", tvb_get_ntohs(tvb, offset));
603   offset += 2;
604   
605   bearer = tvb_get_ntohl(tvb, offset);
606   proto_tree_add_text(tree, tvb, offset, 4,
607                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
608   offset += 4;
609
610   proto_tree_add_text(tree, tvb, offset, 4,
611                       "Physical channel ID: %u", tvb_get_ntohl(tvb, offset));
612   offset += 4;
613
614   proto_tree_add_text(tree, tvb, offset, 2,
615                       "Dialed number length: %u", tvb_get_ntohs(tvb, offset));
616   offset += 2;
617   
618   proto_tree_add_text(tree, tvb, offset, 2,
619                       "Dialing number length: %u", tvb_get_ntohs(tvb, offset));
620   offset += 2;
621   
622   tvb_get_nstringz0(tvb, offset, PHONELEN, dialed);
623   proto_tree_add_text(tree, tvb, offset, PHONELEN,
624                       "Dialed number: %s", dialed);
625   offset += PHONELEN;
626   
627   tvb_get_nstringz0(tvb, offset, PHONELEN, dialing);
628   proto_tree_add_text(tree, tvb, offset, PHONELEN,
629                       "Dialing number: %s", dialing);
630   offset += PHONELEN;
631   
632   tvb_get_nstringz0(tvb, offset, SUBADDRLEN, subaddr);
633   proto_tree_add_text(tree, tvb, offset, SUBADDRLEN,
634                       "Subaddress: %s", subaddr);
635 }
636
637 static void
638 dissect_in_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
639                  proto_tree *tree)
640 {
641   guint8                result;
642   guint8                error;
643
644   proto_tree_add_text(tree, tvb, offset, 2,
645                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
646   offset += 2;
647   
648   proto_tree_add_text(tree, tvb, offset, 2,
649                       "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
650   offset += 2;
651
652   result = tvb_get_guint8(tvb, offset);
653   proto_tree_add_text(tree, tvb, offset, 1,
654                       "Result: %s (%u)", inresulttype2str(result), result);
655   offset += 1;
656   
657   error = tvb_get_guint8(tvb, offset);
658   proto_tree_add_text(tree, tvb, offset, 1,
659                       "Error: %s (%u)", errortype2str(error), error);
660   offset += 1;
661
662   proto_tree_add_text(tree, tvb, offset, 2,
663                       "Receive window size: %u", tvb_get_ntohs(tvb, offset));
664   offset += 2;
665
666   proto_tree_add_text(tree, tvb, offset, 2,
667                       "Processing delay: %u", tvb_get_ntohs(tvb, offset));
668   offset += 2;
669   
670   proto_tree_add_text(tree, tvb, offset, 2,
671                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
672 }
673
674 static void
675 dissect_in_connected(tvbuff_t *tvb, int offset, packet_info *pinfo,
676                      proto_tree *tree)
677 {
678   guint32               frame;
679   
680   proto_tree_add_text(tree, tvb, offset, 2,
681                       "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
682   offset += 2;
683
684   proto_tree_add_text(tree, tvb, offset, 2,
685                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
686   offset += 2;
687
688   proto_tree_add_text(tree, tvb, offset, 4,
689                       "Connect speed: %u", tvb_get_ntohl(tvb, offset));
690   offset += 4;
691   
692   proto_tree_add_text(tree, tvb, offset, 2,
693                       "Receive window size: %u", tvb_get_ntohs(tvb, offset));
694   offset += 2;
695
696   proto_tree_add_text(tree, tvb, offset, 2,
697                       "Processing delay: %u", tvb_get_ntohs(tvb, offset));
698   offset += 2;
699   
700   frame = tvb_get_ntohl(tvb, offset);
701   proto_tree_add_text(tree, tvb, offset, 4,
702                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
703 }
704
705 static void
706 dissect_clear_req(tvbuff_t *tvb, int offset, packet_info *pinfo,
707                   proto_tree *tree)
708 {
709   proto_tree_add_text(tree, tvb, offset, 2,
710                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
711   offset += 2;
712
713   proto_tree_add_text(tree, tvb, offset, 2,
714                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
715 }
716
717 static void
718 dissect_disc_notify(tvbuff_t *tvb, int offset, packet_info *pinfo,
719                     proto_tree *tree)
720 {
721   guint8                result;
722   guint8                error;
723   guint8                stats[STATSLEN+1];
724
725   proto_tree_add_text(tree, tvb, offset, 2,
726                       "Call ID: %u", tvb_get_ntohs(tvb, offset));
727   offset += 2;
728
729   result = tvb_get_guint8(tvb, offset);
730   proto_tree_add_text(tree, tvb, offset, 1,
731                       "Result: %s (%u)", discresulttype2str(result), result);
732   offset += 1;
733   
734   error = tvb_get_guint8(tvb, offset);
735   proto_tree_add_text(tree, tvb, offset, 1,
736                       "Error: %s (%u)", errortype2str(error), error);
737   offset += 1;
738
739   proto_tree_add_text(tree, tvb, offset, 2,
740                       "Cause code: %u", tvb_get_ntohs(tvb, offset));
741   offset += 2;
742   
743   proto_tree_add_text(tree, tvb, offset, 2,
744                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
745   offset += 2;
746
747   tvb_get_nstringz0(tvb, offset, STATSLEN, stats);
748   proto_tree_add_text(tree, tvb, offset, STATSLEN,
749                       "Call statistics: %s", stats);
750 }
751
752 static void
753 dissect_error_notify(tvbuff_t *tvb, int offset, packet_info *pinfo,
754                      proto_tree *tree)
755 {
756   proto_tree_add_text(tree, tvb, offset, 2,
757                       "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
758   offset += 2;
759
760   proto_tree_add_text(tree, tvb, offset, 2,
761                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
762   offset += 2;
763
764   proto_tree_add_text(tree, tvb, offset, 4,
765                       "CRC errors: %u", tvb_get_ntohl(tvb, offset));
766   offset += 4;
767   
768   proto_tree_add_text(tree, tvb, offset, 4,
769                       "Framing errors: %u", tvb_get_ntohl(tvb, offset));
770   offset += 4;
771   
772   proto_tree_add_text(tree, tvb, offset, 4,
773                       "Hardware overruns: %u", tvb_get_ntohl(tvb, offset));
774   offset += 4;
775   
776   proto_tree_add_text(tree, tvb, offset, 4,
777                       "Buffer overruns: %u", tvb_get_ntohl(tvb, offset));
778   offset += 4;
779   
780   proto_tree_add_text(tree, tvb, offset, 4,
781                       "Time-out errors: %u", tvb_get_ntohl(tvb, offset));
782   offset += 4;
783   
784   proto_tree_add_text(tree, tvb, offset, 4,
785                       "Alignment errors: %u", tvb_get_ntohl(tvb, offset));
786 }
787
788 static void
789 dissect_set_link(tvbuff_t *tvb, int offset, packet_info *pinfo,
790                  proto_tree *tree)
791 {
792   proto_tree_add_text(tree, tvb, offset, 2,
793                       "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
794   offset += 2;
795
796   proto_tree_add_text(tree, tvb, offset, 2,
797                       "Reserved: %u", tvb_get_ntohs(tvb, offset));
798   offset += 2;
799
800   proto_tree_add_text(tree, tvb, offset, 4,
801                       "Send ACCM: %#08x", tvb_get_ntohl(tvb, offset));
802   offset += 4;
803   
804   proto_tree_add_text(tree, tvb, offset, 4,
805                       "Recv ACCM: %#08x", tvb_get_ntohl(tvb, offset));
806 }
807
808 void
809 proto_register_pptp(void)
810 {
811   static gint *ett[] = {
812     &ett_pptp,
813   };
814
815   static hf_register_info hf[] = {
816     { &hf_pptp_message_type,
817       { "Message type",                 "pptp.type",
818         FT_UINT16,      BASE_DEC,       VALS(msgtype_vals),     0x0,
819         "PPTP message type", HFILL }}
820   };
821
822   proto_pptp = proto_register_protocol("Point-to-Point Tunnelling Protocol",
823                                        "PPTP", "pptp");
824   proto_register_field_array(proto_pptp, hf, array_length(hf));
825   proto_register_subtree_array(ett, array_length(ett));
826 }
827
828 void
829 proto_reg_handoff_pptp(void)
830 {
831   dissector_add("tcp.port", TCP_PORT_PPTP, dissect_pptp, proto_pptp);
832 }