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