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