proto_registrar_get_nth(hfinfo->id) == hfinfo, so use the latter rather
[obnox/wireshark/wip.git] / packet-ppp.c
1 /* packet-ppp.c
2  * Routines for ppp packet disassembly
3  *
4  * $Id: packet-ppp.c,v 1.90 2002/04/14 23:04:03 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  *
9  * This file created and by Mike Hall <mlh@io.com>
10  * Copyright 1998
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 <string.h>
36 #include <glib.h>
37 #include "prefs.h"
38 #include <epan/packet.h>
39 #include "packet-ppp.h"
40 #include "ppptypes.h"
41 #include "etypes.h"
42 #include <epan/atalk-utils.h>
43 #include "packet-chdlc.h"
44 #include "packet-ip.h"
45 #include "packet-ipx.h"
46 #include "packet-vines.h"
47 #include "nlpid.h"
48
49 #define ppp_min(a, b)  ((a<b) ? a : b)
50
51 static int proto_ppp = -1;
52 static int hf_ppp_address = -1;
53 static int hf_ppp_control = -1;
54 static int hf_ppp_protocol = -1;
55
56 static gint ett_ppp = -1;
57
58 static int proto_lcp = -1;
59
60 static gint ett_lcp = -1;
61 static gint ett_lcp_options = -1;
62 static gint ett_lcp_authprot_opt = -1;
63 static gint ett_lcp_qualprot_opt = -1;
64 static gint ett_lcp_fcs_alternatives_opt = -1;
65 static gint ett_lcp_numbered_mode_opt = -1;
66 static gint ett_lcp_callback_opt = -1;
67 static gint ett_lcp_multilink_ep_disc_opt = -1;
68 static gint ett_lcp_internationalization_opt = -1;
69
70 static int proto_ipcp = -1;
71
72 static gint ett_ipcp = -1;
73 static gint ett_ipcp_options = -1;
74 static gint ett_ipcp_ipaddrs_opt = -1;
75 static gint ett_ipcp_compressprot_opt = -1;
76
77 static int proto_ccp = -1;
78
79 static gint ett_ccp = -1;
80 static gint ett_ccp_options = -1;
81 static gint ett_ccp_stac_opt = -1;
82 static gint ett_ccp_mppc_opt = -1;
83 static gint ett_ccp_bsdcomp_opt = -1;
84 static gint ett_ccp_lzsdcp_opt = -1;
85 static gint ett_ccp_mvrca_opt = -1;
86 static gint ett_ccp_deflate_opt = -1;
87
88 static int proto_cbcp = -1;
89
90 static gint ett_cbcp = -1;
91 static gint ett_cbcp_options = -1;
92 static gint ett_cbcp_callback_opt = -1;
93 static gint ett_cbcp_callback_opt_addr = -1;
94
95 static int proto_bacp = -1;
96
97 static gint ett_bacp = -1;
98 static gint ett_bacp_options = -1;
99 static gint ett_bacp_favored_peer_opt = -1;
100
101 static int proto_bap = -1;
102
103 static gint ett_bap = -1;
104 static gint ett_bap_options = -1;
105 static gint ett_bap_link_type_opt = -1;
106 static gint ett_bap_phone_delta_opt = -1;
107 static gint ett_bap_phone_delta_subopt = -1;
108 static gint ett_bap_call_status_opt = -1;
109
110 static int proto_comp_data = -1;
111
112 static gint ett_comp_data = -1;
113
114 static int proto_pppmuxcp = -1;
115
116 static gint ett_pppmuxcp = -1;
117 static gint ett_pppmuxcp_options = -1;
118
119 static int proto_pppmux = -1;
120
121 static gint ett_pppmux = -1;
122 static gint ett_pppmux_subframe = -1;
123 static gint ett_pppmux_subframe_hdr = -1;
124 static gint ett_pppmux_subframe_flags = -1;
125 static gint ett_pppmux_subframe_info = -1;
126
127 static int proto_mp = -1;
128 static int hf_mp_frag_first = -1;
129 static int hf_mp_frag_last = -1;
130 static int hf_mp_sequence_num = -1;
131
132 static int ett_mp = -1;
133 static int ett_mp_flags = -1;
134
135 static int proto_pap                    = -1;           /* PAP vars */
136 static gint ett_pap                     = -1;
137 static gint ett_pap_data                = -1;
138 static gint ett_pap_peer_id             = -1;
139 static gint ett_pap_password            = -1;
140 static gint ett_pap_message             = -1;
141
142 static int proto_chap                   = -1;           /* CHAP vars */
143 static gint ett_chap                    = -1;
144 static gint ett_chap_data               = -1;
145 static gint ett_chap_value              = -1;
146 static gint ett_chap_name               = -1;
147 static gint ett_chap_message            = -1;
148
149 static dissector_table_t subdissector_table;
150 static dissector_handle_t chdlc_handle;
151 static dissector_handle_t data_handle;
152
153 /* options */
154 static gint ppp_fcs_decode = 0; /* 0 = No FCS, 1 = 16 bit FCS, 2 = 32 bit FCS */
155 #define NO_FCS 0
156 #define FCS_16 1
157 #define FCS_32 2
158 gboolean ppp_vj_decomp = TRUE; /* Default to VJ header decompression */
159                                 
160 /*
161  * For Default Protocol ID negotiated with PPPMuxCP. We need to
162  * this ID so that if the first subframe doesn't have protocol
163  * ID, we can use it
164  */
165
166 static guint pppmux_def_prot_id = 0;
167
168 /* PPP definitions */
169
170 static const value_string ppp_vals[] = {
171         {PPP_IP,        "IP"             },
172         {PPP_OSI,       "OSI"            },
173         {PPP_AT,        "Appletalk"      },
174         {PPP_IPX,       "Netware IPX/SPX"},
175         {PPP_VJC_COMP,  "VJ compressed TCP"},
176         {PPP_VJC_UNCOMP,"VJ uncompressed TCP"},
177         {PPP_BPDU,      "Bridging PDU"},
178         {PPP_VINES,     "Vines"          },
179         {PPP_MP,        "Multilink"},
180         {PPP_IPV6,      "IPv6"           },
181         {PPP_MUX,       "PPP Multiplexing"},
182         {PPP_COMP,      "compressed packet" },
183         {PPP_DEC_LB,    "DEC LANBridge100 Spanning Tree"},
184         {PPP_MPLS_UNI,  "MPLS Unicast"},
185         {PPP_MPLS_MULTI, "MPLS Multicast"},
186         {PPP_IPCP,      "IP Control Protocol" },
187         {PPP_OSICP,     "OSI Control Protocol" },
188         {PPP_ATCP,      "AppleTalk Control Protocol" },
189         {PPP_IPXCP,     "IPX Control Protocol" },
190         {PPP_MUXCP,     "PPPMux Control Protocol"},
191         {PPP_CCP,       "Compression Control Protocol" },
192         {PPP_LCP,       "Link Control Protocol" },
193         {PPP_PAP,       "Password Authentication Protocol"  },
194         {PPP_LQR,       "Link Quality Report protocol" },
195         {PPP_SPAP,      "Shiva Password Authentication Protocol" },
196         {PPP_CHAP,      "Cryptographic Handshake Auth. Protocol" },
197         {PPP_EAP,       "Extensible Authentication Protocol" },
198         {PPP_CBCP,      "Callback Control Protocol" },
199         {PPP_BACP,      "Bandwidth Allocation Control Protocol" },
200         {PPP_BAP,       "Bandwitdh Allocation Protocol" },
201         {0,             NULL            }
202 };
203
204 /* CP (LCP, IPCP, etc.) codes.
205  * from pppd fsm.h 
206  */
207 #define CONFREQ    1  /* Configuration Request */
208 #define CONFACK    2  /* Configuration Ack */
209 #define CONFNAK    3  /* Configuration Nak */
210 #define CONFREJ    4  /* Configuration Reject */
211 #define TERMREQ    5  /* Termination Request */
212 #define TERMACK    6  /* Termination Ack */
213 #define CODEREJ    7  /* Code Reject */
214
215 static const value_string cp_vals[] = {
216         {CONFREQ,    "Configuration Request" },
217         {CONFACK,    "Configuration Ack" },
218         {CONFNAK,    "Configuration Nak" },
219         {CONFREJ,    "Configuration Reject" },
220         {TERMREQ,    "Termination Request" },
221         {TERMACK,    "Termination Ack" },
222         {CODEREJ,    "Code Reject" },
223         {0,          NULL            } };
224
225 /*
226  * LCP-specific packet types.
227  */
228 #define PROTREJ    8  /* Protocol Reject */
229 #define ECHOREQ    9  /* Echo Request */
230 #define ECHOREP    10 /* Echo Reply */
231 #define DISCREQ    11 /* Discard Request */
232 #define IDENT      12 /* Identification */
233 #define TIMEREMAIN 13 /* Time remaining */
234
235 /* 
236  * CCP-specific packet types.
237  */
238 #define RESETREQ   14  /* Reset Request */
239 #define RESETACK   15  /* Reset Ack */
240
241 /*
242  * CBCP-specific packet types.
243  */
244 #define CBREQ      1  /* Callback Request */
245 #define CBRES      2  /* Callback Response */
246 #define CBACK      3  /* Callback Ack */
247
248 #define CBCP_OPT  6 /* Use callback control protocol */
249
250 /*
251  * BAP-specific packet types.
252  */
253 #define BAP_CREQ   1  /* Call Request */
254 #define BAP_CRES   2  /* Call Response */
255 #define BAP_CBREQ  3  /* Callback Request */
256 #define BAP_CBRES  4  /* Callback Response */
257 #define BAP_LDQREQ 5  /* Link Drop Query Request */
258 #define BAP_LDQRES 6  /* Link Drop Query Response */
259 #define BAP_CSI    7  /* Call Status Indication */
260 #define BAP_CSRES  8  /* Call Status Response */
261
262 static const value_string lcp_vals[] = {
263         {CONFREQ,    "Configuration Request" },
264         {CONFACK,    "Configuration Ack" },
265         {CONFNAK,    "Configuration Nak" },
266         {CONFREJ,    "Configuration Reject" },
267         {TERMREQ,    "Termination Request" },
268         {TERMACK,    "Termination Ack" },
269         {CODEREJ,    "Code Reject" },
270         {PROTREJ,    "Protocol Reject" },
271         {ECHOREQ,    "Echo Request" },
272         {ECHOREP,    "Echo Reply" },
273         {DISCREQ,    "Discard Request" },
274         {IDENT,      "Identification" },
275         {TIMEREMAIN, "Time Remaining" },
276         {0,          NULL }
277 };
278
279 static const value_string ccp_vals[] = {
280         {CONFREQ,    "Configuration Request" },
281         {CONFACK,    "Configuration Ack" },
282         {CONFNAK,    "Configuration Nak" },
283         {CONFREJ,    "Configuration Reject" },
284         {TERMREQ,    "Termination Request" },
285         {TERMACK,    "Termination Ack" },
286         {CODEREJ,    "Code Reject" },
287         {RESETREQ,   "Reset Request" },
288         {RESETACK,   "Reset Ack" },
289         {0,          NULL } 
290 };
291
292 static const value_string cbcp_vals[] = {
293         {CBREQ,      "Callback Request" },
294         {CBRES,      "Callback Response" },
295         {CBACK,      "Callback Ack" },
296         {0,          NULL } 
297 };
298
299 static const value_string bap_vals[] = {
300         {BAP_CREQ,      "Call Request" },
301         {BAP_CRES,      "Call Response" },
302         {BAP_CBREQ,     "Callback Request" },
303         {BAP_CBRES,     "Callback Response" },
304         {BAP_LDQREQ,    "Link Drop Query Request" },
305         {BAP_LDQRES,    "Link Drop Query Response" },
306         {BAP_CSI,       "Call Status Indication" },
307         {BAP_CSRES,     "Call Status Response" },
308         {0,             NULL }
309 };
310
311 #define BAP_RESP_CODE_REQACK    0x00
312 #define BAP_RESP_CODE_REQNAK    0x01
313 #define BAP_RESP_CODE_REQREJ    0x02
314 #define BAP_RESP_CODE_REQFULLNAK        0x03
315 static const value_string bap_resp_code_vals[] = {
316         {BAP_RESP_CODE_REQACK,  "Request Ack" },
317         {BAP_RESP_CODE_REQNAK,  "Request Nak" },
318         {BAP_RESP_CODE_REQREJ,  "Request Rej" },
319         {BAP_RESP_CODE_REQFULLNAK,      "Request Full Nak" },
320         {0,                     NULL }
321 };
322
323 #define BAP_LINK_TYPE_ISDN      0       /* ISDN */
324 #define BAP_LINK_TYPE_X25       1       /* X.25 */
325 #define BAP_LINK_TYPE_ANALOG    2       /* Analog */
326 #define BAP_LINK_TYPE_SD        3       /* Switched Digital (non-ISDN) */
327 #define BAP_LINK_TYPE_ISDNOV    4       /* ISDN data over voice */
328 #define BAP_LINK_TYPE_RESV5     5       /* Reserved */
329 #define BAP_LINK_TYPE_RESV6     6       /* Reserved */
330 #define BAP_LINK_TYPE_RESV7     7       /* Reserved */
331 static const value_string bap_link_type_vals[] = {
332         {BAP_LINK_TYPE_ISDN,    "ISDN" },
333         {BAP_LINK_TYPE_X25,     "X.25" },
334         {BAP_LINK_TYPE_ANALOG,  "Analog" },
335         {BAP_LINK_TYPE_SD,      "Switched Digital (non-ISDN)" },
336         {BAP_LINK_TYPE_ISDNOV,  "ISDN data over voice" },
337         {BAP_LINK_TYPE_RESV5,   "Reserved" },
338         {BAP_LINK_TYPE_RESV6,   "Reserved" },
339         {BAP_LINK_TYPE_RESV7,   "Reserved" },
340         {0,                     NULL }
341 };
342
343 #define BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT       1       /* Unique Digit */
344 #define BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM        2       /* Subscriber Number */
345 #define BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR 3 /* Phone Number Sub Address */
346 static const value_string bap_phone_delta_subopt_vals[] = {
347         {BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT,     "Unique Digit" },
348         {BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM,      "Subscriber Number" },
349         {BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR, "Phone Number Sub Address" },
350         {0,                                     NULL }
351 };
352
353 /*
354  * Cause codes for Cause.
355  *
356  * The following code table is taken from packet-q931.c but is slightly 
357  * adapted to BAP protocol.
358  */
359 static const value_string q931_cause_code_vals[] = {
360         { 0x00, "Call successful" },
361         { 0x01, "Unallocated (unassigned) number" },
362         { 0x02, "No route to specified transit network" },
363         { 0x03, "No route to destination" },
364         { 0x04, "Send special information tone" },
365         { 0x05, "Misdialled trunk prefix" },
366         { 0x06, "Channel unacceptable" },
367         { 0x07, "Call awarded and being delivered in an established channel" },
368         { 0x08, "Prefix 0 dialed but not allowed" },
369         { 0x09, "Prefix 1 dialed but not allowed" },
370         { 0x0A, "Prefix 1 dialed but not required" },
371         { 0x0B, "More digits received than allowed, call is proceeding" },
372         { 0x10, "Normal call clearing" },
373         { 0x11, "User busy" },
374         { 0x12, "No user responding" },
375         { 0x13, "No answer from user (user alerted)" },
376         { 0x14, "Subscriber absent" },
377         { 0x15, "Call rejected" },
378         { 0x16, "Number changed" },
379         { 0x17, "Reverse charging rejected" },
380         { 0x18, "Call suspended" },
381         { 0x19, "Call resumed" },
382         { 0x1A, "Non-selected user clearing" },
383         { 0x1B, "Destination out of order" },
384         { 0x1C, "Invalid number format (incomplete number)" },
385         { 0x1D, "Facility rejected" },
386         { 0x1E, "Response to STATUS ENQUIRY" },
387         { 0x1F, "Normal unspecified" },
388         { 0x21, "Circuit out of order" },
389         { 0x22, "No circuit/channel available" },
390         { 0x23, "Destination unattainable" },
391         { 0x25, "Degraded service" },
392         { 0x26, "Network out of order" },
393         { 0x27, "Transit delay range cannot be achieved" },
394         { 0x28, "Throughput range cannot be achieved" },
395         { 0x29, "Temporary failure" },
396         { 0x2A, "Switching equipment congestion" },
397         { 0x2B, "Access information discarded" },
398         { 0x2C, "Requested circuit/channel not available" },
399         { 0x2D, "Pre-empted" },
400         { 0x2E, "Precedence call blocked" },
401         { 0x2F, "Resources unavailable, unspecified" },
402         { 0x31, "Quality of service unavailable" },
403         { 0x32, "Requested facility not subscribed" },
404         { 0x33, "Reverse charging not allowed" },
405         { 0x34, "Outgoing calls barred" },
406         { 0x35, "Outgoing calls barred within CUG" },
407         { 0x36, "Incoming calls barred" },
408         { 0x37, "Incoming calls barred within CUG" },
409         { 0x38, "Call waiting not subscribed" },
410         { 0x39, "Bearer capability not authorized" },
411         { 0x3A, "Bearer capability not presently available" },
412         { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
413         { 0x3F, "Service or option not available, unspecified" },
414         { 0x41, "Bearer capability not implemented" },
415         { 0x42, "Channel type not implemented" },
416         { 0x43, "Transit network selection not implemented" },
417         { 0x44, "Message not implemented" },
418         { 0x45, "Requested facility not implemented" },
419         { 0x46, "Only restricted digital information bearer capability is available" },
420         { 0x4F, "Service or option not implemented, unspecified" },
421         { 0x51, "Invalid call reference value" },
422         { 0x52, "Identified channel does not exist" },
423         { 0x53, "Call identity does not exist for suspended call" },
424         { 0x54, "Call identity in use" },
425         { 0x55, "No call suspended" },
426         { 0x56, "Call having the requested call identity has been cleared" },
427         { 0x57, "Called user not member of CUG" },
428         { 0x58, "Incompatible destination" },
429         { 0x59, "Non-existent abbreviated address entry" },
430         { 0x5A, "Destination address missing, and direct call not subscribed" },
431         { 0x5B, "Invalid transit network selection (national use)" },
432         { 0x5C, "Invalid facility parameter" },
433         { 0x5D, "Mandatory information element is missing" },
434         { 0x5F, "Invalid message, unspecified" },
435         { 0x60, "Mandatory information element is missing" },
436         { 0x61, "Message type non-existent or not implemented" },
437         { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
438         { 0x63, "Information element nonexistant or not implemented" },
439         { 0x64, "Invalid information element contents" },
440         { 0x65, "Message not compatible with call state" },
441         { 0x66, "Recovery on timer expiry" },
442         { 0x67, "Parameter non-existent or not implemented - passed on" },
443         { 0x6E, "Message with unrecognized parameter discarded" },
444         { 0x6F, "Protocol error, unspecified" },
445         { 0x7F, "Internetworking, unspecified" },
446         { 0xFF, "Non-specific failure" },
447         { 0,    NULL }
448 };
449
450 static const value_string bap_call_status_opt_action_vals[] = {
451         {0,     "No retry" },
452         {1,     "Retry" },
453         {0,     NULL }
454 };
455
456 #define STAC_CM_NONE            0
457 #define STAC_CM_LCB             1
458 #define STAC_CM_CRC             2
459 #define STAC_CM_SN              3
460 #define STAC_CM_EXTMODE         4
461 static const value_string stac_checkmode_vals[] = {
462         {STAC_CM_NONE,          "None" },
463         {STAC_CM_LCB,           "LCB" },
464         {STAC_CM_CRC,           "CRC" },
465         {STAC_CM_SN,            "Sequence Number" },
466         {STAC_CM_EXTMODE,       "Extended Mode" },
467         {0,                     NULL }
468 };
469
470 #define LZSDCP_CM_NONE          0
471 #define LZSDCP_CM_LCB           1
472 #define LZSDCP_CM_SN            2
473 #define LZSDCP_CM_SN_LCB        3
474 static const value_string lzsdcp_checkmode_vals[] = {
475         {LZSDCP_CM_NONE,        "None" },
476         {LZSDCP_CM_LCB,         "LCB" },
477         {LZSDCP_CM_SN,          "Sequence Number" },
478         {LZSDCP_CM_SN_LCB,      "Sequence Number + LCB" },
479         {0,                     NULL }
480 };
481
482 #define LZSDCP_PM_NONE          0
483 #define LZSDCP_PM_PROC_UNCOMP   1
484 static const value_string lzsdcp_processmode_vals[] = {
485         {LZSDCP_PM_NONE,        "None" },
486         {LZSDCP_PM_PROC_UNCOMP, "Process-Uncompressed" },
487         {0,                     NULL }
488 };
489
490 /*
491  * Options.  (LCP)
492  */
493 #define CI_MRU                  1       /* Maximum Receive Unit */
494 #define CI_ASYNCMAP             2       /* Async Control Character Map */
495 #define CI_AUTHTYPE             3       /* Authentication Type */
496 #define CI_QUALITY              4       /* Quality Protocol */
497 #define CI_MAGICNUMBER          5       /* Magic Number */
498 #define CI_PCOMPRESSION         7       /* Protocol Field Compression */
499 #define CI_ACCOMPRESSION        8       /* Address/Control Field Compression */
500 #define CI_FCS_ALTERNATIVES     9       /* FCS Alternatives (RFC 1570) */
501 #define CI_SELF_DESCRIBING_PAD  10      /* Self-Describing Pad (RFC 1570) */
502 #define CI_NUMBERED_MODE        11      /* Numbered Mode (RFC 1663) */
503 #define CI_CALLBACK             13      /* Callback (RFC 1570) */
504 #define CI_COMPOUND_FRAMES      15      /* Compound frames (RFC 1570) */
505 #define CI_MULTILINK_MRRU       17      /* Multilink MRRU (RFC 1717) */
506 #define CI_MULTILINK_SSNH       18      /* Multilink Short Sequence Number
507                                            Header (RFC 1717) */
508 #define CI_MULTILINK_EP_DISC    19      /* Multilink Endpoint Discriminator
509                                            (RFC 1717) */
510 #define CI_DCE_IDENTIFIER       21      /* DCE Identifier */
511 #define CI_MULTILINK_PLUS_PROC  22      /* Multilink Plus Procedure */
512 #define CI_LINK_DISC_FOR_BACP   23      /* Link Discriminator for BACP
513                                            (RFC 2125) */
514 #define CI_LCP_AUTHENTICATION   24      /* LCP Authentication Option */
515 #define CI_COBS                 25      /* Consistent Overhead Byte
516                                            Stuffing */
517 #define CI_PREFIX_ELISION       26      /* Prefix elision */
518 #define CI_MULTILINK_HDR_FMT    27      /* Multilink header format */
519 #define CI_INTERNATIONALIZATION 28      /* Internationalization (RFC 2484) */
520 #define CI_SDL_ON_SONET_SDH     29      /* Simple Data Link on SONET/SDH */
521
522 static void dissect_lcp_mru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
523                         int offset, guint length, packet_info *pinfo,
524                         proto_tree *tree);
525 static void dissect_lcp_async_map_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
526                         int offset, guint length, packet_info *pinfo,
527                         proto_tree *tree);
528 static void dissect_lcp_protocol_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
529                         int offset, guint length, packet_info *pinfo,
530                         proto_tree *tree);
531 static void dissect_lcp_authprot_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
532                         int offset, guint length, packet_info *pinfo,
533                         proto_tree *tree);
534 static void dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp,
535                         tvbuff_t *tvb, int offset, guint length,
536                         packet_info *pinfo, proto_tree *tree);
537 static void dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp,
538                         tvbuff_t *tvb, int offset, guint length,
539                         packet_info *pinfo, proto_tree *tree);
540 static void dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp,
541                         tvbuff_t *tvb, int offset, guint length,
542                         packet_info *pinfo, proto_tree *tree);
543 static void dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp,
544                         tvbuff_t *tvb, int offset, guint length,
545                         packet_info *pinfo, proto_tree *tree);
546 static void dissect_lcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
547                         int offset, guint length, packet_info *pinfo,
548                         proto_tree *tree);
549 static void dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp,
550                         tvbuff_t *tvb, int offset, guint length,
551                         packet_info *pinfo, proto_tree *tree);
552 static void dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp,
553                         tvbuff_t *tvb, int offset, guint length,
554                         packet_info *pinfo, proto_tree *tree);
555 static void dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp,
556                         tvbuff_t *tvb, int offset, guint length,
557                         packet_info *pinfo, proto_tree *tree);
558 static void dissect_lcp_internationalization_opt(const ip_tcp_opt *optp,
559                         tvbuff_t *tvb, int offset, guint length,
560                         packet_info *pinfo, proto_tree *tree);
561 static void dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
562
563 static const ip_tcp_opt lcp_opts[] = {
564         {
565                 CI_MRU,
566                 "Maximum Receive Unit",
567                 NULL,
568                 FIXED_LENGTH,
569                 4,
570                 dissect_lcp_mru_opt
571         },
572         {
573                 CI_ASYNCMAP,
574                 "Async Control Character Map",
575                 NULL,
576                 FIXED_LENGTH,
577                 6,
578                 dissect_lcp_async_map_opt
579         },
580         {
581                 CI_AUTHTYPE,
582                 "Authentication protocol",
583                 &ett_lcp_authprot_opt,
584                 VARIABLE_LENGTH,
585                 4,
586                 dissect_lcp_authprot_opt
587         },
588         {
589                 CI_QUALITY,
590                 "Quality protocol",
591                 &ett_lcp_qualprot_opt,
592                 VARIABLE_LENGTH,
593                 4,
594                 dissect_lcp_protocol_opt
595         },
596         {
597                 CI_MAGICNUMBER,
598                 "Magic number",
599                 NULL,
600                 FIXED_LENGTH,
601                 6,
602                 dissect_lcp_magicnumber_opt
603         },
604         {
605                 CI_PCOMPRESSION,
606                 "Protocol field compression",
607                 NULL,
608                 FIXED_LENGTH,
609                 2,
610                 NULL
611         },
612         {
613                 CI_ACCOMPRESSION,
614                 "Address/control field compression",
615                 NULL,
616                 FIXED_LENGTH,
617                 2,
618                 NULL
619         },
620         {
621                 CI_FCS_ALTERNATIVES,
622                 "FCS alternatives",
623                 &ett_lcp_fcs_alternatives_opt,
624                 FIXED_LENGTH,
625                 3,
626                 dissect_lcp_fcs_alternatives_opt
627         },
628         {
629                 CI_SELF_DESCRIBING_PAD,
630                 "Maximum octets of self-describing padding",
631                 NULL,
632                 FIXED_LENGTH,
633                 3,
634                 dissect_lcp_self_describing_pad_opt
635         },
636         {
637                 CI_NUMBERED_MODE,
638                 "Numbered mode",
639                 &ett_lcp_numbered_mode_opt,
640                 VARIABLE_LENGTH,
641                 4,
642                 dissect_lcp_numbered_mode_opt
643         },
644         {
645                 CI_CALLBACK,
646                 "Callback",
647                 &ett_lcp_callback_opt,
648                 VARIABLE_LENGTH,
649                 3,
650                 dissect_lcp_callback_opt,
651         },
652         {
653                 CI_COMPOUND_FRAMES,
654                 "Compound frames",
655                 NULL,
656                 FIXED_LENGTH,
657                 2,
658                 NULL
659         },
660         {
661                 CI_MULTILINK_MRRU,
662                 "Multilink MRRU",
663                 NULL,
664                 FIXED_LENGTH,
665                 4,
666                 dissect_lcp_multilink_mrru_opt
667         },
668         {
669                 CI_MULTILINK_SSNH,
670                 "Use short sequence number headers",
671                 NULL,
672                 FIXED_LENGTH,
673                 2,
674                 NULL
675         },
676         {
677                 CI_MULTILINK_EP_DISC,
678                 "Multilink endpoint discriminator",
679                 &ett_lcp_multilink_ep_disc_opt,
680                 VARIABLE_LENGTH,
681                 3,
682                 dissect_lcp_multilink_ep_disc_opt,
683         },
684         {
685                 CI_DCE_IDENTIFIER,
686                 "DCE identifier",
687                 NULL,
688                 VARIABLE_LENGTH,
689                 2,
690                 NULL
691         },
692         {
693                 CI_MULTILINK_PLUS_PROC,
694                 "Multilink Plus Procedure",
695                 NULL,
696                 VARIABLE_LENGTH,
697                 2,
698                 NULL
699         },
700         {
701                 CI_LINK_DISC_FOR_BACP,
702                 "Link discriminator for BAP",
703                 NULL,
704                 FIXED_LENGTH,
705                 4,
706                 dissect_lcp_bap_link_discriminator_opt
707         },
708         {
709                 CI_LCP_AUTHENTICATION,
710                 "LCP authentication",
711                 NULL,
712                 VARIABLE_LENGTH,
713                 2,
714                 NULL
715         },
716         {
717                 CI_COBS,
718                 "Consistent Overhead Byte Stuffing",
719                 NULL,
720                 VARIABLE_LENGTH,
721                 2,
722                 NULL
723         },
724         {
725                 CI_PREFIX_ELISION,
726                 "Prefix elision",
727                 NULL,
728                 VARIABLE_LENGTH,
729                 2,
730                 NULL
731         },
732         {
733                 CI_MULTILINK_HDR_FMT,
734                 "Multilink header format",
735                 NULL,
736                 VARIABLE_LENGTH,
737                 2,
738                 NULL
739         },
740         {
741                 CI_INTERNATIONALIZATION,
742                 "Internationalization",
743                 &ett_lcp_internationalization_opt,
744                 VARIABLE_LENGTH,
745                 7,
746                 dissect_lcp_internationalization_opt
747         },
748         {
749                 CI_SDL_ON_SONET_SDH,
750                 "Simple data link on SONET/SDH",
751                 NULL,
752                 VARIABLE_LENGTH,
753                 2,
754                 NULL
755         }
756 };
757
758 #define N_LCP_OPTS      (sizeof lcp_opts / sizeof lcp_opts[0])
759
760 /* 
761  * CHAP Algorithms
762  */
763 #define CHAP_ALG_MD5    0x05    /* CHAP with MD5 */
764 #define CHAP_ALG_MSV1   0x80    /* MS-CHAPv1 */
765 #define CHAP_ALG_MSV2   0x81    /* MS-CHAPv2 */
766
767 static const value_string chap_alg_vals[] = {
768         {CHAP_ALG_MD5,  "CHAP with MD5" },
769         {CHAP_ALG_MSV1, "MS-CHAP" },
770         {CHAP_ALG_MSV2, "MS-CHAP-2" },
771         {0,             NULL }
772 };
773
774
775 /*
776  * Options.  (IPCP)
777  */
778 #define CI_ADDRS        1       /* IP Addresses (deprecated) (RFC 1172) */
779 #define CI_COMPRESSTYPE 2       /* Compression Type (RFC 1332) */
780 #define CI_ADDR         3       /* IP Address (RFC 1332) */
781 #define CI_MOBILE_IPv4  4       /* Mobile IPv4 (RFC 2290) */
782 #define CI_MS_DNS1      129     /* Primary DNS value (RFC 1877) */
783 #define CI_MS_WINS1     130     /* Primary WINS value (RFC 1877) */
784 #define CI_MS_DNS2      131     /* Secondary DNS value (RFC 1877) */
785 #define CI_MS_WINS2     132     /* Secondary WINS value (RFC 1877) */
786
787 static void dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
788                         int offset, guint length, packet_info *pinfo,
789                         proto_tree *tree);
790 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
791                         int offset, guint length, packet_info *pinfo,
792                         proto_tree *tree);
793
794 static const ip_tcp_opt ipcp_opts[] = {
795         {
796                 CI_ADDRS,
797                 "IP addresses (deprecated)",
798                 &ett_ipcp_ipaddrs_opt,
799                 FIXED_LENGTH,
800                 10,
801                 dissect_ipcp_addrs_opt
802         },
803         {
804                 CI_COMPRESSTYPE,
805                 "IP compression protocol",
806                 &ett_ipcp_compressprot_opt,
807                 VARIABLE_LENGTH,
808                 4,
809                 dissect_lcp_protocol_opt
810         },
811         {
812                 CI_ADDR,
813                 "IP address",
814                 NULL,
815                 FIXED_LENGTH,
816                 6,
817                 dissect_ipcp_addr_opt
818         },
819         {
820                 CI_MOBILE_IPv4,
821                 "Mobile node's home IP address",
822                 NULL,
823                 FIXED_LENGTH,
824                 6,
825                 dissect_ipcp_addr_opt
826         },
827         {
828                 CI_MS_DNS1,
829                 "Primary DNS server IP address",
830                 NULL,
831                 FIXED_LENGTH,
832                 6,
833                 dissect_ipcp_addr_opt
834         },
835         {
836                 CI_MS_WINS1,
837                 "Primary WINS server IP address",
838                 NULL,
839                 FIXED_LENGTH,
840                 6,
841                 dissect_ipcp_addr_opt
842         },
843         {
844                 CI_MS_DNS2,
845                 "Secondary DNS server IP address",
846                 NULL,
847                 FIXED_LENGTH,
848                 6,
849                 dissect_ipcp_addr_opt
850         },
851         {
852                 CI_MS_WINS2,
853                 "Secondary WINS server IP address",
854                 NULL,
855                 FIXED_LENGTH,
856                 6,
857                 dissect_ipcp_addr_opt
858         }
859 };
860
861 #define N_IPCP_OPTS     (sizeof ipcp_opts / sizeof ipcp_opts[0])
862
863 /*
864  * Options.  (CCP)
865  */
866 #define CI_CCP_OUI      0       /* OUI (RFC1962) */
867 #define CI_CCP_PREDICT1 1       /* Predictor type 1 (RFC1962) */
868 #define CI_CCP_PREDICT2 2       /* Predictor type 2 (RFC1962) */
869 #define CI_CCP_PUDDLE   3       /* Puddle Jumper (RFC1962) */
870 #define CI_CCP_HPPPC    16      /* Hewlett-Packard PPC (RFC1962) */
871 #define CI_CCP_STAC     17      /* stac Electronics LZS (RFC1974) */
872 #define CI_CCP_MPPC     18      /* Microsoft PPC (RFC2218/3078) */
873 #define CI_CCP_GFZA     19      /* Gandalf FZA (RFC1962) */
874 #define CI_CCP_V42BIS   20      /* V.42bis compression */
875 #define CI_CCP_BSDLZW   21      /* BSD LZW Compress (RFC1977) */
876 #define CI_CCP_LZSDCP   23      /* LZS-DCP (RFC1967) */
877 #define CI_CCP_MVRCA    24      /* MVRCA (Magnalink) (RFC1975) */
878 #define CI_CCP_DEFLATE  26      /* Deflate (RFC1979) */
879 #define CI_CCP_RESERVED 255     /* Reserved (RFC1962) */
880
881 /*
882  * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE) 
883  * supported bits.
884  */
885 #define MPPC_SUPPORTED_BITS_C   0x00000001      /* MPPC negotiation */
886 #define MPPE_SUPPORTED_BITS_D   0x00000010      /* Obsolete */
887 #define MPPE_SUPPORTED_BITS_L   0x00000020      /* 40-bit encryption */
888 #define MPPE_SUPPORTED_BITS_S   0x00000040      /* 128-bit encryption */
889 #define MPPE_SUPPORTED_BITS_M   0x00000080      /* 56-bit encryption */
890 #define MPPE_SUPPORTED_BITS_H   0x01000000      /* stateless mode */
891
892 static void dissect_ccp_stac_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
893                         int offset, guint length, packet_info *pinfo,
894                         proto_tree *tree);
895
896 static void dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
897                         int offset, guint length, packet_info *pinfo,
898                         proto_tree *tree);
899
900 static void dissect_ccp_bsdcomp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
901                         int offset, guint length, packet_info *pinfo,
902                         proto_tree *tree);
903
904 static void dissect_ccp_lzsdcp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
905                         int offset, guint length, packet_info *pinfo,
906                         proto_tree *tree);
907
908 static void dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
909                         int offset, guint length, packet_info *pinfo,
910                         proto_tree *tree);
911
912 static void dissect_ccp_deflate_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
913                         int offset, guint length, packet_info *pinfo,
914                         proto_tree *tree);
915
916 static const ip_tcp_opt ccp_opts[] = {
917         {
918                 CI_CCP_STAC,
919                 "Stac Electronics LZS",
920                 &ett_ccp_stac_opt,
921                 VARIABLE_LENGTH,
922                 5,
923                 /* In RFC 1974, this is a fixed-length field of size 5,
924                    but in Ascend Proprietary STAC compression this field
925                    is 6 octets. Sigh... */
926                 dissect_ccp_stac_opt
927         },
928         {
929                 CI_CCP_MPPC,
930                 "Microsoft PPC",
931                 &ett_ccp_mppc_opt,
932                 FIXED_LENGTH,
933                 6,
934                 dissect_ccp_mppc_opt
935         },
936         {
937                 CI_CCP_BSDLZW,
938                 "BSD Compress",
939                 &ett_ccp_bsdcomp_opt,
940                 FIXED_LENGTH,
941                 3,
942                 dissect_ccp_bsdcomp_opt
943         },
944         {
945                 CI_CCP_LZSDCP,
946                 "LZS-DCP",
947                 &ett_ccp_lzsdcp_opt,
948                 FIXED_LENGTH,
949                 6,
950                 dissect_ccp_lzsdcp_opt
951         },
952         {
953                 CI_CCP_MVRCA,
954                 "MVRCA (Magnalink)",
955                 &ett_ccp_mvrca_opt,
956                 FIXED_LENGTH,
957                 4,
958                 dissect_ccp_mvrca_opt
959         },
960         {
961                 CI_CCP_DEFLATE,
962                 "Deflate",
963                 &ett_ccp_deflate_opt,
964                 FIXED_LENGTH,
965                 4,   /* RFC1979 says the length is 3 but it's actually 4. */
966                 dissect_ccp_deflate_opt
967         },
968 };
969
970 #define N_CCP_OPTS      (sizeof ccp_opts / sizeof ccp_opts[0])
971
972 /*
973  * Options.  (CBCP)
974  */
975 #define CI_CBCP_NO_CALLBACK     1  /* No callback */
976 #define CI_CBCP_CB_USER         2  /* Callback to a user-specified number */
977 #define CI_CBCP_CB_PRE          3  /* Callback to a pre-specified or 
978                                             administrator specified number */
979 #define CI_CBCP_CB_ANY          4  /* Callback to any of a list of numbers */
980
981 static void dissect_cbcp_no_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
982                         int offset, guint length, packet_info *pinfo,
983                         proto_tree *tree);
984
985 static void dissect_cbcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
986                         int offset, guint length, packet_info *pinfo,
987                         proto_tree *tree);
988
989 static const ip_tcp_opt cbcp_opts[] = {
990         {
991                 CI_CBCP_NO_CALLBACK,
992                 "No callback",
993                 NULL,
994                 FIXED_LENGTH,
995                 2,
996                 dissect_cbcp_no_callback_opt
997         },
998         {
999                 CI_CBCP_CB_USER,
1000                 "Callback to a user-specified number",
1001                 &ett_cbcp_callback_opt,
1002                 VARIABLE_LENGTH,
1003                 4,
1004                 dissect_cbcp_callback_opt
1005         },
1006         {
1007                 CI_CBCP_CB_PRE,
1008                 "Callback to a pre-specified or admin-specified number",
1009                 &ett_cbcp_callback_opt,
1010                 FIXED_LENGTH,
1011                 3,
1012                 dissect_cbcp_callback_opt
1013         },
1014         {
1015                 CI_CBCP_CB_ANY,
1016                 "Callback to any of a list of numbers",
1017                 &ett_cbcp_callback_opt,
1018                 VARIABLE_LENGTH,
1019                 4,
1020                 dissect_cbcp_callback_opt
1021         }
1022
1023 };
1024
1025 #define N_CBCP_OPTS     (sizeof cbcp_opts / sizeof cbcp_opts[0])
1026
1027 /*
1028  * Options.  (BACP)
1029  */
1030 #define CI_BACP_FAVORED_PEER    1  /* Favored-Peer */
1031
1032 static void dissect_bacp_favored_peer_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1033                         int offset, guint length, packet_info *pinfo,
1034                         proto_tree *tree);
1035
1036 static const ip_tcp_opt bacp_opts[] = {
1037         {
1038                 CI_BACP_FAVORED_PEER,
1039                 "Favored-Peer",
1040                 &ett_bacp_favored_peer_opt,
1041                 FIXED_LENGTH,
1042                 6,
1043                 dissect_bacp_favored_peer_opt
1044         }
1045 };
1046
1047 #define N_BACP_OPTS     (sizeof bacp_opts / sizeof bacp_opts[0])
1048
1049 /*
1050  * Options.  (BAP)
1051  */
1052 #define CI_BAP_LINK_TYPE        1  /* Link Type */
1053 #define CI_BAP_PHONE_DELTA      2  /* Phone-Delta */
1054 #define CI_BAP_NO_PHONE_NUM_NEEDED      3  /* No Phone Number Needed */
1055 #define CI_BAP_REASON           4  /* Reason */
1056 #define CI_BAP_LINK_DISC        5  /* Link Discriminator */
1057 #define CI_BAP_CALL_STATUS      6  /* Call Status */
1058
1059 static void dissect_bap_link_type_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1060                         int offset, guint length, packet_info *pinfo,
1061                         proto_tree *tree);
1062
1063 static void dissect_bap_phone_delta_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1064                         int offset, guint length, packet_info *pinfo,
1065                         proto_tree *tree);
1066
1067 static void dissect_bap_link_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1068                         int offset, guint length, packet_info *pinfo,
1069                         proto_tree *tree);
1070
1071 static void dissect_bap_reason_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1072                         int offset, guint length, packet_info *pinfo,
1073                         proto_tree *tree);
1074
1075 static void dissect_bap_call_status_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1076                         int offset, guint length, packet_info *pinfo,
1077                         proto_tree *tree);
1078
1079 static const ip_tcp_opt bap_opts[] = {
1080         {
1081                 CI_BAP_LINK_TYPE,
1082                 "Link Type",
1083                 &ett_bap_link_type_opt,
1084                 FIXED_LENGTH,
1085                 5,
1086                 dissect_bap_link_type_opt
1087         },
1088         {
1089                 CI_BAP_PHONE_DELTA,
1090                 "Phone Delta",
1091                 &ett_bap_phone_delta_opt,
1092                 VARIABLE_LENGTH,
1093                 4,
1094                 dissect_bap_phone_delta_opt
1095         },
1096         {
1097                 CI_BAP_NO_PHONE_NUM_NEEDED,
1098                 "No Phone Number Needed",
1099                 NULL,
1100                 FIXED_LENGTH,
1101                 2,
1102                 NULL
1103         },
1104         {
1105                 CI_BAP_REASON,
1106                 "Reason",
1107                 NULL,
1108                 VARIABLE_LENGTH,
1109                 2,
1110                 dissect_bap_reason_opt
1111         },
1112         {
1113                 CI_BAP_LINK_DISC,
1114                 "Link Discriminator",
1115                 NULL,
1116                 FIXED_LENGTH,
1117                 4,
1118                 dissect_bap_link_disc_opt
1119         },
1120         {
1121                 CI_BAP_CALL_STATUS,
1122                 "Call Status",
1123                 &ett_bap_call_status_opt,
1124                 FIXED_LENGTH,
1125                 4,
1126                 dissect_bap_call_status_opt
1127         }
1128 };
1129
1130 #define N_BAP_OPTS      (sizeof bap_opts / sizeof bap_opts[0])
1131
1132 static void dissect_ppp(tvbuff_t *tvb, packet_info *pinfo, 
1133     proto_tree *tree);
1134
1135 static const value_string pap_vals[] = {
1136         {CONFREQ,    "Authenticate-Request" },
1137         {CONFACK,    "Authenticate-Ack" },
1138         {CONFNAK,    "Authenticate-Nak" },
1139         {0,          NULL            } };
1140
1141 static void dissect_pap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1142
1143 #define CHAP_CHAL  1  /* CHAP Challenge */
1144 #define CHAP_RESP  2  /* CHAP Response */
1145 #define CHAP_SUCC  3  /* CHAP Success */
1146 #define CHAP_FAIL  4  /* CHAP Failure */
1147
1148 static const value_string chap_vals[] = {
1149         {CHAP_CHAL,  "Challenge" },
1150         {CHAP_RESP,  "Response" },
1151         {CHAP_SUCC,  "Success" },
1152         {CHAP_FAIL,  "Failure" },
1153         {0,          NULL            } };
1154
1155 static void dissect_chap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1156
1157 static const value_string pppmuxcp_vals[] = {
1158         {CONFREQ,    "Configuration Request" },
1159         {CONFACK,    "Configuration Ack" },
1160         {0,          NULL}
1161 };
1162
1163 /*
1164  * PPPMuxCP options
1165  */
1166
1167 #define CI_DEFAULT_PID   1
1168
1169 static void dissect_pppmuxcp_def_pid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1170                         int offset, guint length, packet_info *pinfo, proto_tree *tree);
1171
1172
1173 static const ip_tcp_opt pppmuxcp_opts[] = {
1174         {
1175                 CI_DEFAULT_PID,
1176                 "Default Protocol ID",
1177                 NULL,
1178                 FIXED_LENGTH,
1179                 4,
1180                 dissect_pppmuxcp_def_pid_opt
1181         }
1182 };
1183
1184 #define N_PPPMUXCP_OPTS (sizeof pppmuxcp_opts / sizeof pppmuxcp_opts[0])
1185
1186 static const unsigned int fcstab_32[256] =
1187       {
1188       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
1189       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
1190       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1191       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
1192       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1193       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1194       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
1195       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
1196       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1197       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1198       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
1199       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1200       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
1201       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
1202       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1203       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
1204       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
1205       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1206       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
1207       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1208       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1209       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
1210       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
1211       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1212       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1213       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
1214       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1215       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
1216       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
1217       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1218       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
1219       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
1220       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1221       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
1222       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1223       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1224       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
1225       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
1226       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1227       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1228       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
1229       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1230       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
1231       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
1232       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1233       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
1234       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
1235       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1236       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
1237       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1238       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1239       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
1240       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
1241       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1242       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1243       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
1244       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1245       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
1246       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
1247       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1248       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
1249       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
1250       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1251       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1252       };
1253
1254 static const unsigned short fcstab_16[256] = {
1255         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1256         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1257         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1258         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1259         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1260         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1261         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1262         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1263         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1264         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1265         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1266         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1267         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1268         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1269         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1270         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1271         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1272         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1273         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1274         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1275         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1276         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1277         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1278         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1279         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1280         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1281         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1282         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1283         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1284         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1285         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1286         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1287     };
1288   
1289 /*
1290 *******************************************************************************
1291 * DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data.
1292 *******************************************************************************
1293 */
1294 static guint16
1295 fcs16(register guint16 fcs,
1296          tvbuff_t * tvbuff,
1297          guint32 offset,
1298          guint32 len)
1299 {
1300     guint8 val;
1301
1302     /* Check for Invalid Length */
1303     if (len == 0)
1304         return (0x0000);
1305     while (len--) {
1306         val = tvb_get_guint8(tvbuff, offset++);
1307         fcs = (guint16)((fcs >> 8) & 0x00ff) ^
1308             fcstab_16[((guint16)(fcs ^ (guint16)((val) & 0x00ff)) & 0x00ff)];
1309     }
1310
1311     return (fcs ^ 0xffff);
1312 }
1313   
1314 /*
1315 *******************************************************************************
1316 * DETAILS : Calculate a new FCS-32 given the current FCS-32 and the new data.
1317 *******************************************************************************
1318 */
1319 static guint32
1320 fcs32(guint32 fcs,
1321          tvbuff_t * tvbuff,
1322          guint32 offset,
1323          guint32 len)
1324 {
1325     guint8 val;
1326
1327     /* Check for invalid Length */
1328     if (len == 0)
1329         return (0x00000000);
1330
1331     while (len--) {
1332         val = tvb_get_guint8(tvbuff, offset++);
1333         fcs = (((fcs) >> 8) ^ fcstab_32[((fcs) ^ (val)) & 0xff]);
1334     }
1335     return (fcs ^ 0xffffffff);
1336 }
1337
1338 void
1339 capture_ppp_hdlc( const u_char *pd, int offset, int len, packet_counts *ld ) {
1340   if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
1341     ld->other++;
1342     return;
1343   }
1344   if (pd[0] == CHDLC_ADDR_UNICAST || pd[0] == CHDLC_ADDR_MULTICAST) {
1345     capture_chdlc(pd, offset, len, ld);
1346     return;
1347   }
1348   if (!BYTES_ARE_IN_FRAME(offset, len, 4)) {
1349     ld->other++;
1350     return;
1351   }
1352   switch (pntohs(&pd[offset + 2])) {
1353     case PPP_IP:
1354       capture_ip(pd, offset + 4, len, ld);
1355       break;
1356     case PPP_IPX:
1357       capture_ipx(pd, offset + 4, len, ld);
1358       break;
1359     case PPP_VINES:
1360       capture_vines(pd, offset + 4, len, ld);
1361       break;
1362     default:
1363       ld->other++;
1364       break;
1365   }
1366 }
1367
1368 static void
1369 dissect_lcp_mru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
1370                         guint length, packet_info *pinfo _U_,
1371                         proto_tree *tree)
1372 {
1373   proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
1374                         tvb_get_ntohs(tvb, offset + 2));
1375 }
1376
1377 static void
1378 dissect_lcp_async_map_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
1379                         guint length, packet_info *pinfo _U_,
1380                         proto_tree *tree)
1381 {
1382   guint32 map;
1383   char *mapstr;
1384   static const char *ctrlchars[32] = {
1385     "NUL", "SOH",       "STX", "ETX",        "EOT",      "ENQ", "ACK", "BEL",
1386     "BS",  "HT",        "NL",  "VT",         "NP (FF)",  "CR",  "SO",  "SI",
1387     "DLE", "DC1 (XON)", "DC2", "DC3 (XOFF)", "DC4",      "NAK", "SYN", "ETB",
1388     "CAN", "EM",        "SUB", "ESC",        "FS",       "GS",  "RS",  "US"
1389   };
1390   char mapbuf[32*(10+2)+1];
1391   char *mapp;
1392   int i;
1393
1394   /*
1395    * XXX - walk through the map and show the characters to map?
1396    * Put them in a subtree of this item, and have the top-level item
1397    * either say "None", "All", or give a list of the characters?)
1398    */
1399   map = tvb_get_ntohl(tvb, offset + 2);
1400   if (map == 0x00000000)
1401     mapstr = "None";    /* don't map any control characters */
1402   else if (map == 0xffffffff)
1403     mapstr = "All";     /* map all control characters */
1404   else {
1405     /*
1406      * Show the names of the control characters being mapped.
1407      */
1408     mapp = &mapbuf[0];
1409     for (i = 0; i < 32; i++) {
1410       if (map & (1 << i)) {
1411         if (mapp != &mapbuf[0]) {
1412           strcpy(mapp, ", ");
1413           mapp += 2;
1414         }
1415         strcpy(mapp, ctrlchars[i]);
1416         mapp += strlen(ctrlchars[i]);
1417       }
1418     }
1419     mapstr = mapbuf;
1420   }
1421   proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%08x (%s)", optp->name,
1422                       map, mapstr);
1423 }
1424
1425 static void
1426 dissect_lcp_protocol_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
1427                         guint length, packet_info *pinfo _U_,
1428                         proto_tree *tree)
1429 {
1430   guint16 protocol;
1431   proto_item *tf;
1432   proto_tree *field_tree = NULL;
1433   
1434   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1435           optp->name, length, plurality(length, "", "s"));
1436   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1437   offset += 2;
1438   length -= 2;
1439   protocol = tvb_get_ntohs(tvb, offset);
1440   proto_tree_add_text(field_tree, tvb, offset, 2, "%s: %s (0x%02x)", optp->name,
1441                 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
1442   offset += 2;
1443   length -= 2;
1444   if (length > 0)
1445     proto_tree_add_text(field_tree, tvb, offset, length, "Data (%d byte%s)", length,
1446                         plurality(length, "", "s"));
1447 }
1448
1449 static void
1450 dissect_lcp_authprot_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
1451                          guint length, packet_info *pinfo _U_,
1452                          proto_tree *tree)
1453 {
1454   guint16 protocol;
1455   guint8 algorithm;
1456   proto_item *tf;
1457   proto_tree *field_tree = NULL;
1458   
1459   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1460           optp->name, length, plurality(length, "", "s"));
1461   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1462   offset += 2;
1463   length -= 2;
1464   protocol = tvb_get_ntohs(tvb, offset);
1465   proto_tree_add_text(field_tree, tvb, offset, 2, "%s: %s (0x%02x)", optp->name,
1466                 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
1467   offset += 2;
1468   length -= 2;
1469   if (length > 0) {
1470     if (protocol == PPP_CHAP) {
1471       algorithm = tvb_get_guint8(tvb, offset);
1472       proto_tree_add_text(field_tree, tvb, offset, length, 
1473                           "Algorithm: %s (0x%02x)", 
1474                           val_to_str(algorithm, chap_alg_vals, "Unknown"), 
1475                           algorithm);
1476       offset++;
1477     } else {
1478       proto_tree_add_text(field_tree, tvb, offset, length, "Data (%d byte%s)", length,
1479                         plurality(length, "", "s"));
1480     }
1481   }
1482 }
1483
1484 static void
1485 dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1486                         int offset, guint length, packet_info *pinfo _U_,
1487                         proto_tree *tree)
1488 {
1489   proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%08x", optp->name,
1490                         tvb_get_ntohl(tvb, offset + 2));
1491 }
1492
1493 static void
1494 dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1495                         int offset, guint length, packet_info *pinfo _U_,
1496                         proto_tree *tree)
1497 {
1498   proto_item *tf;
1499   proto_tree *field_tree = NULL;
1500   guint8 alternatives;
1501   
1502   alternatives = tvb_get_guint8(tvb, offset + 2);
1503   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%02x",
1504           optp->name, alternatives);
1505   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1506   offset += 2;
1507   if (alternatives & 0x1)
1508     proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
1509        decode_boolean_bitfield(alternatives, 0x1, 8, "Null FCS", NULL));
1510   if (alternatives & 0x2)
1511     proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
1512        decode_boolean_bitfield(alternatives, 0x2, 8, "CCITT 16-bit FCS", NULL));
1513   if (alternatives & 0x4)
1514     proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
1515        decode_boolean_bitfield(alternatives, 0x4, 8, "CCITT 32-bit FCS", NULL));
1516 }
1517
1518 static void
1519 dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1520                         int offset, guint length, packet_info *pinfo _U_,
1521                         proto_tree *tree)
1522 {
1523   proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
1524                         tvb_get_guint8(tvb, offset + 2));
1525 }
1526
1527 static void
1528 dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1529                         int offset, guint length, packet_info *pinfo _U_,
1530                         proto_tree *tree)
1531 {
1532   proto_item *tf;
1533   proto_tree *field_tree = NULL;
1534   
1535   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1536           optp->name, length, plurality(length, "", "s"));
1537   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1538   offset += 2;
1539   length -= 2;
1540   proto_tree_add_text(field_tree, tvb, offset, 1, "Window: %u",
1541                         tvb_get_guint8(tvb, offset));
1542   offset += 1;
1543   length -= 1;
1544   if (length > 0)
1545     proto_tree_add_text(field_tree, tvb, offset, length, "Address (%d byte%s)",
1546                         length, plurality(length, "", "s"));
1547 }
1548
1549 static const value_string callback_op_vals[] = {
1550         {0, "Location is determined by user authentication" },
1551         {1, "Message is dialing string" },
1552         {2, "Message is location identifier" },
1553         {3, "Message is E.164" },
1554         {4, "Message is distinguished name" },
1555         {5, "unassigned"},
1556         {6, "Location is determined during CBCP negotiation" },
1557         {0, NULL }
1558 };
1559
1560 static void
1561 dissect_lcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
1562                         guint length, packet_info *pinfo _U_,
1563                         proto_tree *tree)
1564 {
1565   proto_item *tf;
1566   proto_tree *field_tree = NULL;
1567   guint8 operation;
1568   
1569   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1570           optp->name, length, plurality(length, "", "s"));
1571   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1572   offset += 2;
1573   length -= 2;
1574   operation = tvb_get_guint8(tvb, offset);
1575   proto_tree_add_text(field_tree, tvb, offset, 1, "Operation: %s (0x%02x)",
1576                 val_to_str(operation, callback_op_vals, "Unknown"),
1577                 operation);
1578   offset += 1;
1579   length -= 1;
1580   if (length > 0)
1581     proto_tree_add_text(field_tree, tvb, offset, length, "Message (%d byte%s)",
1582                         length, plurality(length, "", "s"));
1583 }
1584
1585 static void
1586 dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1587                         int offset, guint length, packet_info *pinfo _U_,
1588                         proto_tree *tree)
1589 {
1590   proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
1591                         tvb_get_ntohs(tvb, offset + 2));
1592 }
1593
1594 #define CLASS_NULL                      0
1595 #define CLASS_LOCAL                     1
1596 #define CLASS_IP                        2
1597 #define CLASS_IEEE_802_1                3
1598 #define CLASS_PPP_MAGIC_NUMBER          4
1599 #define CLASS_PSDN_DIRECTORY_NUMBER     5
1600
1601 static const value_string multilink_ep_disc_class_vals[] = {
1602         {CLASS_NULL,                  "Null" },
1603         {CLASS_LOCAL,                 "Locally assigned address" },
1604         {CLASS_IP,                    "IP address" },
1605         {CLASS_IEEE_802_1,            "IEEE 802.1 globally assigned MAC address" },
1606         {CLASS_PPP_MAGIC_NUMBER,      "PPP magic-number block" },
1607         {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number" },
1608         {0,                           NULL }
1609 };
1610
1611 static void
1612 dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1613                         int offset, guint length, packet_info *pinfo _U_,
1614                         proto_tree *tree)
1615 {
1616   proto_item *tf;
1617   proto_tree *field_tree = NULL;
1618   guint8 ep_disc_class;
1619
1620   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1621           optp->name, length, plurality(length, "", "s"));
1622   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1623   offset += 2;
1624   length -= 2;
1625   ep_disc_class = tvb_get_guint8(tvb, offset);
1626   proto_tree_add_text(field_tree, tvb, offset, 1, "Class: %s (%u)",
1627                 val_to_str(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"),
1628                 ep_disc_class);
1629   offset += 1;
1630   length -= 1;
1631   if (length > 0) {
1632     switch (ep_disc_class) {
1633
1634     case CLASS_NULL:
1635       proto_tree_add_text(field_tree, tvb, offset, length,
1636                         "Address (%d byte%s), should have been empty",
1637                         length, plurality(length, "", "s"));
1638       break;
1639
1640     case CLASS_LOCAL:
1641       if (length > 20) {
1642         proto_tree_add_text(field_tree, tvb, offset, length,
1643                         "Address (%d byte%s), should have been <20",
1644                         length, plurality(length, "", "s"));
1645       } else {
1646         proto_tree_add_text(field_tree, tvb, offset, length,
1647                         "Address (%d byte%s)",
1648                         length, plurality(length, "", "s"));
1649       }
1650       break;
1651
1652     case CLASS_IP:
1653       if (length != 4) {
1654         proto_tree_add_text(field_tree, tvb, offset, length,
1655                         "Address (%d byte%s), should have been 4",
1656                         length, plurality(length, "", "s"));
1657       } else {
1658         proto_tree_add_text(field_tree, tvb, offset, length,
1659                         "Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1660       }
1661       break;
1662
1663     case CLASS_IEEE_802_1:
1664       if (length != 6) {
1665         proto_tree_add_text(field_tree, tvb, offset, length,
1666                         "Address (%d byte%s), should have been 6",
1667                         length, plurality(length, "", "s"));
1668       } else {
1669         proto_tree_add_text(field_tree, tvb, offset, length,
1670                         "Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6)));
1671       }
1672       break;
1673
1674     case CLASS_PPP_MAGIC_NUMBER:
1675       /* XXX - dissect as 32-bit magic numbers */
1676       if (length > 20) {
1677         proto_tree_add_text(field_tree, tvb, offset, length,
1678                         "Address (%d byte%s), should have been <20",
1679                         length, plurality(length, "", "s"));
1680       } else {
1681         proto_tree_add_text(field_tree, tvb, offset, length,
1682                         "Address (%d byte%s)",
1683                         length, plurality(length, "", "s"));
1684       }
1685       break;
1686
1687     case CLASS_PSDN_DIRECTORY_NUMBER:
1688       if (length > 15) {
1689         proto_tree_add_text(field_tree, tvb, offset, length,
1690                         "Address (%d byte%s), should have been <20",
1691                         length, plurality(length, "", "s"));
1692       } else {
1693         proto_tree_add_text(field_tree, tvb, offset, length,
1694                         "Address (%d byte%s)",
1695                         length, plurality(length, "", "s"));
1696       }
1697       break;
1698
1699     default:
1700       proto_tree_add_text(field_tree, tvb, offset, length,
1701                         "Address (%d byte%s)",
1702                         length, plurality(length, "", "s"));
1703       break;
1704     }
1705   }
1706 }
1707
1708 static void
1709 dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1710                         int offset, guint length, packet_info *pinfo _U_,
1711                         proto_tree *tree)
1712 {
1713   proto_tree_add_text(tree, tvb, offset, length,
1714                         "%s: 0x%04x", optp->name,
1715                         tvb_get_ntohs(tvb, offset + 2));
1716 }
1717
1718 /* Character set numbers from the IANA charset registry. */
1719 static const value_string charset_num_vals[] = {
1720         {105, "UTF-8" },
1721         {0,   NULL }
1722 };
1723
1724 static void
1725 dissect_lcp_internationalization_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1726                         int offset, guint length, packet_info *pinfo _U_,
1727                         proto_tree *tree)
1728 {
1729   proto_item *tf;
1730   proto_tree *field_tree = NULL;
1731   guint32 charset;
1732   
1733   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1734           optp->name, length, plurality(length, "", "s"));
1735   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1736   offset += 2;
1737   length -= 2;
1738   charset = tvb_get_ntohl(tvb, offset);
1739   proto_tree_add_text(field_tree, tvb, offset, 4, "Character set: %s (0x%04x)",
1740                 val_to_str(charset, charset_num_vals, "Unknown"),
1741                 charset);
1742   offset += 4;
1743   length -= 4;
1744   if (length > 0) {
1745     /* XXX - should be displayed as an ASCII string */
1746     proto_tree_add_text(field_tree, tvb, offset, length, "Language tag (%d byte%s)",
1747                         length, plurality(length, "", "s"));
1748   }
1749 }
1750
1751 static void
1752 dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1753                         int offset, guint length, packet_info *pinfo _U_,
1754                         proto_tree *tree)
1755 {
1756   proto_item *tf;
1757   proto_tree *field_tree = NULL;
1758   
1759   tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
1760           optp->name, length, plurality(length, "", "s"));
1761   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1762   offset += 2;
1763   length -= 2;
1764   proto_tree_add_text(field_tree, tvb, offset, 4,
1765                         "Source IP address: %s",
1766                         ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1767   offset += 4;
1768   length -= 4;
1769   proto_tree_add_text(field_tree, tvb, offset, 4,
1770                         "Destination IP address: %s",
1771                         ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1772 }
1773
1774 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1775                         int offset, guint length, packet_info *pinfo _U_,
1776                         proto_tree *tree)
1777 {
1778   proto_tree_add_text(tree, tvb, offset, length, "%s: %s", optp->name,
1779                         ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)));
1780 }
1781
1782 static void dissect_pppmuxcp_def_pid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1783                         int offset, guint length, packet_info *pinfo _U_,
1784                         proto_tree *tree)
1785
1786   pppmux_def_prot_id = tvb_get_ntohs(tvb, offset + 2);
1787   proto_tree_add_text(tree, tvb, offset + 2, length - 2, "%s: %s (0x%02x)",optp->name,
1788                       val_to_str(pppmux_def_prot_id, ppp_vals, "Unknown"), pppmux_def_prot_id);
1789 }
1790
1791
1792 static void
1793 dissect_ccp_stac_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1794                         int offset, guint length, packet_info *pinfo _U_,
1795                         proto_tree *tree)
1796 {
1797   proto_item *tf;
1798   proto_tree *field_tree;
1799   guint8 check_mode;
1800
1801   if (length == 6) {
1802     proto_tree_add_text(tree, tvb, offset, length, 
1803                         "%s (Ascend Proprietary version)", optp->name);
1804     /* We don't know how to decode the following 4 octets, since
1805        there's no public document that describe their usage. */
1806   } else {
1807     tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1808     field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1809
1810     proto_tree_add_text(field_tree, tvb, offset + 2, 2,
1811                         "History Count: %u", tvb_get_ntohs(tvb, offset + 2));
1812     check_mode = tvb_get_guint8(tvb, offset + 4);
1813     proto_tree_add_text(field_tree, tvb, offset + 4, 1,
1814                         "Check Mode: %s (0x%02X)", 
1815                         val_to_str(check_mode, stac_checkmode_vals, "Unknown"),
1816                         check_mode); 
1817   }
1818 }
1819
1820 static void
1821 dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1822                         int offset, guint length, packet_info *pinfo _U_,
1823                         proto_tree *tree)
1824 {
1825   proto_item *tf;
1826   proto_tree *flags_tree;
1827   guint32 supported_bits;
1828
1829   supported_bits = tvb_get_ntohl(tvb, offset + 2);
1830   tf = proto_tree_add_text(tree, tvb, offset, length, 
1831               "%s: Supported Bits: 0x%08X", optp->name, supported_bits);
1832   flags_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1833   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1834       decode_boolean_bitfield(supported_bits, MPPC_SUPPORTED_BITS_C, 8*4, 
1835       "Desire to negotiate MPPC", "NO Desire to negotiate MPPC"));
1836   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1837       decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_D, 8*4, 
1838       "Obsolete (should NOT be 1)", "Obsolete (should ALWAYS be 0)"));
1839   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1840       decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_L, 8*4, 
1841       "40-bit encryption ON", "40-bit encryption OFF"));
1842   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1843       decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_S, 8*4, 
1844       "128-bit encryption ON", "128-bit encryption OFF"));
1845   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1846       decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_M, 8*4, 
1847       "56-bit encryption ON", "56-bit encryption OFF"));
1848   proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
1849       decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_H, 8*4, 
1850       "Stateless mode ON", "Stateless mode OFF"));
1851 }
1852
1853 static void
1854 dissect_ccp_bsdcomp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1855                         int offset, guint length, packet_info *pinfo _U_,
1856                         proto_tree *tree)
1857 {
1858   proto_item *tf;
1859   proto_tree *field_tree;
1860
1861   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1862   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1863
1864   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1865                       "Version: %u", tvb_get_guint8(tvb, offset + 2) >> 5);
1866   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1867                       "Dict: %u bits", 
1868                       tvb_get_guint8(tvb, offset + 2) & 0x1f);
1869 }
1870
1871 static void
1872 dissect_ccp_lzsdcp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1873                         int offset, guint length, packet_info *pinfo _U_,
1874                         proto_tree *tree)
1875 {
1876   proto_item *tf;
1877   proto_tree *field_tree;
1878   guint8 check_mode;
1879   guint8 process_mode;
1880
1881   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1882   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1883
1884   proto_tree_add_text(field_tree, tvb, offset + 2, 2,
1885                       "History Count: %u", tvb_get_ntohs(tvb, offset + 2));
1886   check_mode = tvb_get_guint8(tvb, offset + 4);
1887   proto_tree_add_text(field_tree, tvb, offset + 4, 1,
1888                       "Check Mode: %s (0x%02X)", 
1889                       val_to_str(check_mode, lzsdcp_checkmode_vals, "Unknown"),
1890                       check_mode); 
1891   process_mode = tvb_get_guint8(tvb, offset + 5);
1892   proto_tree_add_text(field_tree, tvb, offset + 5, 1,
1893                       "Process Mode: %s (0x%02X)", 
1894                       val_to_str(process_mode, lzsdcp_processmode_vals, "Unkown"),
1895                       process_mode); 
1896 }
1897
1898 static void
1899 dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1900                         int offset, guint length, packet_info *pinfo _U_,
1901                         proto_tree *tree)
1902 {
1903   proto_item *tf;
1904   proto_tree *field_tree;
1905
1906   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1907   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1908
1909   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1910                       "Features: %u", tvb_get_guint8(tvb, offset + 2) >> 5);
1911   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1912                       "Packet by Packet flag: %s", 
1913                       tvb_get_guint8(tvb, offset + 2) & 0x20 ? "true" : "false");
1914   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1915                       "History: %u", tvb_get_guint8(tvb, offset + 2) & 0x20);
1916   proto_tree_add_text(field_tree, tvb, offset + 3, 1,
1917                       "Number of contexts: %u", tvb_get_guint8(tvb, offset + 3));
1918 }
1919
1920 static void
1921 dissect_ccp_deflate_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1922                         int offset, guint length, packet_info *pinfo _U_,
1923                         proto_tree *tree)
1924 {
1925   proto_item *tf;
1926   proto_tree *field_tree;
1927   guint8 method;
1928
1929   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1930   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1931
1932   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1933                       "Window: %u", hi_nibble(tvb_get_guint8(tvb, offset + 2)));
1934   method = lo_nibble(tvb_get_guint8(tvb, offset + 2));
1935   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1936                       "Method: %s (0x%02x)", 
1937                       method == 0x08 ?  "zlib compression" : "other", method);
1938   proto_tree_add_text(field_tree, tvb, offset + 3, 1,
1939                       "Sequence number check method: %u", 
1940                       tvb_get_guint8(tvb, offset + 2) & 0x03);
1941 }
1942
1943 static void
1944 dissect_cbcp_no_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1945                         int offset, guint length, packet_info *pinfo _U_,
1946                         proto_tree *tree)
1947 {
1948   proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1949 }
1950
1951 static void
1952 dissect_cbcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1953                         int offset, guint length, packet_info *pinfo _U_,
1954                         proto_tree *tree)
1955 {
1956   proto_item *tf;
1957   proto_tree *field_tree;
1958   proto_item *ta;
1959   proto_tree *addr_tree;
1960   guint8 addr_type;
1961   gint addr_len;
1962   guint8 buf[256];      /* Since length field in Callback Conf Option is
1963                            8 bits, 256-octet buf is large enough. */
1964   
1965   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
1966   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
1967
1968   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
1969                       "Callback delay: %u", tvb_get_guint8(tvb, offset + 2));
1970   offset += 3;
1971   length -= 3;
1972   
1973   while (length > 0) {
1974     ta = proto_tree_add_text(field_tree, tvb, offset, length, 
1975                              "Callback Address");
1976     addr_type = tvb_get_guint8(tvb, offset); 
1977     addr_tree = proto_item_add_subtree(tf, ett_cbcp_callback_opt_addr);
1978     proto_tree_add_text(addr_tree, tvb, offset, 1, 
1979                         "Address Type: %s (%u)", 
1980                         ((addr_type == 1) ? "PSTN/ISDN" : "Other"), addr_type);
1981     offset++;
1982     length--;
1983     addr_len = tvb_get_nstringz0(tvb, offset, sizeof(buf), buf);
1984     proto_tree_add_text(addr_tree, tvb, offset, addr_len + 1,
1985                         "Address: %s", buf);
1986     offset += (addr_len + 1);
1987     length -= (addr_len + 1);
1988   }
1989 }
1990
1991 static void
1992 dissect_bacp_favored_peer_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
1993                         int offset, guint length, packet_info *pinfo _U_,
1994                         proto_tree *tree)
1995 {
1996   proto_item *tf;
1997   proto_tree *field_tree;
1998
1999   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
2000   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2001
2002   proto_tree_add_text(field_tree, tvb, offset + 2, 4,
2003                       "Magic number: 0x%08x", tvb_get_ntohl(tvb, offset + 2));
2004 }
2005
2006 static void
2007 dissect_bap_link_type_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
2008                         int offset, guint length, packet_info *pinfo _U_,
2009                         proto_tree *tree)
2010 {
2011   proto_item *tf;
2012   proto_tree *field_tree;
2013   guint8 link_type;
2014
2015   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
2016   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2017
2018   proto_tree_add_text(field_tree, tvb, offset + 2, 2,
2019               "Link Speed: %u kbps", tvb_get_ntohs(tvb, offset + 2));
2020   link_type = tvb_get_guint8(tvb, offset + 4);
2021   proto_tree_add_text(field_tree, tvb, offset + 4, 1,
2022               "Link Type: %s (%u)", val_to_str(link_type, bap_link_type_vals,
2023                                                 "Unknown"), link_type);
2024 }
2025
2026 static void
2027 dissect_bap_phone_delta_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
2028                         int offset, guint length, packet_info *pinfo _U_,
2029                         proto_tree *tree)
2030 {
2031   proto_item *tf;
2032   proto_tree *field_tree;
2033   proto_item *ti;
2034   proto_tree *suboption_tree;
2035   guint8 subopt_type;
2036   guint8 subopt_len;
2037   guint8 buf[256];      /* Since Sub-Option length field in BAP Phone-Delta
2038                            Option is 8 bits, 256-octets buf is large enough */
2039
2040   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
2041   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2042
2043   offset += 2;
2044   length -= 2;
2045
2046   while (length > 0) {
2047     subopt_type = tvb_get_guint8(tvb, offset);
2048     subopt_len = tvb_get_guint8(tvb, offset + 1);
2049     ti = proto_tree_add_text(field_tree, tvb, offset, subopt_len, 
2050                 "Sub-Option (%d byte%s)",
2051                 subopt_len, plurality(subopt_len, "", "s"));
2052     suboption_tree = proto_item_add_subtree(ti, ett_bap_phone_delta_subopt);
2053
2054     proto_tree_add_text(suboption_tree, tvb, offset, 1,
2055         "Sub-Option Type: %s (%u)", 
2056         val_to_str(subopt_type, bap_phone_delta_subopt_vals, "Unknown"),
2057         subopt_type);
2058
2059     proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
2060         "Sub-Option Length: %u", subopt_len);
2061
2062     switch (subopt_type) {
2063     case BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT:
2064       proto_tree_add_text(suboption_tree, tvb, offset + 2, 1, "Uniq Digit: %u", 
2065                           tvb_get_guint8(tvb, offset + 2));
2066       break;
2067     case BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM:
2068       tvb_get_nstringz0(tvb, offset + 2, subopt_len - 2, buf);
2069       proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2, 
2070                           "Subscriber Number: %s", buf);
2071       break;
2072     case BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR:
2073       tvb_get_nstringz0(tvb, offset + 2, subopt_len - 2, buf);
2074       proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2, 
2075                           "Phone Number Sub Address: %s", buf);
2076       break;
2077     default:
2078       proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
2079                           "Unknown");
2080       break;
2081     }
2082     offset += subopt_len;
2083     length -= subopt_len;
2084   }
2085 }
2086
2087 static void
2088 dissect_bap_reason_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
2089                         int offset, guint length, packet_info *pinfo _U_,
2090                         proto_tree *tree)
2091 {
2092   guint8 buf[256];      /* Since length field in BAP Reason Option is
2093                            8 bits, 256-octets buf is large enough */
2094
2095   tvb_get_nstringz0(tvb, offset + 2, length - 2, buf);
2096   proto_tree_add_text(tree, tvb, offset, length, "%s: %s", 
2097                            optp->name, buf);
2098 }
2099
2100 static void
2101 dissect_bap_link_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
2102                         int offset, guint length, packet_info *pinfo _U_,
2103                         proto_tree *tree)
2104 {
2105   proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%04x", 
2106                       optp->name, tvb_get_ntohs(tvb, offset + 2));
2107 }
2108
2109 static void
2110 dissect_bap_call_status_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
2111                         int offset, guint length, packet_info *pinfo _U_,
2112                         proto_tree *tree)
2113 {
2114   proto_item *tf;
2115   proto_tree *field_tree;
2116   guint8 status, action;
2117
2118   tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
2119   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2120
2121   status = tvb_get_guint8(tvb, offset + 2);
2122   proto_tree_add_text(field_tree, tvb, offset + 2, 1,
2123       "Status: %s (0x%02x)", 
2124       val_to_str(status, q931_cause_code_vals, "Unknown"), status);
2125
2126   action = tvb_get_guint8(tvb, offset + 3);
2127   proto_tree_add_text(field_tree, tvb, offset + 3, 1,
2128       "Action: %s (0x%02x)", 
2129       val_to_str(action, bap_call_status_opt_action_vals, "Unknown"), action);
2130 }
2131
2132 static void
2133 dissect_cp( tvbuff_t *tvb, int proto_id, int proto_subtree_index,
2134         const value_string *proto_vals, int options_subtree_index,
2135         const ip_tcp_opt *opts, int nopts, packet_info *pinfo, proto_tree *tree ) {
2136   proto_item *ti;
2137   proto_tree *fh_tree = NULL;
2138   proto_item *tf;
2139   proto_tree *field_tree;
2140
2141   guint8 code;
2142   guint8 id;
2143   int length, offset;
2144   guint16 protocol;
2145
2146   code = tvb_get_guint8(tvb, 0);
2147   id = tvb_get_guint8(tvb, 1);
2148   length = tvb_get_ntohs(tvb, 2);
2149
2150   if(check_col(pinfo->cinfo, COL_PROTOCOL))
2151     col_set_str(pinfo->cinfo, COL_PROTOCOL,
2152                 proto_get_protocol_short_name(proto_id));
2153
2154   if(check_col(pinfo->cinfo, COL_INFO))
2155         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2156                 proto_get_protocol_short_name(proto_id),
2157                 val_to_str(code, proto_vals, "Unknown"));
2158
2159   if(tree) {
2160     ti = proto_tree_add_item(tree, proto_id, tvb, 0, length, FALSE);
2161     fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
2162     proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
2163       val_to_str(code, proto_vals, "Unknown"), code);
2164     proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
2165                         id);
2166     proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
2167                         length);
2168   }
2169   offset = 4;
2170   length -= 4;
2171
2172   switch (code) {
2173     case CONFREQ:
2174     case CONFACK:
2175     case CONFNAK:
2176     case CONFREJ:
2177       if(tree) {
2178         if (length > 0) {
2179           tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2180             "Options: (%d byte%s)", length, plurality(length, "", "s"));
2181           field_tree = proto_item_add_subtree(tf, options_subtree_index);
2182           dissect_ip_tcp_options(tvb, offset, length, opts, nopts, -1,
2183                                  pinfo, field_tree);
2184         }
2185       }
2186       break;
2187
2188     case ECHOREQ:
2189     case ECHOREP:
2190     case DISCREQ:
2191     case IDENT:
2192       if(tree) {
2193         proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
2194                         tvb_get_ntohl(tvb, offset));
2195         offset += 4;
2196         length -= 4;
2197         if (length > 0)
2198           proto_tree_add_text(fh_tree, tvb, offset, length, "Message (%d byte%s)",
2199                                 length, plurality(length, "", "s"));
2200       }
2201       break;
2202
2203     case TIMEREMAIN:
2204       if(tree) {
2205         proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
2206                         tvb_get_ntohl(tvb, offset));
2207         offset += 4;
2208         length -= 4;
2209         proto_tree_add_text(fh_tree, tvb, offset, 4, "Seconds remaining: %u",
2210                         tvb_get_ntohl(tvb, offset));
2211         offset += 4;
2212         length -= 4;
2213         if (length > 0)
2214           proto_tree_add_text(fh_tree, tvb, offset, length, "Message (%d byte%s)",
2215                                 length, plurality(length, "", "s"));
2216       }
2217       break;
2218
2219     case PROTREJ:
2220       if(tree) {
2221         protocol = tvb_get_ntohs(tvb, offset);
2222         proto_tree_add_text(fh_tree, tvb, offset, 2, "Rejected protocol: %s (0x%04x)",
2223                 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
2224         offset += 2;
2225         length -= 2;
2226         if (length > 0)
2227           proto_tree_add_text(fh_tree, tvb, offset, length, "Rejected packet (%d byte%s)",
2228                                 length, plurality(length, "", "s"));
2229                 /* XXX - should be dissected as a PPP packet */
2230       }
2231       break;
2232
2233     case CODEREJ:
2234                 /* decode the rejected LCP packet here. */
2235       if (length > 0)
2236         proto_tree_add_text(fh_tree, tvb, offset, length, "Rejected packet (%d byte%s)",
2237                                 length, plurality(length, "", "s"));
2238       break;
2239
2240     case TERMREQ:
2241     case TERMACK:
2242       if (length > 0)
2243         proto_tree_add_text(fh_tree, tvb, offset, length, "Data (%d byte%s)",
2244                                 length, plurality(length, "", "s"));
2245       break;
2246
2247     default:
2248       if (length > 0)
2249         proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
2250                                 length, plurality(length, "", "s"));
2251       break;
2252   }
2253 }
2254
2255 /* Protocol field compression */
2256 #define PFC_BIT 0x01
2257
2258 static void
2259 dissect_ppp_common( tvbuff_t *tvb, int offset, packet_info *pinfo,
2260                 proto_tree *tree, proto_tree *fh_tree,
2261                 proto_item *ti ) {
2262   guint16 ppp_prot;
2263   int     proto_len;
2264   tvbuff_t      *next_tvb;
2265
2266   ppp_prot = tvb_get_guint8(tvb, offset);
2267   if (ppp_prot & PFC_BIT) {
2268     /* Compressed protocol field - just the byte we fetched. */
2269     proto_len = 1;
2270   } else {
2271     /* Uncompressed protocol field - fetch all of it. */
2272     ppp_prot = tvb_get_ntohs(tvb, offset);
2273     proto_len = 2;
2274   }
2275
2276   /* If "ti" is not null, it refers to the top-level "proto_ppp" item
2277      for PPP, and was given a length equal to the length of any
2278      stuff in the header preceding the protocol type, e.g. an HDLC
2279      header, which is just "offset"; add the length of the protocol
2280      type field to it. */
2281   if (ti != NULL)
2282     proto_item_set_len(ti, offset + proto_len);
2283
2284   if (tree) {
2285     proto_tree_add_uint(fh_tree, hf_ppp_protocol, tvb, offset, proto_len,
2286       ppp_prot);
2287   }
2288
2289   next_tvb = tvb_new_subset(tvb, offset + proto_len, -1, -1);
2290
2291   /* do lookup with the subdissector table */
2292   if (!dissector_try_port(subdissector_table, ppp_prot, next_tvb, pinfo, tree)) {
2293     if (check_col(pinfo->cinfo, COL_PROTOCOL))
2294       col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ppp_prot);
2295     if (check_col(pinfo->cinfo, COL_INFO))
2296       col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
2297                    val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
2298     call_dissector(data_handle,next_tvb, pinfo, tree);
2299   }
2300 }
2301
2302 static void
2303 dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2304 {
2305   dissect_cp(tvb, proto_lcp, ett_lcp, lcp_vals, ett_lcp_options,
2306              lcp_opts, N_LCP_OPTS, pinfo, tree);
2307 }
2308
2309 static void
2310 dissect_ipcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2311 {
2312   dissect_cp(tvb, proto_ipcp, ett_ipcp, cp_vals, ett_ipcp_options,
2313              ipcp_opts, N_IPCP_OPTS, pinfo, tree);
2314 }
2315
2316 static void
2317 dissect_ccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2318 {
2319   dissect_cp(tvb, proto_ccp, ett_ccp, ccp_vals, ett_ccp_options,
2320              ccp_opts, N_CCP_OPTS, pinfo, tree);
2321 }
2322
2323 static void
2324 dissect_cbcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2325 {
2326   dissect_cp(tvb, proto_cbcp, ett_cbcp, cbcp_vals, ett_cbcp_options,
2327              cbcp_opts, N_CBCP_OPTS, pinfo, tree);
2328 }
2329
2330 static void
2331 dissect_bacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2332 {
2333   dissect_cp(tvb, proto_bacp, ett_bacp, cp_vals, ett_bacp_options,
2334              bacp_opts, N_BACP_OPTS, pinfo, tree);
2335 }
2336
2337 static void
2338 dissect_bap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2339 {
2340   
2341   proto_item *ti;
2342   proto_tree *fh_tree = NULL;
2343   proto_item *tf;
2344   proto_tree *field_tree;
2345
2346   guint8 type;
2347   guint8 id;
2348   int length, offset;
2349   guint8 resp_code;
2350
2351   type = tvb_get_guint8(tvb, 0);
2352   id = tvb_get_guint8(tvb, 1);
2353   length = tvb_get_ntohs(tvb, 2);
2354
2355   if(check_col(pinfo->cinfo, COL_PROTOCOL))
2356     col_set_str(pinfo->cinfo, COL_PROTOCOL,
2357                 proto_get_protocol_short_name(proto_bap));
2358
2359   if(check_col(pinfo->cinfo, COL_INFO))
2360         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2361                 proto_get_protocol_short_name(proto_bap),
2362                 val_to_str(type, bap_vals, "Unknown"));
2363
2364   if(tree) {
2365     ti = proto_tree_add_item(tree, proto_bap, tvb, 0, length, FALSE);
2366     fh_tree = proto_item_add_subtree(ti, ett_bap_options);
2367     proto_tree_add_text(fh_tree, tvb, 0, 1, "Type: %s (0x%02x)",
2368       val_to_str(type, bap_vals, "Unknown"), type);
2369     proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
2370                         id);
2371     proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
2372                         length);
2373   }
2374   offset = 4;
2375   length -= 4;
2376
2377   if (type == BAP_CRES || type == BAP_CBRES || 
2378       type == BAP_LDQRES || type == BAP_CSRES) {
2379     resp_code = tvb_get_guint8(tvb, offset);
2380     proto_tree_add_text(fh_tree, tvb, offset, 1, "Response Code: %s (0x%02x)",
2381         val_to_str(resp_code, bap_resp_code_vals, "Unknown"), resp_code);
2382     offset++;
2383     length--;
2384   }
2385
2386   if(tree) {
2387     if (length > 0) {
2388       tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2389                "Data (%d byte%s)", length, plurality(length, "", "s"));
2390       field_tree = proto_item_add_subtree(tf, ett_bap_options);
2391       dissect_ip_tcp_options(tvb, offset, length, bap_opts, N_BAP_OPTS, -1,
2392                              pinfo, field_tree);
2393     }
2394   }
2395 }
2396
2397 static void
2398 dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2399 {
2400   proto_item *ti;
2401   proto_tree *comp_data_tree;
2402
2403   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2404     col_set_str(pinfo->cinfo, COL_PROTOCOL, 
2405                 proto_get_protocol_short_name(proto_comp_data));
2406
2407   if(check_col(pinfo->cinfo, COL_INFO))
2408     col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2409                  proto_get_protocol_short_name(proto_comp_data),
2410                  val_to_str(PPP_COMP, ppp_vals, "Unknown"));
2411
2412   if (tree) {
2413     ti = proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, FALSE);
2414     comp_data_tree = proto_item_add_subtree(ti, ett_comp_data);
2415   }
2416 }
2417
2418 static void
2419 dissect_pppmuxcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2420 {
2421   dissect_cp(tvb,proto_pppmuxcp,ett_pppmuxcp,pppmuxcp_vals,
2422              ett_pppmuxcp_options,pppmuxcp_opts,N_PPPMUXCP_OPTS,pinfo,tree);
2423 }
2424
2425 #define PPPMUX_FLAGS_MASK          0xc0
2426 #define PPPMUX_PFF_BIT_SET         0x80
2427 #define PPPMUX_LXT_BIT_SET         0x40
2428
2429 static void 
2430 dissect_pppmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2431 {
2432   proto_tree *mux_tree, *hdr_tree, *sub_tree, *flag_tree;
2433   proto_tree *info_tree;
2434   proto_item *ti = NULL,*sub_ti = NULL;
2435   guint8 flags, byte;
2436   guint16 length;
2437   static guint16 pid;
2438   tvbuff_t *next_tvb;    
2439   int offset = 0, length_remaining;
2440   int length_field = 0, pid_field = 0,hdr_length = 0;
2441   
2442   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2443     col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPP PPPMux");
2444         
2445   if (check_col(pinfo->cinfo, COL_INFO))
2446     col_set_str(pinfo->cinfo, COL_INFO, "PPP Multiplexing");
2447         
2448   length_remaining = tvb_reported_length(tvb);
2449   
2450   if (tree) {
2451     ti = proto_tree_add_item(tree, proto_pppmux, tvb, 0, -1, FALSE);
2452     mux_tree = proto_item_add_subtree(ti,ett_pppmux);
2453     
2454     while (length_remaining > 0) {
2455         
2456       flags = tvb_get_guint8(tvb,offset) & PPPMUX_FLAGS_MASK;
2457       
2458       if (flags && PPPMUX_LXT_BIT_SET ) {
2459         length = tvb_get_ntohs(tvb,offset) & 0x3fff;
2460         length_field = 2;
2461       } else {
2462         length = tvb_get_guint8(tvb,offset) & 0x3f;
2463         length_field = 1;
2464       }
2465       
2466       if (flags && PPPMUX_PFF_BIT_SET) {
2467         byte = tvb_get_guint8(tvb,offset + length_field);
2468         if (byte && PFC_BIT) {            /* Compressed PID field*/
2469           pid = byte;
2470           pid_field = 1;
2471         } else {                  /*PID field is 2 bytes*/
2472           pid = tvb_get_ntohs(tvb,offset + length_field);
2473           pid_field = 2;
2474         }
2475       } else {
2476         if (!pid){       /*No Last PID, hence use the default */
2477           if (pppmux_def_prot_id) 
2478             pid = pppmux_def_prot_id;
2479         }
2480       }
2481       
2482       hdr_length = length_field + pid_field;
2483       
2484       ti = proto_tree_add_text(mux_tree, tvb, offset, length + length_field,
2485                                "PPPMux Sub-frame");
2486       sub_tree = proto_item_add_subtree(ti,ett_pppmux_subframe);
2487       sub_ti = proto_tree_add_text(sub_tree, tvb, offset,
2488                                    hdr_length,"Header field");
2489       
2490       hdr_tree = proto_item_add_subtree(sub_ti,ett_pppmux_subframe_hdr);
2491       ti = proto_tree_add_text(hdr_tree, tvb, offset, length_field, "PFF/LXT: 0x%02X",
2492                                flags);
2493       
2494       flag_tree = proto_item_add_subtree(ti,ett_pppmux_subframe_flags);
2495       proto_tree_add_text(flag_tree,tvb,offset,length_field,"%s",
2496                           decode_boolean_bitfield(flags,0x80,8,"PID Present","PID not present"));
2497       proto_tree_add_text(flag_tree,tvb,offset,length_field,"%s",
2498                           decode_boolean_bitfield(flags,0x40,8,"2 bytes ength field ","1 byte length field"));
2499       
2500       ti = proto_tree_add_text(hdr_tree,tvb,offset,length_field,"Sub-frame Length = %u",length);
2501       
2502       if (flags && PPPMUX_PFF_BIT_SET)
2503         proto_tree_add_text(hdr_tree,tvb,offset + length_field,pid_field,"%s: %s(0x%02x)",
2504                             "Protocol ID",val_to_str(pid,ppp_vals,"Unknown"), pid);
2505       
2506       offset += hdr_length;
2507       length_remaining -= hdr_length;
2508       length -= pid_field;
2509       
2510       sub_ti = proto_tree_add_text(sub_tree,tvb,offset,length,"Information Field");
2511       info_tree = proto_item_add_subtree(sub_ti,ett_pppmux_subframe_info);
2512       
2513       next_tvb = tvb_new_subset(tvb,offset,length,-1); 
2514       
2515       if (!dissector_try_port(subdissector_table, pid, next_tvb, pinfo, info_tree)) {
2516         call_dissector(data_handle, next_tvb, pinfo, info_tree);
2517       }
2518       offset += length;
2519       length_remaining -= length;
2520     }  /* While length_remaining */
2521     pid = 0; 
2522   } /* if tree */  
2523 }
2524
2525
2526 #define MP_FRAG_MASK     0xC0
2527 #define MP_FRAG(bits)    ((bits) & MP_FRAG_MASK)
2528 #define MP_FRAG_FIRST    0x80
2529 #define MP_FRAG_LAST     0x40
2530 #define MP_FRAG_RESERVED 0x3f
2531
2532 static const true_false_string frag_truth = {
2533   "Yes",
2534   "No"
2535 };
2536
2537 /* According to RFC 1717, the length the MP header isn't indicated anywhere
2538    in the header itself.  It starts out at four bytes and can be
2539    negotiated down to two using LCP.  We currently assume that all
2540    headers are four bytes.  - gcc
2541  */
2542 static void
2543 dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2544 {
2545   proto_tree *mp_tree, *hdr_tree;
2546   proto_item *ti = NULL;
2547   guint8      flags;
2548   gchar      *flag_str;
2549   tvbuff_t   *next_tvb;
2550
2551   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2552     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP MP");
2553
2554   if (check_col(pinfo->cinfo, COL_INFO))
2555     col_set_str(pinfo->cinfo, COL_INFO, "PPP Multilink");
2556
2557   flags = tvb_get_guint8(tvb, 0);
2558
2559   if (tree) {
2560     switch (flags) {
2561       case MP_FRAG_FIRST:
2562         flag_str = "First";
2563         break;
2564       case MP_FRAG_LAST:
2565         flag_str = "Last";
2566         break;
2567       case MP_FRAG_FIRST|MP_FRAG_LAST:
2568         flag_str = "First, Last";
2569         break;
2570       default:
2571         flag_str = "Unknown";
2572         break;
2573     }
2574     ti = proto_tree_add_item(tree, proto_mp, tvb, 0, 4, FALSE);
2575     mp_tree = proto_item_add_subtree(ti, ett_mp);
2576     ti = proto_tree_add_text(mp_tree, tvb, 0, 1, "Fragment: 0x%2X (%s)",
2577       flags, flag_str);
2578     hdr_tree = proto_item_add_subtree(ti, ett_mp_flags);
2579     proto_tree_add_boolean(hdr_tree, hf_mp_frag_first, tvb, 0, 1, flags);
2580     proto_tree_add_boolean(hdr_tree, hf_mp_frag_last, tvb, 0, 1, flags),
2581     proto_tree_add_text(hdr_tree, tvb, 0, 1, "%s",
2582       decode_boolean_bitfield(flags, MP_FRAG_RESERVED, sizeof(flags) * 8,
2583         "reserved", "reserved"));
2584     proto_tree_add_item(mp_tree, hf_mp_sequence_num, tvb,  1, 3, FALSE);
2585   }
2586
2587   if (tvb_reported_length_remaining(tvb, 4) > 0) {
2588     next_tvb = tvb_new_subset(tvb, 4, -1, -1);
2589     dissect_ppp(next_tvb, pinfo, tree);
2590   }
2591 }
2592
2593 /*
2594  * Handles PPP without HDLC framing, just a protocol field (RFC 1661).
2595  */
2596 static void
2597 dissect_ppp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
2598   proto_item *ti = NULL;
2599   proto_tree *fh_tree = NULL;
2600
2601   if(tree) {
2602     ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, FALSE);
2603     fh_tree = proto_item_add_subtree(ti, ett_ppp);
2604   }
2605
2606   dissect_ppp_common(tvb, 0, pinfo, tree, fh_tree, ti);
2607 }
2608
2609 /*
2610  * Handles link-layer encapsulations where the frame might be
2611  * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
2612  */
2613 static void
2614 dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
2615   proto_item *ti = NULL;
2616   proto_tree *fh_tree = NULL;
2617   guint8     byte0;
2618   int        proto_offset;
2619   int        rx_fcs_offset;
2620   guint32    rx_fcs_exp;
2621   guint32    rx_fcs_got;
2622
2623   byte0 = tvb_get_guint8(tvb, 0);
2624   if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
2625     /* Cisco HDLC encapsulation */
2626     call_dissector(chdlc_handle, tvb, pinfo, tree);
2627   }
2628
2629   /*
2630    * XXX - should we have a routine that always dissects PPP, for use
2631    * when we know the packets are PPP, not CHDLC?
2632    */
2633
2634   /* PPP HDLC encapsulation */
2635   if (byte0 == 0xff)
2636     proto_offset = 2;
2637   else {
2638     /* address and control are compressed (NULL) */
2639     proto_offset = 0;
2640   }
2641
2642   /* load the top pane info. This should be overwritten by
2643      the next protocol in the stack */
2644
2645   if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
2646     col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
2647   if(check_col(pinfo->cinfo, COL_RES_DL_DST))
2648     col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
2649   if(check_col(pinfo->cinfo, COL_PROTOCOL))
2650     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" );
2651
2652   if(tree) {
2653     ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, proto_offset, FALSE);
2654     fh_tree = proto_item_add_subtree(ti, ett_ppp);
2655     if (byte0 == 0xff) {
2656       proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1, FALSE);
2657       proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1, FALSE);
2658     }
2659   }
2660
2661   dissect_ppp_common(tvb, proto_offset, pinfo, tree, fh_tree, ti);
2662
2663   /* Calculate the FCS check */
2664   /* XXX - deal with packets cut off by the snapshot length */
2665   if (ppp_fcs_decode == FCS_16) {
2666     rx_fcs_offset = tvb_length(tvb) - 2;
2667     rx_fcs_exp = fcs16(0xFFFF, tvb, 0, rx_fcs_offset);
2668     rx_fcs_got = tvb_get_letohs(tvb, rx_fcs_offset);
2669     if (rx_fcs_got != rx_fcs_exp) {
2670       proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2, "FCS 16: 0x%04x (incorrect, should be %04x)", rx_fcs_got, rx_fcs_exp);
2671     } else {
2672       proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2, "FCS 16: 0x%04x (correct)", rx_fcs_got);
2673     }
2674   } else if (ppp_fcs_decode == FCS_32) {
2675     rx_fcs_offset = tvb_length(tvb) - 4;
2676     rx_fcs_exp = fcs32(0xFFFFFFFF, tvb, 0, rx_fcs_offset);
2677     rx_fcs_got = tvb_get_letohl(tvb, rx_fcs_offset);
2678     if (rx_fcs_got != rx_fcs_exp) {
2679       proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4, "FCS 32: 0x%08x (incorrect, should be %08x) ", rx_fcs_got, rx_fcs_exp);
2680     } else {
2681       proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4, "FCS 32: 0x%08x (correct)", rx_fcs_got);
2682     }
2683   }
2684 }
2685
2686 /*
2687  * Handles PAP just as a protocol field
2688  */
2689 static void
2690 dissect_pap( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
2691   proto_item *ti;
2692   proto_tree *fh_tree = NULL;
2693   proto_item *tf;
2694   proto_tree *field_tree;
2695   proto_item *tm;
2696   proto_tree *message_tree;
2697   proto_item *tp;
2698   proto_tree *peer_id_tree;
2699   proto_item *tpw;
2700   proto_tree *passwd_tree;
2701
2702   guint8 code;
2703   guint8 id, peer_id_length, password_length, msg_length;
2704   int length, offset;
2705
2706   code = tvb_get_guint8(tvb, 0);
2707   id = tvb_get_guint8(tvb, 1);
2708   length = tvb_get_ntohs(tvb, 2);
2709
2710   if(check_col(pinfo->cinfo, COL_PROTOCOL))
2711     col_set_str(pinfo->cinfo, COL_PROTOCOL,
2712                 proto_get_protocol_short_name(proto_pap));
2713
2714   if(check_col(pinfo->cinfo, COL_INFO))
2715         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2716                 proto_get_protocol_short_name(proto_pap),
2717                 val_to_str(code, pap_vals, "Unknown"));
2718
2719   if(tree) {
2720     ti = proto_tree_add_item(tree, proto_pap, tvb, 0, length, FALSE);
2721     fh_tree = proto_item_add_subtree(ti, ett_pap);
2722     proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
2723       val_to_str(code, pap_vals, "Unknown"), code);
2724     proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
2725                         id);
2726     proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
2727                         length);
2728   }
2729   offset = 4;
2730   length -= 4;
2731
2732   switch (code) {
2733     case CONFREQ:
2734       if(tree) {
2735         if (length > 0) {
2736           tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2737             "Data (%d byte%s)", length, plurality(length, "", "s"));
2738           field_tree = proto_item_add_subtree(tf, ett_pap_data);
2739                   peer_id_length = tvb_get_guint8(tvb, offset);
2740                   tp = proto_tree_add_text(field_tree, tvb, offset,      1,
2741               "Peer ID length: %d byte%s", peer_id_length, plurality(peer_id_length, "", "s"));
2742                   if (--length > 0) {
2743                           peer_id_tree = proto_item_add_subtree(tp, ett_pap_peer_id);
2744                           proto_tree_add_text(peer_id_tree, tvb, ++offset, ppp_min(peer_id_length, length),
2745               "Peer-ID (%d byte%s)", peer_id_length, plurality(peer_id_length, "", "s"));
2746                           offset+=peer_id_length;
2747                           length-=peer_id_length;
2748                           if (length > 0) {
2749                                 password_length = tvb_get_guint8(tvb, offset);
2750                                 if (--length > 0) {
2751                                         tpw = proto_tree_add_text(field_tree, tvb, offset,      1,
2752                                                 "Password length: %d byte%s", password_length, plurality(password_length, "", "s"));
2753                                         passwd_tree = proto_item_add_subtree(tpw, ett_pap_password);
2754                                         proto_tree_add_text(passwd_tree, tvb, ++offset, ppp_min(password_length, length),
2755                                                 "Password (%d byte%s)", password_length, plurality(password_length, "", "s"));
2756                                 }
2757                           }
2758                   }
2759         }
2760       }
2761       break;
2762
2763     case CONFACK:
2764     case CONFNAK:
2765       if(tree) {
2766         if (length > 0) {
2767           tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2768             "Data (%d byte%s)", length, plurality(length, "", "s"));
2769           field_tree = proto_item_add_subtree(tf, ett_pap_data);
2770                   msg_length = tvb_get_guint8(tvb, offset);
2771                   tm = proto_tree_add_text(field_tree, tvb, offset,      1,
2772               "Message length: %d byte%s", msg_length, plurality(msg_length, "", "s"));
2773                   if (--length > 0) {
2774                         message_tree = proto_item_add_subtree(tm, ett_pap_message);
2775                     proto_tree_add_text(message_tree, tvb, ++offset, ppp_min(msg_length, length),
2776               "Message (%d byte%s)", msg_length, plurality(msg_length, "", "s"));
2777                   }
2778         }
2779       }
2780       break;
2781     default:
2782       if (length > 0)
2783         proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
2784                                 length, plurality(length, "", "s"));
2785       break;
2786   }
2787 }
2788
2789 /*
2790  * Handles CHAP just as a protocol field
2791  */
2792 static void
2793 dissect_chap( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
2794   proto_item *ti;
2795   proto_tree *fh_tree = NULL;
2796   proto_item *tf;
2797   proto_tree *field_tree;
2798   proto_item *tv;
2799   proto_tree *value_tree;
2800
2801   guint8 code, id, value_size;
2802   guint16 length;
2803   int offset;
2804   int name_length;
2805
2806   code = tvb_get_guint8(tvb, 0);
2807   id = tvb_get_guint8(tvb, 1);
2808   length = tvb_get_ntohs(tvb, 2);
2809
2810   if(check_col(pinfo->cinfo, COL_PROTOCOL))
2811     col_set_str(pinfo->cinfo, COL_PROTOCOL,
2812                 proto_get_protocol_short_name(proto_chap));
2813
2814   if(check_col(pinfo->cinfo, COL_INFO))
2815         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2816                 proto_get_protocol_short_name(proto_chap),
2817                 val_to_str(code, chap_vals, "Unknown"));
2818
2819   if(tree) {
2820     ti = proto_tree_add_item(tree, proto_chap, tvb, 0, length, FALSE);
2821     fh_tree = proto_item_add_subtree(ti, ett_chap);
2822     proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
2823       val_to_str(code, chap_vals, "Unknown"), code);
2824     proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
2825                         id);
2826     proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
2827                         length);
2828   }
2829   offset = 4;
2830   length -= 4;
2831
2832   switch (code) {
2833     case CHAP_CHAL:
2834     case CHAP_RESP:
2835       if(tree) {
2836         if (length > 0) {
2837           tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2838                                    "Data (%d byte%s)", length, 
2839                                    plurality(length, "", "s"));
2840           field_tree = proto_item_add_subtree(tf, ett_chap_data);
2841           value_size = tvb_get_guint8(tvb, offset);
2842           name_length = length - value_size - 1; 
2843           tv = proto_tree_add_text(field_tree, tvb, offset, 1,
2844                                    "Value Size: %d byte%s", 
2845                                    value_size, plurality(value_size, "", "s"));
2846           if (--length > 0) {
2847             value_tree = proto_item_add_subtree(tv, ett_chap_value);
2848             proto_tree_add_text(value_tree, tvb, ++offset, 
2849                                 ppp_min(value_size, length),
2850                                 "Value (%d byte%s)", 
2851                                 value_size, plurality(value_size, "", "s"));
2852             offset+=value_size;
2853             length-=value_size;
2854             if (length > 0) {
2855               proto_tree_add_text(field_tree, tvb, offset, 
2856                                   ppp_min(name_length, length),
2857                                   "Name (%d byte%s)", name_length, 
2858                                   plurality(name_length, "", "s"));
2859             }
2860           }
2861         }
2862       }
2863       break;
2864
2865     case CHAP_SUCC:
2866     case CHAP_FAIL:
2867       if(tree) {
2868         if (length > 0) {
2869           tf = proto_tree_add_text(fh_tree, tvb, offset, length,
2870                                    "Data (%d byte%s)", length, 
2871                                    plurality(length, "", "s"));
2872           field_tree = proto_item_add_subtree(tf, ett_chap_data);
2873           tv = proto_tree_add_text(field_tree, tvb, offset, length,
2874                                    "Message: %d byte%s", 
2875                                    length, plurality(length, "", "s"));
2876         }
2877       }
2878       break;
2879     default:
2880       if (length > 0)
2881         proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
2882                                 length, plurality(length, "", "s"));
2883       break;
2884   }
2885 }
2886
2887
2888 void
2889 proto_register_ppp(void)
2890 {
2891   static hf_register_info hf[] = {
2892     { &hf_ppp_address,
2893     { "Address", "ppp.address", FT_UINT8, BASE_HEX,
2894         NULL, 0x0, "", HFILL }},
2895
2896     { &hf_ppp_control,
2897     { "Control", "ppp.control", FT_UINT8, BASE_HEX,
2898         NULL, 0x0, "", HFILL }},
2899
2900     { &hf_ppp_protocol,
2901     { "Protocol", "ppp.protocol", FT_UINT16, BASE_HEX,
2902         VALS(ppp_vals), 0x0, "", HFILL }},
2903   };
2904   static gint *ett[] = {
2905     &ett_ppp,
2906   };
2907
2908   static enum_val_t ppp_options[] = {
2909     {"None", 0},
2910     {"16-Bit", 1},
2911     {"32-Bit", 2},
2912     {NULL, -1}
2913   };
2914
2915   module_t *ppp_module;
2916
2917   proto_ppp = proto_register_protocol("Point-to-Point Protocol", "PPP", "ppp");
2918   proto_register_field_array(proto_ppp, hf, array_length(hf));
2919   proto_register_subtree_array(ett, array_length(ett));
2920
2921 /* subdissector code */
2922   subdissector_table = register_dissector_table("ppp.protocol",
2923         "PPP protocol", FT_UINT16, BASE_HEX);
2924
2925   register_dissector("ppp_hdlc", dissect_ppp_hdlc, proto_ppp);
2926   register_dissector("ppp", dissect_ppp, proto_ppp);
2927
2928   /* Register the preferences for the ppp protocol */
2929   ppp_module = prefs_register_protocol(proto_ppp, NULL);
2930
2931   prefs_register_enum_preference(ppp_module,
2932     "ppp_fcs",
2933     "PPP Frame Checksum Type",
2934     "The type of PPP frame checksum (none, 16-bit, 32-bit)",
2935     &ppp_fcs_decode,
2936     ppp_options, FALSE);
2937   prefs_register_bool_preference(ppp_module,
2938     "ppp_vj",
2939     "PPP Van Jacobson Compression",
2940     "Whether Van Jacobson-compressed PPP frames should be decompressed",
2941     &ppp_vj_decomp);
2942
2943   prefs_register_uint_preference(ppp_module, "default_proto_id",
2944                                  "PPPMuxCP Default PID",
2945                                  "Default Protocol ID to be used",
2946                                  16, &pppmux_def_prot_id);
2947 }
2948
2949 void
2950 proto_reg_handoff_ppp(void)
2951 {
2952   dissector_handle_t ppp_hdlc_handle, ppp_handle;
2953
2954   /*
2955    * Get a handle for the CHDLC dissector.
2956    */
2957   chdlc_handle = find_dissector("chdlc");
2958   data_handle = find_dissector("data");
2959
2960   ppp_hdlc_handle = find_dissector("ppp_hdlc");
2961   ppp_handle = find_dissector("ppp");
2962   dissector_add("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_handle);
2963   dissector_add("wtap_encap", WTAP_ENCAP_PPP_WITH_PHDR, ppp_hdlc_handle);
2964   dissector_add("fr.ietf", NLPID_PPP, ppp_handle);
2965   dissector_add("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle);
2966 }
2967
2968 void
2969 proto_register_mp(void)
2970 {
2971   static hf_register_info hf[] = {
2972     { &hf_mp_frag_first,
2973     { "First fragment",         "mp.first",     FT_BOOLEAN, 8,
2974         TFS(&frag_truth), MP_FRAG_FIRST, "", HFILL }},
2975
2976     { &hf_mp_frag_last,
2977     { "Last fragment",          "mp.last",      FT_BOOLEAN, 8,
2978         TFS(&frag_truth), MP_FRAG_LAST, "", HFILL }},
2979
2980     { &hf_mp_sequence_num,
2981     { "Sequence number",        "mp.seq",       FT_UINT24, BASE_DEC, NULL, 0x0,
2982         "", HFILL }}
2983   };
2984   static gint *ett[] = {
2985     &ett_mp,
2986     &ett_mp_flags,
2987   };
2988
2989   proto_mp = proto_register_protocol("PPP Multilink Protocol", "PPP MP", "mp");
2990   proto_register_field_array(proto_mp, hf, array_length(hf));
2991   proto_register_subtree_array(ett, array_length(ett));
2992 }
2993
2994 void
2995 proto_reg_handoff_mp(void)
2996 {
2997   dissector_handle_t mp_handle;
2998
2999   mp_handle = create_dissector_handle(dissect_mp, proto_mp);
3000   dissector_add("ppp.protocol", PPP_MP, mp_handle);
3001 }
3002
3003 void
3004 proto_register_lcp(void)
3005 {
3006   static gint *ett[] = {
3007     &ett_lcp,
3008     &ett_lcp_options,
3009     &ett_lcp_authprot_opt,
3010     &ett_lcp_qualprot_opt,
3011     &ett_lcp_fcs_alternatives_opt,
3012     &ett_lcp_numbered_mode_opt,
3013     &ett_lcp_callback_opt,
3014     &ett_lcp_multilink_ep_disc_opt,
3015     &ett_lcp_internationalization_opt,
3016   };
3017
3018   proto_lcp = proto_register_protocol("PPP Link Control Protocol", "PPP LCP",
3019                                       "lcp");
3020   proto_register_subtree_array(ett, array_length(ett));
3021 }
3022
3023 void
3024 proto_reg_handoff_lcp(void)
3025 {
3026   dissector_handle_t lcp_handle;
3027
3028   lcp_handle = create_dissector_handle(dissect_lcp, proto_lcp);
3029   dissector_add("ppp.protocol", PPP_LCP, lcp_handle);
3030
3031   /*
3032    * NDISWAN on Windows translates Ethernet frames from higher-level
3033    * protocols into PPP frames to hand to the PPP driver, and translates
3034    * PPP frames from the PPP driver to hand to the higher-level protocols.
3035    *
3036    * Apparently the PPP driver, on at least some versions of Windows,
3037    * passes frames for internal-to-PPP protocols up through NDISWAN;
3038    * the protocol type field appears to be passed through unchanged
3039    * (unlike what's done with, for example, the protocol type field
3040    * for IP, which is mapped from its PPP value to its Ethernet value).
3041    *
3042    * This means that we may see, on Ethernet captures, frames for
3043    * protocols internal to PPP, so we register PPP_LCP with the
3044    * "ethertype" dissector table as well as the PPP protocol dissector
3045    * table.
3046    */
3047   dissector_add("ethertype", PPP_LCP, lcp_handle);
3048 }
3049
3050 void
3051 proto_register_ipcp(void)
3052 {
3053   static gint *ett[] = {
3054     &ett_ipcp,
3055     &ett_ipcp_options,
3056     &ett_ipcp_ipaddrs_opt,
3057     &ett_ipcp_compressprot_opt,
3058   };
3059
3060   proto_ipcp = proto_register_protocol("PPP IP Control Protocol", "PPP IPCP",
3061                                       "ipcp");
3062   proto_register_subtree_array(ett, array_length(ett));
3063 }
3064
3065 void
3066 proto_reg_handoff_ipcp(void)
3067 {
3068   dissector_handle_t ipcp_handle;
3069
3070   ipcp_handle = create_dissector_handle(dissect_ipcp, proto_ipcp);
3071   dissector_add("ppp.protocol", PPP_IPCP, ipcp_handle);
3072
3073   /*
3074    * See above comment about NDISWAN for an explanation of why we're
3075    * registering with the "ethertype" dissector table.
3076    */
3077   dissector_add("ethertype", PPP_IPCP, ipcp_handle);
3078 }
3079
3080 void
3081 proto_register_ccp(void)
3082 {
3083   static gint *ett[] = {
3084     &ett_ccp,
3085     &ett_ccp_options,
3086     &ett_ccp_stac_opt,
3087     &ett_ccp_mppc_opt,
3088     &ett_ccp_bsdcomp_opt,
3089     &ett_ccp_lzsdcp_opt,
3090     &ett_ccp_mvrca_opt,
3091     &ett_ccp_deflate_opt,
3092   };
3093
3094   proto_ccp = proto_register_protocol("PPP Compression Control Protocol", 
3095                                       "PPP CCP", "ccp");
3096   proto_register_subtree_array(ett, array_length(ett));
3097 }
3098
3099 void
3100 proto_reg_handoff_ccp(void)
3101 {
3102   dissector_handle_t ccp_handle;
3103
3104   ccp_handle = create_dissector_handle(dissect_ccp, proto_ccp);
3105   dissector_add("ppp.protocol", PPP_CCP, ccp_handle);
3106
3107   /*
3108    * See above comment about NDISWAN for an explanation of why we're
3109    * registering with the "ethertype" dissector table.
3110    */
3111   dissector_add("ethertype", PPP_CCP, ccp_handle);
3112 }
3113
3114 void
3115 proto_register_cbcp(void)
3116 {
3117   static gint *ett[] = {
3118     &ett_cbcp,
3119     &ett_cbcp_options,
3120     &ett_cbcp_callback_opt,
3121     &ett_cbcp_callback_opt_addr
3122   };
3123
3124   proto_cbcp = proto_register_protocol("PPP Callback Control Protocoll", 
3125                                       "PPP CBCP", "cbcp");
3126   proto_register_subtree_array(ett, array_length(ett));
3127 }
3128
3129 void
3130 proto_reg_handoff_cbcp(void)
3131 {
3132   dissector_handle_t cbcp_handle;
3133
3134   cbcp_handle = create_dissector_handle(dissect_cbcp, proto_cbcp);
3135   dissector_add("ppp.protocol", PPP_CBCP, cbcp_handle);
3136
3137   /*
3138    * See above comment about NDISWAN for an explanation of why we're
3139    * registering with the "ethertype" dissector table.
3140    */
3141   dissector_add("ethertype", PPP_CBCP, cbcp_handle);
3142 }
3143
3144 void
3145 proto_register_bacp(void)
3146 {
3147   static gint *ett[] = {
3148     &ett_bacp,
3149     &ett_bacp_options,
3150     &ett_bacp_favored_peer_opt
3151   };
3152
3153   proto_bacp = proto_register_protocol("PPP Bandwidth Allocation Control Protocol", 
3154                                       "PPP BACP", "bacp");
3155   proto_register_subtree_array(ett, array_length(ett));
3156 }
3157
3158 void
3159 proto_reg_handoff_bacp(void)
3160 {
3161   dissector_handle_t bacp_handle;
3162
3163   bacp_handle = create_dissector_handle(dissect_bacp, proto_bacp);
3164   dissector_add("ppp.protocol", PPP_BACP, bacp_handle);
3165
3166   /*
3167    * See above comment about NDISWAN for an explanation of why we're
3168    * registering with the "ethertype" dissector table.
3169    */
3170   dissector_add("ethertype", PPP_BACP, bacp_handle);
3171 }
3172
3173 void
3174 proto_register_bap(void)
3175 {
3176   static gint *ett[] = {
3177     &ett_bap,
3178     &ett_bap_options,
3179     &ett_bap_link_type_opt,
3180     &ett_bap_phone_delta_opt,
3181     &ett_bap_phone_delta_subopt,
3182     &ett_bap_call_status_opt
3183   };
3184
3185   proto_bap = proto_register_protocol("PPP Bandwidth Allocation Protocol", 
3186                                       "PPP BAP", "bap");
3187   proto_register_subtree_array(ett, array_length(ett));
3188 }
3189
3190 void
3191 proto_reg_handoff_bap(void)
3192 {
3193   dissector_handle_t bap_handle;
3194
3195   bap_handle = create_dissector_handle(dissect_bap, proto_bap);
3196   dissector_add("ppp.protocol", PPP_BAP, bap_handle);
3197
3198   /*
3199    * See above comment about NDISWAN for an explanation of why we're
3200    * registering with the "ethertype" dissector table.
3201    */
3202   dissector_add("ethertype", PPP_BAP, bap_handle);
3203 }
3204
3205 void
3206 proto_register_comp_data(void)
3207 {
3208   static gint *ett[] = {
3209     &ett_comp_data
3210   };
3211
3212   proto_comp_data = proto_register_protocol("PPP Compressed Datagram",
3213                                       "PPP Comp", "comp_data");
3214   proto_register_subtree_array(ett, array_length(ett));
3215 }
3216
3217 void
3218 proto_reg_handoff_comp_data(void)
3219 {
3220   dissector_handle_t comp_data_handle;
3221
3222   comp_data_handle = create_dissector_handle(dissect_comp_data,
3223                                         proto_comp_data);
3224   dissector_add("ppp.protocol", PPP_COMP, comp_data_handle);
3225
3226   /*
3227    * See above comment about NDISWAN for an explanation of why we're
3228    * registering with the "ethertype" dissector table.
3229    */
3230   dissector_add("ethertype", PPP_COMP, comp_data_handle);
3231 }
3232
3233 void
3234 proto_register_pap(void)
3235 {
3236   static gint *ett[] = {
3237     &ett_pap,
3238         &ett_pap_data,
3239         &ett_pap_peer_id,
3240         &ett_pap_password,
3241         &ett_pap_message,
3242   };
3243
3244   proto_pap = proto_register_protocol("PPP Password Authentication Protocol", "PPP PAP",
3245                                       "pap");
3246   proto_register_subtree_array(ett, array_length(ett));
3247 }
3248
3249 void
3250 proto_reg_handoff_pap(void)
3251 {
3252   dissector_handle_t pap_handle;
3253
3254   pap_handle = create_dissector_handle(dissect_pap, proto_pap);
3255   dissector_add("ppp.protocol", PPP_PAP, pap_handle);
3256
3257   /*
3258    * See above comment about NDISWAN for an explanation of why we're
3259    * registering with the "ethertype" dissector table.
3260    */
3261   dissector_add("ethertype", PPP_PAP, pap_handle);
3262 }
3263
3264 void
3265 proto_register_chap(void)
3266 {
3267   static gint *ett[] = {
3268     &ett_chap,
3269     &ett_chap_data,
3270     &ett_chap_value,
3271     &ett_chap_name,
3272     &ett_chap_message,
3273   };
3274
3275   proto_chap = proto_register_protocol("PPP Challenge Handshake Authentication Protocol", "PPP CHAP",
3276                                       "chap");
3277   proto_register_subtree_array(ett, array_length(ett));
3278 }
3279
3280 void
3281 proto_reg_handoff_chap(void)
3282 {
3283   dissector_handle_t chap_handle;
3284
3285   chap_handle = create_dissector_handle(dissect_chap, proto_chap);
3286   dissector_add("ppp.protocol", PPP_CHAP, chap_handle);
3287
3288   /*
3289    * See above comment about NDISWAN for an explanation of why we're
3290    * registering with the "ethertype" dissector table.
3291    */
3292   dissector_add("ethertype", PPP_CHAP, chap_handle);
3293 }
3294
3295 void
3296 proto_register_pppmuxcp(void)
3297 {
3298   static gint *ett[] = {
3299     &ett_pppmuxcp,
3300     &ett_pppmuxcp_options,
3301   };
3302
3303   proto_pppmuxcp = proto_register_protocol("PPPMux Control Protocol", 
3304                                        "PPP PPPMuxCP",
3305                                       "pppmuxcp");
3306   proto_register_subtree_array(ett, array_length(ett));
3307 }
3308
3309
3310 void
3311 proto_reg_handoff_pppmuxcp(void)
3312
3313   dissector_handle_t muxcp_handle; 
3314  
3315   muxcp_handle = create_dissector_handle(dissect_pppmuxcp, proto_pppmuxcp);
3316   dissector_add("ppp.protocol", PPP_MUXCP, muxcp_handle);
3317
3318   /*
3319    * See above comment about NDISWAN for an explanation of why we're
3320    * registering with the "ethertype" dissector table.
3321    */
3322   dissector_add("ethertype", PPP_MUXCP, muxcp_handle);
3323 }
3324
3325
3326 void 
3327 proto_register_pppmux(void) 
3328
3329   static gint *ett[] = { 
3330     &ett_pppmux, 
3331     &ett_pppmux_subframe, 
3332     &ett_pppmux_subframe_hdr, 
3333     &ett_pppmux_subframe_flags, 
3334     &ett_pppmux_subframe_info, 
3335   }; 
3336  
3337   proto_pppmux = proto_register_protocol("PPP Multiplexing",  
3338                                        "PPP PPPMux", 
3339                                       "pppmux"); 
3340   proto_register_subtree_array(ett, array_length(ett)); 
3341
3342  
3343 void 
3344 proto_reg_handoff_pppmux(void) 
3345
3346   dissector_handle_t pppmux_handle; 
3347  
3348   pppmux_handle = create_dissector_handle(dissect_pppmux, proto_pppmux); 
3349   dissector_add("ppp.protocol", PPP_MUX, pppmux_handle); 
3350  
3351   /* 
3352    * See above comment about NDISWAN for an explanation of why we're 
3353    * registering with the "ethertype" dissector table. 
3354    */ 
3355   dissector_add("ethertype", PPP_MUX, pppmux_handle); 
3356
3357