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