If the capture child process exits unexpectedly, give more information
[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.13 2000/11/19 08:54:02 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 #define NUM_MSG_TYPES           3
54 #define msgtype2str(t)  \
55   ((t < NUM_MSG_TYPES) ? msgtypestr[t] : "UNKNOWN-MESSAGES-TYPE")
56
57 static const char *msgtypestr[NUM_MSG_TYPES] = {
58   "UNKNOWN-MESSAGE-TYPE",
59   "CONTROL-MESSAGE",
60   "MANAGEMENT-MESSAGE"
61 };
62
63 #define NUM_FRAME_TYPES         4
64 #define frametype2str(t)        \
65   ((t < NUM_FRAME_TYPES) ? frametypestr[t] : "UNKNOWN-FRAMING-TYPE")
66
67 static const char *frametypestr[NUM_FRAME_TYPES] = {
68   "UNKNOWN-FRAMING-TYPE",
69   "ASYNCHRONOUS",
70   "SYNCHRONOUS",
71   "EITHER"
72 };
73
74 #define NUM_BEARER_TYPES        4
75 #define bearertype2str(t)       \
76   ((t < NUM_BEARER_TYPES) ? bearertypestr[t] : "UNKNOWN-BEARER-TYPE")
77
78 static const char *bearertypestr[NUM_BEARER_TYPES] = {
79   "UNKNOWN-BEARER-TYPE",
80   "ANALOG",
81   "DIGITAL",
82   "EITHER"
83 };
84
85 #define NUM_CNTRLRESULT_TYPES   6
86 #define cntrlresulttype2str(t)  \
87   ((t < NUM_CNTRLRESULT_TYPES) ? cntrlresulttypestr[t] : "UNKNOWN-CNTRLRESULT-TYPE")
88
89 static const char *cntrlresulttypestr[NUM_CNTRLRESULT_TYPES] = {
90   "UNKNOWN-CNTRLRESULT-TYPE",
91   "SUCCESS",
92   "GENERAL-ERROR",
93   "COMMAND-CHANNEL-EXISTS",
94   "NOT-AUTHORIZED",
95   "VERSION-NOT-SUPPORTED"
96 };
97
98 #define NUM_ERROR_TYPES         7
99 #define errortype2str(t)        \
100   ((t < NUM_ERROR_TYPES) ? errortypestr[t] : "UNKNOWN-ERROR-TYPE")
101
102 static const char *errortypestr[NUM_ERROR_TYPES] = {
103   "NONE",
104   "NOT-CONNECTED",
105   "BAD-FORMAT",
106   "BAD-VALUE",
107   "NO-RESOURCE",
108   "BAD-CALL-ID",
109   "PAC-ERROR"
110 };
111
112 #define NUM_REASON_TYPES        4
113 #define reasontype2str(t)       \
114   ((t < NUM_REASON_TYPES) ? reasontypestr[t] : "UNKNOWN-REASON-TYPE")
115
116 static const char *reasontypestr[NUM_REASON_TYPES] = {
117   "UNKNOWN-REASON-TYPE",
118   "NONE",
119   "STOP-PROTOCOL",
120   "STOP-LOCAL-SHUTDOWN"
121 };
122
123 #define NUM_STOPRESULT_TYPES    3
124 #define stopresulttype2str(t)   \
125   ((t < NUM_STOPRESULT_TYPES) ? stopresulttypestr[t] : "UNKNOWN-STOPRESULT-TYPE")
126
127 static const char *stopresulttypestr[NUM_STOPRESULT_TYPES] = {
128   "UNKNOWN-STOPRESULT-TYPE",
129   "SUCCESS",
130   "GENERAL-ERROR"
131 };
132
133 #define NUM_ECHORESULT_TYPES    3
134 #define echoresulttype2str(t)   \
135   ((t < NUM_ECHORESULT_TYPES) ? echoresulttypestr[t] : "UNKNOWN-ECHORESULT-TYPE")
136
137 static const char *echoresulttypestr[NUM_ECHORESULT_TYPES] = {
138   "UNKNOWN-ECHORESULT-TYPE",
139   "SUCCESS",
140   "GENERAL-ERROR"
141 };
142
143 #define NUM_OUTRESULT_TYPES     8
144 #define outresulttype2str(t)    \
145   ((t < NUM_OUTRESULT_TYPES) ? outresulttypestr[t] : "UNKNOWN-OUTRESULT-TYPE")
146
147 static const char *outresulttypestr[NUM_OUTRESULT_TYPES] = {
148   "UNKNOWN-OUTRESULT-TYPE",
149   "CONNECTED",
150   "GENERAL-ERROR",
151   "NO-CARRIER",
152   "BUSY",
153   "NO-DIAL-TONE",
154   "TIME-OUT",
155   "DO-NOT-ACCEPT"
156 };
157
158 #define NUM_INRESULT_TYPES      4
159 #define inresulttype2str(t)     \
160   ((t < NUM_INRESULT_TYPES) ? inresulttypestr[t] : "UNKNOWN-INRESULT-TYPE")
161
162 static const char *inresulttypestr[NUM_INRESULT_TYPES] = {
163   "UNKNOWN-INRESULT-TYPE",
164   "CONNECT",
165   "GENERAL-ERROR",
166   "DO-NOT-ACCEPT"
167 };
168
169 #define NUM_DISCRESULT_TYPES    5
170 #define discresulttype2str(t)   \
171   ((t < NUM_DISCRESULT_TYPES) ? discresulttypestr[t] : "UNKNOWN-DISCRESULT-TYPE")
172
173 static const char *discresulttypestr[NUM_DISCRESULT_TYPES] = {
174   "UNKNOWN-DISCRESULT-TYPE",
175   "LOST-CARRIER",
176   "GENERAL-ERROR",
177   "ADMIN-SHUTDOWN",
178   "REQUEST"
179 };
180
181 static void dissect_unknown(const u_char *, int, frame_data *, proto_tree *);
182 static void dissect_cntrl_req(const u_char *, int, frame_data *, proto_tree *);
183 static void dissect_cntrl_reply(const u_char *, int, frame_data *, proto_tree *);
184 static void dissect_stop_req(const u_char *, int, frame_data *, proto_tree *);
185 static void dissect_stop_reply(const u_char *, int, frame_data *, proto_tree *);
186 static void dissect_echo_req(const u_char *, int, frame_data *, proto_tree *);
187 static void dissect_echo_reply(const u_char *, int, frame_data *, proto_tree *);
188 static void dissect_out_req(const u_char *, int, frame_data *, proto_tree *);
189 static void dissect_out_reply(const u_char *, int, frame_data *, proto_tree *);
190 static void dissect_in_req(const u_char *, int, frame_data *, proto_tree *);
191 static void dissect_in_reply(const u_char *, int, frame_data *, proto_tree *);
192 static void dissect_in_connected(const u_char *, int, frame_data *, proto_tree *);
193 static void dissect_clear_req(const u_char *, int, frame_data *, proto_tree *);
194 static void dissect_disc_notify(const u_char *, int, frame_data *, proto_tree *);
195 static void dissect_error_notify(const u_char *, int, frame_data *, proto_tree *);
196 static void dissect_set_link(const u_char *, int, frame_data *, proto_tree *);
197
198 #define NUM_CNTRL_TYPES         16
199 #define cntrltype2str(t)        \
200   ((t < NUM_CNTRL_TYPES) ? strfuncs[t].str : "UNKNOWN-CONTROL-TYPE")
201
202 static struct strfunc {
203   const char *  str;
204   void          (*func)(const u_char *, int, frame_data *, proto_tree *);
205 } strfuncs[NUM_CNTRL_TYPES] = {
206   {"UNKNOWN-CONTROL-TYPE",    dissect_unknown      },
207   {"START-CONTROL-REQUEST",   dissect_cntrl_req    },
208   {"START-CONTROL-REPLY",     dissect_cntrl_reply  },
209   {"STOP-CONTROL-REQUEST",    dissect_stop_req     },
210   {"STOP-CONTROL-REPLY",      dissect_stop_reply   },
211   {"ECHO-REQUEST",            dissect_echo_req     },
212   {"ECHO-REPLY",              dissect_echo_reply   },
213   {"OUTGOING-CALL-REQUEST",   dissect_out_req      },
214   {"OUTGOING-CALL-REPLY",     dissect_out_reply    },
215   {"INCOMING-CALL-REQUEST",   dissect_in_req       },
216   {"INCOMING-CALL-REPLY",     dissect_in_reply     },
217   {"INCOMING-CALL-CONNECTED", dissect_in_connected },
218   {"CLEAR-CALL-REQUEST",      dissect_clear_req    },
219   {"DISCONNECT-NOTIFY",       dissect_disc_notify  },
220   {"ERROR-NOTIFY",            dissect_error_notify },
221   {"SET-LINK",                dissect_set_link     }
222 };
223
224 struct pptp_hdr
225 {
226   guint16       len;
227   guint16       type;
228   guint32       cookie;
229   guint16       cntrl_type;
230   guint16       resv;
231 };
232
233 struct cntrl_req
234 {
235   guint8        major_ver;
236   guint8        minor_ver;
237   guint16       resv;
238   guint32       frame;
239   guint32       bearer;
240   guint16       max_chan;
241   guint16       firm_rev;
242   guint8        host[64];
243   guint8        vendor[64];
244 };
245
246 struct cntrl_reply
247 {
248   guint8        major_ver;
249   guint8        minor_ver;
250   guint8        result;
251   guint8        error;
252   guint32       frame;
253   guint32       bearer;
254   guint16       max_chan;
255   guint16       firm_rev;
256   guint8        host[64];
257   guint8        vendor[64];
258 };
259
260 struct stop_req
261 {
262   guint8        reason;
263   guint8        resv0;
264   guint16       resv1;
265 };
266
267 struct stop_reply
268 {
269   guint8        result;
270   guint8        error;
271   guint16       resv;
272 };
273
274 struct echo_req
275 {
276   guint32       ident;
277 };
278
279 struct echo_reply
280 {
281   guint32       ident;
282   guint8        result;
283   guint8        error;
284   guint16       resv;
285 };
286
287 struct out_req
288 {
289   guint16       call_id;
290   guint16       call_serial;
291   guint32       min_bps;
292   guint32       max_bps;
293   guint32       bearer;
294   guint32       frame;
295   guint16       win_size;
296   guint16       delay;
297   guint16       phone_len;
298   guint16       resv;
299   guint8        phone[64];
300   guint8        subaddr[64];
301 };
302
303 struct out_reply
304 {
305   guint16       call_id;
306   guint16       peer_id;
307   guint8        result;
308   guint8        error;
309   guint16       cause;
310   guint32       speed;
311   guint16       win_size;
312   guint16       delay;
313   guint32       channel_id;
314 };
315
316 struct in_req
317 {
318   guint16       call_id;
319   guint16       call_serial;
320   guint32       bearer;
321   guint32       channel_id;
322   guint16       dialed_len;
323   guint16       dialing_len;
324   guint8        dialed[64];
325   guint8        dialing[64];
326   guint8        subaddr[64];
327 };
328
329 struct in_reply
330 {
331   guint16       call_id;
332   guint16       peer_id;
333   guint8        result;
334   guint8        error;
335   guint16       win_size;
336   guint16       delay;
337   guint16       resv;
338 };
339
340 struct in_connected
341 {
342   guint16       peer_id;
343   guint16       resv;
344   guint32       speed;
345   guint16       win_size;
346   guint16       delay;
347   guint32       frame;
348 };
349
350 struct clear_req
351 {
352   guint16       call_id;
353   guint16       resv;
354 };
355
356 struct disc_notify
357 {
358   guint16       call_id;
359   guint8        result;
360   guint8        error;
361   guint16       cause;
362   guint16       resv;
363   guint8        stats[128];
364 };
365
366 struct error_notify
367 {
368   guint16       peer_id;
369   guint16       resv;
370   guint32       crc;
371   guint32       frame;
372   guint32       hardware;
373   guint32       buffer;
374   guint32       timeout;
375   guint32       alignment;
376 };
377
378 struct set_link
379 {
380   guint16       peer_id;
381   guint16       resv;
382   guint32       send_acm;
383   guint32       recv_acm;
384 };
385
386 static void
387 dissect_pptp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
388
389   struct pptp_hdr *     hdr = (struct pptp_hdr *)(pd + offset);
390   guint16               len;
391   guint16               cntrl_type;
392
393   OLD_CHECK_DISPLAY_AS_DATA(proto_pptp, pd, offset, fd, tree);
394
395   if (check_col(fd, COL_PROTOCOL))
396     col_set_str(fd, COL_PROTOCOL, "PPTP");
397   
398   len        = pntohs(&hdr->len);
399   cntrl_type = pntohs(&hdr->cntrl_type);
400
401   if (check_col(fd, COL_INFO))
402     col_add_fstr(fd, COL_INFO, "%s", cntrltype2str(cntrl_type));
403     
404   if (IS_DATA_IN_FRAME(offset) && tree) {
405     guint16             msg_type;
406     guint32             cookie;
407     proto_item *        ti;
408     proto_tree *        pptp_tree;
409
410     ti = proto_tree_add_item(tree, proto_pptp, NullTVB, offset, len, FALSE);
411     pptp_tree = proto_item_add_subtree(ti, ett_pptp);
412     
413     proto_tree_add_text(pptp_tree, NullTVB, offset, sizeof(hdr->len), 
414                         "Length: %u", len);
415     offset += sizeof(hdr->len);
416
417     msg_type = pntohs(&hdr->type);
418     proto_tree_add_uint_format(pptp_tree, hf_pptp_message_type, NullTVB,
419                                offset, sizeof(hdr->type), 
420                                msg_type,
421                                "Message type: %s (%u)", 
422                                msgtype2str(msg_type), msg_type);
423     
424     offset += sizeof(hdr->type);
425
426     cookie = pntohl(&hdr->cookie);
427
428     if (cookie == MAGIC_COOKIE)
429       proto_tree_add_text(pptp_tree, NullTVB, offset, sizeof(hdr->cookie),
430                           "Cookie: %#08x (correct)", cookie);
431     else
432       proto_tree_add_text(pptp_tree, NullTVB, offset, sizeof(hdr->cookie),
433                           "Cookie: %#08x (incorrect)", cookie);
434     offset += sizeof(hdr->cookie);
435     
436     proto_tree_add_text(pptp_tree, NullTVB, offset, sizeof(hdr->cntrl_type),
437                         "Control type: %s (%u)", cntrltype2str(cntrl_type), cntrl_type);
438     offset += sizeof(hdr->cntrl_type);
439
440     proto_tree_add_text(pptp_tree, NullTVB, offset, sizeof(hdr->resv),
441                         "Reserved: %u", pntohs(&hdr->resv));
442     offset += sizeof(hdr->resv);
443
444     if (cntrl_type < NUM_CNTRL_TYPES)
445       ( *(strfuncs[cntrl_type].func))(pd, offset, fd, pptp_tree);
446     else
447       old_dissect_data(pd, offset, fd, pptp_tree);
448   }
449 }
450
451 static void
452 dissect_unknown(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
453   old_dissect_data(pd, offset, fd, tree);
454 }
455
456 static void
457 dissect_cntrl_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
458
459   struct cntrl_req *    hdr = (struct cntrl_req *)(pd + offset);
460   guint32               frame;
461   guint32               bearer;
462   
463   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->major_ver) + sizeof(hdr->minor_ver), 
464                       "Protocol version: %u.%u", hdr->major_ver, hdr->minor_ver );
465   offset += sizeof(hdr->major_ver) + sizeof(hdr->minor_ver);
466
467   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
468                       "Reserved: %u", pntohs(&hdr->resv));
469   offset += sizeof(hdr->resv);
470
471   frame = pntohl(&hdr->frame);
472   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->frame),
473                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
474   offset += sizeof(hdr->frame);
475
476   bearer = pntohl(&hdr->bearer);
477   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->bearer),
478                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
479   offset += sizeof(hdr->bearer);
480
481   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->max_chan),
482                       "Maximum channels: %u", pntohs(&hdr->max_chan));
483   offset += sizeof(hdr->max_chan);
484   
485   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->firm_rev),
486                       "Firmware revision: %u", pntohs(&hdr->firm_rev));
487   offset += sizeof(hdr->firm_rev);
488   
489   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->host),
490                       "Hostname: %s", hdr->host);
491   offset += sizeof(hdr->host);
492   
493   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->vendor),
494                       "Vendor: %s", hdr->vendor);
495 }
496
497 static void
498 dissect_cntrl_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
499   struct cntrl_reply *  hdr = (struct cntrl_reply *)(pd + offset);
500   guint32               frame;
501   guint32               bearer;
502
503   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->major_ver) + sizeof(hdr->minor_ver), 
504                       "Protocol version: %u.%u", hdr->major_ver, hdr->minor_ver );
505   offset += sizeof(hdr->major_ver) + sizeof(hdr->minor_ver);
506
507   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
508                       "Result: %s (%u)", cntrlresulttype2str(hdr->result), hdr->result);
509   offset += sizeof(hdr->result);
510   
511   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
512                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
513   offset += sizeof(hdr->error);
514   
515   frame = pntohl(&hdr->frame);
516   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->frame),
517                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
518   offset += sizeof(hdr->frame);
519
520   bearer = pntohl(&hdr->bearer);
521   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->bearer),
522                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
523   offset += sizeof(hdr->bearer);
524
525   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->max_chan),
526                       "Maximum channels: %u", pntohs(&hdr->max_chan));
527   offset += sizeof(hdr->max_chan);
528   
529   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->firm_rev),
530                       "Firmware revision: %u", pntohs(&hdr->firm_rev));
531   offset += sizeof(hdr->firm_rev);
532   
533   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->host),
534                       "Hostname: %s", hdr->host);
535   offset += sizeof(hdr->host);
536   
537   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->vendor),
538                       "Vendor: %s", hdr->vendor);
539 }
540
541 static void
542 dissect_stop_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
543   struct stop_req *     hdr = (struct stop_req *)(pd + offset);
544   
545   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->reason),
546                       "Reason: %s (%u)", reasontype2str(hdr->reason), hdr->reason);
547   offset += sizeof(hdr->reason);
548   
549   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv0),
550                       "Reserved: %u", hdr->resv0);
551   offset += sizeof(hdr->resv0);
552   
553   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv1),
554                       "Reserved: %u", pntohs(&hdr->resv1));
555   offset += sizeof(hdr->resv1);
556 }
557
558 static void
559 dissect_stop_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
560   struct stop_reply *   hdr = (struct stop_reply *)(pd + offset);
561   
562   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
563                       "Result: %s (%u)", stopresulttype2str(hdr->result), hdr->result);
564   offset += sizeof(hdr->result);
565   
566   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
567                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
568   offset += sizeof(hdr->error);
569   
570   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
571                       "Reserved: %u", pntohs(&hdr->resv));
572   offset += sizeof(hdr->resv);
573 }
574
575 static void
576 dissect_echo_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
577   struct echo_req *     hdr = (struct echo_req *)(pd + offset);
578   
579   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->ident),
580                       "Identifier: %u", pntohl(&hdr->ident));
581   offset += sizeof(hdr->ident);
582 }
583
584 static void
585 dissect_echo_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
586   struct echo_reply *   hdr = (struct echo_reply *)(pd + offset);
587   
588   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->ident),
589                       "Identifier: %u", pntohl(&hdr->ident));
590   offset += sizeof(hdr->ident);
591   
592   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
593                       "Result: %s (%u)", echoresulttype2str(hdr->result), hdr->result);
594   offset += sizeof(hdr->result);
595   
596   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
597                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
598   offset += sizeof(hdr->error);
599   
600   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
601                       "Reserved: %u", pntohs(&hdr->resv));
602   offset += sizeof(hdr->resv);
603 }
604
605 static void
606 dissect_out_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
607   struct out_req *      hdr = (struct out_req *)(pd + offset);
608   guint32               bearer;
609   guint32               frame;
610   
611   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
612                       "Call ID: %u", pntohs(&hdr->call_id));
613   offset += sizeof(hdr->call_id);
614   
615   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_serial),
616                       "Call Serial Number: %u", pntohs(&hdr->call_serial));
617   offset += sizeof(hdr->call_serial);
618   
619   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->min_bps),
620                       "Minimum BPS: %u", pntohl(&hdr->min_bps));
621   offset += sizeof(hdr->min_bps);
622   
623   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->max_bps),
624                       "Maximum BPS: %u", pntohl(&hdr->max_bps));
625   offset += sizeof(hdr->max_bps);
626   
627   bearer = pntohl(&hdr->bearer);
628   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->bearer),
629                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
630   offset += sizeof(hdr->bearer);
631
632   frame = pntohl(&hdr->frame);
633   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->frame),
634                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
635   offset += sizeof(hdr->frame);
636
637   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->win_size),
638                       "Receive window size: %u", pntohs(&hdr->win_size));
639   offset += sizeof(hdr->win_size);
640
641   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->delay),
642                       "Processing delay: %u", pntohs(&hdr->delay));
643   offset += sizeof(hdr->delay);
644   
645   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->phone_len),
646                       "Phone number length: %u", pntohs(&hdr->phone_len));
647   offset += sizeof(hdr->phone_len);
648   
649   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
650                       "Reserved: %u", pntohs(&hdr->resv));
651   offset += sizeof(hdr->resv);
652   
653   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->phone),
654                       "Phone number: %s", hdr->phone);
655   offset += sizeof(hdr->phone);
656
657   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->subaddr),
658                       "Subaddress: %s", hdr->subaddr);
659   offset += sizeof(hdr->subaddr);
660 }
661
662 static void
663 dissect_out_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
664   struct out_reply *    hdr = (struct out_reply *)(pd + offset);
665
666   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
667                       "Call ID: %u", pntohs(&hdr->call_id));
668   offset += sizeof(hdr->call_id);
669   
670   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->peer_id),
671                       "Peer's call ID: %u", pntohs(&hdr->peer_id));
672   offset += sizeof(hdr->peer_id);
673
674   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
675                       "Result: %s (%u)", outresulttype2str(hdr->result), hdr->result);
676   offset += sizeof(hdr->result);
677   
678   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
679                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
680   offset += sizeof(hdr->error);
681
682   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->cause),
683                       "Cause code: %u", pntohs(&hdr->cause));
684   offset += sizeof(hdr->cause);
685   
686   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->speed),
687                       "Connect speed: %u", pntohl(&hdr->speed));
688   offset += sizeof(hdr->speed);
689
690   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->win_size),
691                       "Receive window size: %u", pntohs(&hdr->win_size));
692   offset += sizeof(hdr->win_size);
693
694   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->delay),
695                       "Processing delay: %u", pntohs(&hdr->delay));
696   offset += sizeof(hdr->delay);
697   
698   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->channel_id),
699                       "Physical channel ID: %u", pntohl(&hdr->channel_id));
700   offset += sizeof(hdr->channel_id);
701 }
702
703
704 static void
705 dissect_in_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
706   struct in_req *       hdr = (struct in_req *)(pd + offset);
707   guint32               bearer;
708   
709   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
710                       "Call ID: %u", pntohs(&hdr->call_id));
711   offset += sizeof(hdr->call_id);
712   
713   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_serial),
714                       "Call serial number: %u", pntohs(&hdr->call_serial));
715   offset += sizeof(hdr->call_serial);
716   
717   bearer = pntohl(&hdr->bearer);
718   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->bearer),
719                       "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
720   offset += sizeof(hdr->bearer);
721
722   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->channel_id),
723                       "Physical channel ID: %u", pntohl(&hdr->channel_id));
724   offset += sizeof(hdr->channel_id);
725
726   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->dialed_len),
727                       "Dialed number length: %u", pntohs(&hdr->dialed_len));
728   offset += sizeof(hdr->dialed_len);
729   
730   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->dialing_len),
731                       "Dialing number length: %u", pntohs(&hdr->dialing_len));
732   offset += sizeof(hdr->dialing_len);
733   
734   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->dialed),
735                       "Dialed number: %s", hdr->dialed);
736   offset += sizeof(hdr->dialed);
737   
738   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->dialing),
739                       "Dialing number: %s", hdr->dialing);
740   offset += sizeof(hdr->dialing);
741   
742   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->subaddr),
743                       "Subaddress: %s", hdr->subaddr);
744   offset += sizeof(hdr->subaddr);
745 }
746
747 static void
748 dissect_in_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
749   struct in_reply *     hdr = (struct in_reply *)(pd + offset);
750   
751   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
752                       "Call ID: %u", pntohs(&hdr->call_id));
753   offset += sizeof(hdr->call_id);
754   
755   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->peer_id),
756                       "Peer's call ID: %u", pntohs(&hdr->peer_id));
757   offset += sizeof(hdr->peer_id);
758
759   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
760                       "Result: %s (%u)", inresulttype2str(hdr->result), hdr->result);
761   offset += sizeof(hdr->result);
762   
763   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
764                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
765   offset += sizeof(hdr->error);
766
767   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->win_size),
768                       "Receive window size: %u", pntohs(&hdr->win_size));
769   offset += sizeof(hdr->win_size);
770
771   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->delay),
772                       "Processing delay: %u", pntohs(&hdr->delay));
773   offset += sizeof(hdr->delay);
774   
775   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
776                       "Reserved: %u", hdr->resv);
777   offset += sizeof(hdr->resv);
778 }
779
780 static void
781 dissect_in_connected(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
782   struct in_connected * hdr = (struct in_connected *)(pd + offset);
783   guint32               frame;
784   
785   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->peer_id),
786                       "Peer's call ID: %u", pntohs(&hdr->peer_id));
787   offset += sizeof(hdr->peer_id);
788
789   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
790                       "Reserved: %u", pntohs(&hdr->resv));
791   offset += sizeof(hdr->resv);
792
793   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->speed),
794                       "Connect speed: %u", pntohl(&hdr->speed));
795   offset += sizeof(hdr->speed);
796   
797   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->win_size),
798                       "Receive window size: %u", pntohs(&hdr->win_size));
799   offset += sizeof(hdr->win_size);
800
801   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->delay),
802                       "Processing delay: %u", pntohs(&hdr->delay));
803   offset += sizeof(hdr->delay);
804   
805   frame = pntohl(&hdr->frame);
806   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->frame),
807                       "Framing capabilities: %s (%u)", frametype2str(frame), frame);
808   offset += sizeof(hdr->frame);
809 }
810
811 static void
812 dissect_clear_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
813   struct clear_req *    hdr = (struct clear_req *)(pd + offset);
814   
815   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
816                       "Call ID: %u", pntohs(&hdr->call_id));
817   offset += sizeof(hdr->call_id);
818
819   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
820                       "Reserved: %u", pntohs(&hdr->resv));
821   offset += sizeof(hdr->resv);
822 }
823
824 static void
825 dissect_disc_notify(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
826   struct disc_notify *  hdr = (struct disc_notify *)(pd + offset);
827   
828   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->call_id),
829                       "Call ID: %u", pntohs(&hdr->call_id));
830   offset += sizeof(hdr->call_id);
831
832   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->result),
833                       "Result: %s (%u)", discresulttype2str(hdr->result), hdr->result);
834   offset += sizeof(hdr->result);
835   
836   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->error),
837                       "Error: %s (%u)", errortype2str(hdr->error), hdr->error);
838   offset += sizeof(hdr->error);
839
840   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->cause),
841                       "Cause code: %u", pntohs(&hdr->cause));
842   offset += sizeof(hdr->cause);
843   
844   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
845                       "Reserved: %u", pntohs(&hdr->resv));
846   offset += sizeof(hdr->resv);
847
848   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->stats),
849                       "Call statistics: %s", hdr->stats);
850   offset += sizeof(hdr->stats);
851 }
852
853 static void
854 dissect_error_notify(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
855   struct error_notify * hdr = (struct error_notify *)(pd + offset);
856   
857   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->peer_id),
858                       "Peer's call ID: %u", pntohs(&hdr->peer_id));
859   offset += sizeof(hdr->peer_id);
860
861   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
862                       "Reserved: %u", pntohs(&hdr->resv));
863   offset += sizeof(hdr->resv);
864
865   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->crc),
866                       "CRC errors: %u", pntohl(&hdr->crc));
867   offset += sizeof(hdr->crc);
868   
869   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->frame),
870                       "Framing errors: %u", pntohl(&hdr->frame));
871   offset += sizeof(hdr->frame);
872   
873   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->hardware),
874                       "Hardware overruns: %u", pntohl(&hdr->hardware));
875   offset += sizeof(hdr->hardware);
876   
877   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->buffer),
878                       "Buffer overruns: %u", pntohl(&hdr->buffer));
879   offset += sizeof(hdr->buffer);
880   
881   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->timeout),
882                       "Time-out errors: %u", pntohl(&hdr->timeout));
883   offset += sizeof(hdr->timeout);
884   
885   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->alignment),
886                       "Alignment errors: %u", pntohl(&hdr->alignment));
887   offset += sizeof(hdr->alignment);
888 }
889
890 static void
891 dissect_set_link(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
892   struct set_link *     hdr = (struct set_link *)(pd + offset);
893   
894   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->peer_id),
895                       "Peer's call ID: %u", pntohs(&hdr->peer_id));
896   offset += sizeof(hdr->peer_id);
897
898   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->resv),
899                       "Reserved: %u", pntohs(&hdr->resv));
900   offset += sizeof(hdr->resv);
901
902   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->send_acm),
903                       "Send ACCM: %#08x", pntohl(&hdr->send_acm));
904   offset += sizeof(hdr->send_acm);
905   
906   proto_tree_add_text(tree, NullTVB, offset, sizeof(hdr->recv_acm),
907                       "Recv ACCM: %#08x", pntohl(&hdr->recv_acm));
908   offset += sizeof(hdr->recv_acm);
909 }
910
911 void
912 proto_register_pptp(void)
913 {
914   static gint *ett[] = {
915     &ett_pptp,
916   };
917
918   static hf_register_info hf[] = {
919     { &hf_pptp_message_type,
920       { "Message Type",                 "pptp.type",
921         FT_UINT16,      BASE_HEX,       NULL,   0x0,
922         "PPTP message type" }}
923   };
924
925   proto_pptp = proto_register_protocol("Point-to-Point Tunnelling Protocol",
926                                        "pptp");
927   proto_register_field_array(proto_pptp, hf, array_length(hf));
928   proto_register_subtree_array(ett, array_length(ett));
929 }
930
931 void
932 proto_reg_handoff_pptp(void)
933 {
934   old_dissector_add("tcp.port", TCP_PORT_PPTP, dissect_pptp);
935 }