1 /* packet-ppp.c
2  * Routines for ppp packet disassembly
3  * RFC 1661, RFC 1662
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  *
8  * This file created and by Mike Hall <mlh@io.com>
9  * Copyright 1998
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13 
14 #include "config.h"
15 
16 #include <epan/packet.h>
17 #include <epan/capture_dissectors.h>
18 #include <wsutil/pint.h>
19 #include <wsutil/str_util.h>
20 #include <epan/prefs.h>
21 #include "packet-ppp.h"
22 #include <epan/ppptypes.h>
23 #include <epan/etypes.h>
24 #include <epan/expert.h>
25 #include <epan/ip_opts.h>
26 #include "packet-chdlc.h"
27 #include "packet-ip.h"
28 #include "packet-ipx.h"
29 #include <epan/nlpid.h>
30 #include <epan/crc16-tvb.h>
31 #include <epan/crc32-tvb.h>
32 #include <epan/ipproto.h>
33 #include <epan/addr_resolv.h>
34 #include <epan/reassemble.h>
35 #include "packet-sll.h"
36 #include "packet-juniper.h"
37 #include "packet-sflow.h"
38 #include "packet-l2tp.h"
39 
40 void proto_register_ppp_raw_hdlc(void);
41 void proto_reg_handoff_ppp_raw_hdlc(void);
42 void proto_register_ppp(void);
43 void proto_reg_handoff_ppp(void);
44 void proto_register_mp(void);
45 void proto_reg_handoff_mp(void);
46 void proto_register_lcp(void);
47 void proto_reg_handoff_lcp(void);
48 void proto_register_vsncp(void);
49 void proto_reg_handoff_vsncp(void);
50 void proto_register_vsnp(void);
51 void proto_reg_handoff_vsnp(void);
52 void proto_register_ipcp(void);
53 void proto_reg_handoff_ipcp(void);
54 void proto_register_bcp_bpdu(void);
55 void proto_reg_handoff_bcp_bpdu(void);
56 void proto_register_bcp_ncp(void);
57 void proto_reg_handoff_bcp_ncp(void);
58 void proto_register_osinlcp(void);
59 void proto_reg_handoff_bcp(void);
60 void proto_reg_handoff_osinlcp(void);
61 void proto_register_ccp(void);
62 void proto_reg_handoff_ccp(void);
63 void proto_register_cbcp(void);
64 void proto_reg_handoff_cbcp(void);
65 void proto_register_bacp(void);
66 void proto_reg_handoff_bacp(void);
67 void proto_register_bap(void);
68 void proto_reg_handoff_bap(void);
69 void proto_register_comp_data(void);
70 void proto_reg_handoff_comp_data(void);
71 void proto_register_pap(void);
72 void proto_reg_handoff_pap(void);
73 void proto_register_chap(void);
74 void proto_reg_handoff_chap(void);
75 void proto_register_pppmuxcp(void);
76 void proto_reg_handoff_pppmuxcp(void);
77 void proto_register_pppmux(void);
78 void proto_reg_handoff_pppmux(void);
79 void proto_register_mplscp(void);
80 void proto_reg_handoff_mplscp(void);
81 void proto_register_cdpcp(void);
82 void proto_reg_handoff_cdpcp(void);
83 void proto_register_ipv6cp(void);
84 void proto_reg_handoff_ipv6cp(void);
85 void proto_register_iphc_crtp(void);
86 void proto_reg_handoff_iphc_crtp(void);
87 
88 
89 static int proto_ppp = -1;
90 static int hf_ppp_direction = -1;
91 static int hf_ppp_address = -1;
92 static int hf_ppp_control = -1;
93 static int hf_ppp_protocol = -1;
94 static int hf_ppp_code = -1;
95 static int hf_ppp_identifier = -1;
96 static int hf_ppp_length = -1;
97 static int hf_ppp_magic_number = -1;
98 static int hf_ppp_oui = -1;
99 static int hf_ppp_kind = -1;
100 static int hf_ppp_data = -1;
101 static int hf_ppp_fcs_16 = -1;
102 static int hf_ppp_fcs_32 = -1;
103 static int hf_ppp_fcs_status = -1;
104 
105 static gint ett_ppp = -1;
106 static gint ett_ppp_opt_type = -1;
107 static gint ett_ppp_unknown_opt = -1;
108 
109 static expert_field ei_ppp_opt_len_invalid = EI_INIT;
110 static expert_field ei_ppp_fcs = EI_INIT;
111 
112 static int proto_ppp_hdlc = -1;
113 
114 /* Generated from convert_proto_tree_add_text.pl */
115 static int hf_ppp_hdlc_data = -1;
116 static int hf_ppp_hdlc_fragment = -1;
117 
118 static gint ett_ppp_hdlc_data = -1;
119 
120 static int proto_lcp = -1;
121 static int proto_lcp_option_vendor = -1;
122 static int proto_lcp_option_mru = -1;
123 static int proto_lcp_option_async_map = -1;
124 static int proto_lcp_option_authprot = -1;
125 static int proto_lcp_option_qualprot = -1;
126 static int proto_lcp_option_magicnumber = -1;
127 static int proto_lcp_option_linkqualmon = -1;
128 static int proto_lcp_option_field_compress = -1;
129 static int proto_lcp_option_addr_field_compress = -1;
130 static int proto_lcp_option_fcs_alternatives = -1;
131 static int proto_lcp_option_self_desc_pad = -1;
132 static int proto_lcp_option_numbered_mode = -1;
133 static int proto_lcp_option_callback = -1;
134 static int proto_lcp_option_compound_frames = -1;
135 static int proto_lcp_option_nomdataencap = -1;
136 static int proto_lcp_option_multilink_mrru = -1;
137 static int proto_lcp_option_multilink_ssnh = -1;
138 static int proto_lcp_option_multilink_ep_disc = -1;
139 static int proto_lcp_option_dce_identifier = -1;
140 static int proto_lcp_option_multilink_pp = -1;
141 static int proto_lcp_option_link_discrim = -1;
142 static int proto_lcp_option_auth = -1;
143 static int proto_lcp_option_cobs = -1;
144 static int proto_lcp_option_prefix_elision = -1;
145 static int proto_lcp_option_multilink_hdr_fmt = -1;
146 static int proto_lcp_option_internationalization = -1;
147 static int proto_lcp_option_sonet_sdh = -1;
148 
149 static gint ett_lcp = -1;
150 static gint ett_lcp_options = -1;
151 static gint ett_lcp_vendor_opt = -1;
152 static gint ett_lcp_mru_opt = -1;
153 static gint ett_lcp_asyncmap_opt = -1;
154 static gint ett_lcp_authprot_opt = -1;
155 static gint ett_lcp_qualprot_opt = -1;
156 static gint ett_lcp_magicnumber_opt = -1;
157 static gint ett_lcp_linkqualmon_opt = -1;
158 static gint ett_lcp_pcomp_opt = -1;
159 static gint ett_lcp_acccomp_opt = -1;
160 static gint ett_lcp_fcs_alternatives_opt = -1;
161 static gint ett_lcp_self_desc_pad_opt = -1;
162 static gint ett_lcp_numbered_mode_opt = -1;
163 static gint ett_lcp_callback_opt = -1;
164 static gint ett_lcp_compound_frames_opt = -1;
165 static gint ett_lcp_nomdataencap_opt = -1;
166 static gint ett_lcp_multilink_mrru_opt = -1;
167 static gint ett_lcp_multilink_ssnh_opt = -1;
168 static gint ett_lcp_multilink_ep_disc_opt = -1;
169 static gint ett_lcp_magic_block = -1;
170 static gint ett_lcp_dce_identifier_opt = -1;
171 static gint ett_lcp_multilink_pp_opt = -1;
172 static gint ett_lcp_bacp_link_discrim_opt = -1;
173 static gint ett_lcp_auth_opt = -1;
174 static gint ett_lcp_cobs_opt = -1;
175 static gint ett_lcp_prefix_elision_opt = -1;
176 static gint ett_multilink_hdr_fmt_opt = -1;
177 static gint ett_lcp_internationalization_opt = -1;
178 static gint ett_lcp_sonet_sdh_opt = -1;
179 
180 static dissector_table_t lcp_option_table;
181 
182 static int proto_ipcp = -1;
183 static int proto_ipcp_option_addrs = -1;
184 static int proto_ipcp_option_compress = -1;
185 static int proto_ipcp_option_addr = -1;
186 static int proto_ipcp_option_mobileipv4 = -1;
187 static int proto_ipcp_option_pri_dns = -1;
188 static int proto_ipcp_option_pri_nbns = -1;
189 static int proto_ipcp_option_sec_dns = -1;
190 static int proto_ipcp_option_sec_nbns = -1;
191 static int proto_ipcp_rohc_option_profiles = -1;
192 static int proto_ipcp_iphc_option_rtp_compress = -1;
193 static int proto_ipcp_iphc_option_enhanced_rtp_compress = -1;
194 static int proto_ipcp_iphc_option_neghdrcomp = -1;
195 
196 static gint ett_ipcp = -1;
197 static gint ett_ipcp_options = -1;
198 static gint ett_ipcp_ipaddrs_opt = -1;
199 static gint ett_ipcp_compress_opt = -1;
200 static gint ett_ipcp_ipaddr_opt = -1;
201 static gint ett_ipcp_mobileipv4_opt = -1;
202 static gint ett_ipcp_pridns_opt = -1;
203 static gint ett_ipcp_secdns_opt = -1;
204 static gint ett_ipcp_prinbns_opt = -1;
205 static gint ett_ipcp_secnbns_opt = -1;
206 
207 static gint ett_ipcp_iphc_rtp_compress_opt = -1;
208 static gint ett_ipcp_iphc_enhanced_rtp_compress_opt = -1;
209 static gint ett_ipcp_iphc_neghdrcomp_opt = -1;
210 static gint ett_ipcp_rohc_profiles_opt = -1;
211 
212 static dissector_table_t ipcp_option_table;
213 static dissector_table_t ipcp_rohc_suboption_table;
214 static dissector_table_t ipcp_iphc_suboption_table;
215 
216 static int proto_vsncp = -1;
217 static int proto_vsncp_option_pdnid = -1;
218 static int proto_vsncp_option_apname = -1;
219 static int proto_vsncp_option_pdntype = -1;
220 static int proto_vsncp_option_pdnaddress = -1;
221 static int proto_vsncp_option_pco = -1;
222 static int proto_vsncp_option_errorcode = -1;
223 static int proto_vsncp_option_attachtype = -1;
224 static int proto_vsncp_option_ipv4address = -1;
225 static int proto_vsncp_option_addressalloc = -1;
226 static int proto_vsncp_option_apn_ambr = -1;
227 static int proto_vsncp_option_ipv6_hsgw_lla_iid = -1;
228 
229 static int hf_vsncp_opt_type = -1;
230 static int hf_vsncp_opt_length = -1;
231 /* Generated from convert_proto_tree_add_text.pl */
232 static int hf_vsncp_protocol_configuration_length = -1;
233 static int hf_vsncp_error_code = -1;
234 static int hf_vsncp_identifier = -1;
235 static int hf_vsncp_attach_type = -1;
236 static int hf_vsncp_protocol_configuration_data = -1;
237 static int hf_vsncp_default_router_address = -1;
238 static int hf_vsncp_pdn_identifier = -1;
239 static int hf_vsncp_address_allocation_cause = -1;
240 static int hf_vsncp_length = -1;
241 static int hf_vsncp_code = -1;
242 static int hf_vsncp_protocol = -1;
243 static int hf_vsncp_pdn_type = -1;
244 static int hf_vsncp_ipv6_interface_identifier = -1;
245 static int hf_vsncp_pdn_ipv4 = -1;
246 static int hf_vsncp_access_point_name = -1;
247 static int hf_vsncp_ambr_data = -1;
248 static int hf_vsncp_pdn_ipv6 = -1;
249 
250 static gint ett_vsncp = -1;
251 static gint ett_vsncp_options = -1;
252 static gint ett_vsncp_pdnid_opt = -1;
253 static gint ett_vsncp_apname_opt = -1;
254 static gint ett_vsncp_pdntype_opt = -1;
255 static gint ett_vsncp_pdnaddress_opt = -1;
256 static gint ett_vsncp_pco_opt = -1;
257 static gint ett_vsncp_errorcode_opt = -1;
258 static gint ett_vsncp_attachtype_opt = -1;
259 static gint ett_vsncp_ipv4address_opt = -1;
260 static gint ett_vsncp_addressalloc_opt = -1;
261 static gint ett_vsncp_apn_ambr_opt = -1;
262 static gint ett_vsncp_ipv6_hsgw_lla_iid_opt = -1;
263 
264 static dissector_table_t vsncp_option_table;
265 
266 static int proto_vsnp = -1;
267 static gint hf_vsnp_pdnid = -1;
268 
269 static gint ett_vsnp =-1;
270 
271 static int proto_osinlcp = -1;
272 static int proto_osinlcp_option_align_npdu = -1;
273 
274 static gint ett_osinlcp = -1;
275 static gint ett_osinlcp_options = -1;
276 static gint ett_osinlcp_align_npdu_opt = -1;
277 
278 static dissector_table_t osinlcp_option_table;
279 
280 static int proto_bcp_bpdu = -1;
281 static int hf_bcp_bpdu_flags = -1;
282 static int hf_bcp_bpdu_fcs_present = -1;
283 static int hf_bcp_bpdu_zeropad = -1;
284 static int hf_bcp_bpdu_bcontrol = -1;
285 static int hf_bcp_bpdu_pads = -1;
286 static int hf_bcp_bpdu_mac_type = -1;
287 static int hf_bcp_bpdu_pad = -1;
288 
289 static gint ett_bcp_bpdu = -1;
290 static gint ett_bcp_bpdu_flags = -1;
291 
292 static int proto_bcp_ncp = -1;
293 static int proto_bcp_ncp_option_bridge_id = -1;
294 static int proto_bcp_ncp_option_line_id = -1;
295 static int proto_bcp_ncp_option_mac_sup = -1;
296 static int proto_bcp_ncp_option_tinygram_comp = -1;
297 static int proto_bcp_ncp_option_lan_id = -1;
298 static int proto_bcp_ncp_option_mac_addr = -1;
299 static int proto_bcp_ncp_option_stp = -1;
300 static int proto_bcp_ncp_option_ieee_802_tagged_frame = -1;
301 static int proto_bcp_ncp_option_management_inline = -1;
302 static int proto_bcp_ncp_option_bcp_ind = -1;
303 
304 static int hf_bcp_ncp_opt_type = -1;
305 static int hf_bcp_ncp_opt_length = -1;
306 static int hf_bcp_ncp_lan_seg_no = -1;
307 static int hf_bcp_ncp_bridge_no = -1;
308 static int hf_bcp_ncp_tinygram_comp = -1;
309 static int hf_bcp_ncp_mac = -1;
310 static int hf_bcp_ncp_mac_l = -1;
311 static int hf_bcp_ncp_mac_m = -1;
312 static int hf_bcp_ncp_stp_prot = -1;
313 static int hf_bcp_ncp_ieee_802_tagged_frame = -1;
314 
315 static gint ett_bcp_ncp = -1;
316 static gint ett_bcp_ncp_options = -1;
317 static gint ett_bcp_ncp_ieee_802_tagged_frame_opt = -1;
318 static gint ett_bcp_ncp_management_inline_opt = -1;
319 static gint ett_bcp_ncp_bcp_ind_opt = -1;
320 static gint ett_bcp_ncp_bridge_id_opt = -1;
321 static gint ett_bcp_ncp_line_id_opt = -1;
322 static gint ett_bcp_ncp_mac_sup_opt = -1;
323 static gint ett_bcp_ncp_tinygram_comp_opt = -1;
324 static gint ett_bcp_ncp_lan_id_opt = -1;
325 static gint ett_bcp_ncp_mac_addr_opt = -1;
326 static gint ett_bcp_ncp_stp_opt = -1;
327 
328 static dissector_table_t bcp_ncp_option_table;
329 
330 static int proto_ccp = -1;
331 static int proto_ccp_option_oui = -1;
332 static int proto_ccp_option_predict1 = -1;
333 static int proto_ccp_option_predict2 = -1;
334 static int proto_ccp_option_puddle = -1;
335 static int proto_ccp_option_hpppc = -1;
336 static int proto_ccp_option_stac = -1;
337 static int proto_ccp_option_stac_ascend = -1;
338 static int proto_ccp_option_mppe = -1;
339 static int proto_ccp_option_gfza = -1;
340 static int proto_ccp_option_v42bis = -1;
341 static int proto_ccp_option_bsdcomp = -1;
342 static int proto_ccp_option_lzsdcp = -1;
343 static int proto_ccp_option_mvrca = -1;
344 static int proto_ccp_option_dce = -1;
345 static int proto_ccp_option_deflate = -1;
346 static int proto_ccp_option_v44lzjh = -1;
347 
348 static gint ett_ccp = -1;
349 static gint ett_ccp_options = -1;
350 static gint ett_ccp_oui_opt = -1;
351 static gint ett_ccp_predict1_opt = -1;
352 static gint ett_ccp_predict2_opt = -1;
353 static gint ett_ccp_puddle_opt = -1;
354 static gint ett_ccp_hpppc_opt = -1;
355 static gint ett_ccp_stac_opt = -1;
356 static gint ett_ccp_stac_opt_check_mode = -1;
357 static gint ett_ccp_mppe_opt = -1;
358 static gint ett_ccp_mppe_opt_supp_bits = -1;
359 static gint ett_ccp_gfza_opt = -1;
360 static gint ett_ccp_v42bis_opt = -1;
361 static gint ett_ccp_bsdcomp_opt = -1;
362 static gint ett_ccp_lzsdcp_opt = -1;
363 static gint ett_ccp_mvrca_opt = -1;
364 static gint ett_ccp_dce_opt = -1;
365 static gint ett_ccp_deflate_opt = -1;
366 static gint ett_ccp_v44lzjh_opt = -1;
367 
368 static dissector_table_t ccp_option_table;
369 
370 static int proto_cbcp = -1;
371 static int proto_cbcp_option_no_callback = -1;
372 static int proto_cbcp_option_callback_user = -1;
373 static int proto_cbcp_option_callback_admin = -1;
374 static int proto_cbcp_option_callback_list = -1;
375 
376 static int hf_cbcp_opt_type = -1;
377 static int hf_cbcp_opt_length = -1;
378 /* Generated from convert_proto_tree_add_text.pl */
379 static int hf_cbcp_address_type = -1;
380 static int hf_cbcp_address = -1;
381 static int hf_cbcp_callback_delay = -1;
382 static int hf_cbcp_no_callback = -1;
383 
384 static gint ett_cbcp = -1;
385 static gint ett_cbcp_options = -1;
386 static gint ett_cbcp_callback_opt = -1;
387 static gint ett_cbcp_callback_opt_addr = -1;
388 static gint ett_cbcp_no_callback = -1;
389 static gint ett_cbcp_callback_user = -1;
390 static gint ett_cbcp_callback_admin = -1;
391 static gint ett_cbcp_callback_list = -1;
392 
393 static expert_field ei_cbcp_address = EI_INIT;
394 
395 static dissector_table_t cbcp_option_table;
396 
397 static int proto_bacp = -1;
398 static int proto_bacp_option_favored_peer = -1;
399 
400 static int hf_bacp_opt_type = -1;
401 static int hf_bacp_opt_length = -1;
402 /* Generated from convert_proto_tree_add_text.pl */
403 static int hf_bacp_link_speed = -1;
404 static int hf_bacp_magic_number = -1;
405 static int hf_bacp_link_type = -1;
406 
407 static gint ett_bacp = -1;
408 static gint ett_bacp_options = -1;
409 static gint ett_bacp_favored_peer_opt = -1;
410 
411 static dissector_table_t bacp_option_table;
412 
413 static int proto_bap = -1;
414 static int proto_bap_option_link_type = -1;
415 static int proto_bap_option_phone_delta = -1;
416 static int proto_bap_option_no_phone = -1;
417 static int proto_bap_option_reason = -1;
418 static int proto_bap_option_link_disc = -1;
419 static int proto_bap_option_call_status = -1;
420 
421 static int hf_bap_opt_type = -1;
422 static int hf_bap_opt_length = -1;
423 /* Generated from convert_proto_tree_add_text.pl */
424 static int hf_bap_sub_option_length = -1;
425 static int hf_bap_call_status = -1;
426 static int hf_bap_unknown_option_data = -1;
427 static int hf_bap_sub_option_type = -1;
428 static int hf_bap_reason = -1;
429 static int hf_bap_link_discriminator = -1;
430 static int hf_bap_unique_digit = -1;
431 static int hf_bap_type = -1;
432 static int hf_bap_identifier = -1;
433 static int hf_bap_subscriber_number = -1;
434 static int hf_bap_phone_number_sub_address = -1;
435 static int hf_bap_response_code = -1;
436 static int hf_bap_call_action = -1;
437 static int hf_bap_length = -1;
438 
439 static gint ett_bap = -1;
440 static gint ett_bap_options = -1;
441 static gint ett_bap_link_type_opt = -1;
442 static gint ett_bap_phone_delta_opt = -1;
443 static gint ett_bap_phone_delta_subopt = -1;
444 static gint ett_bap_call_status_opt = -1;
445 static gint ett_bap_no_phone_opt = -1;
446 static gint ett_bap_reason_opt = -1;
447 static gint ett_bap_link_disc_opt = -1;
448 
449 static expert_field ei_bap_sub_option_length = EI_INIT;
450 
451 static dissector_table_t bap_option_table;
452 
453 static dissector_handle_t ppp_hdlc_handle, ppp_handle;
454 
455 static int proto_comp_data = -1;
456 
457 #if 0  /* see dissect_comp_data() */
458 static gint ett_comp_data = -1;
459 #endif
460 static int proto_pppmuxcp = -1;
461 static int proto_pppmuxcp_option_def_pid = -1;
462 
463 static int hf_pppmux_flags_pid = -1;
464 static int hf_pppmux_flags_field_length = -1;
465 static int hf_pppmuxcp_opt_type = -1;
466 static int hf_pppmuxcp_opt_length = -1;
467 /* Generated from convert_proto_tree_add_text.pl */
468 static int hf_pppmux_sub_frame_length = -1;
469 static int hf_pppmux_flags = -1;
470 static int hf_pppmux_def_prot_id = -1;
471 
472 static gint ett_pppmuxcp = -1;
473 static gint ett_pppmuxcp_options = -1;
474 static gint ett_pppmuxcp_def_pid_opt = -1;
475 
476 static dissector_table_t pppmuxcp_option_table;
477 
478 static int proto_pppmux = -1;
479 static int hf_pppmux_protocol = -1;
480 
481 static gint ett_pppmux = -1;
482 static gint ett_pppmux_subframe = -1;
483 static gint ett_pppmux_subframe_hdr = -1;
484 static gint ett_pppmux_subframe_flags = -1;
485 static gint ett_pppmux_subframe_info = -1;
486 
487 static reassembly_table mp_reassembly_table;
488 
489 static int proto_mp = -1;
490 static int hf_mp_frag = -1;
491 static int hf_mp_frag_short = -1;
492 static int hf_mp_frag_first = -1;
493 static int hf_mp_frag_last = -1;
494 static int hf_mp_sequence_num = -1;
495 static int hf_mp_sequence_num_cls = -1;
496 static int hf_mp_sequence_num_reserved = -1;
497 static int hf_mp_short_sequence_num = -1;
498 static int hf_mp_short_sequence_num_cls = -1;
499 static int hf_mp_payload = -1;
500 static gint hf_mp_fragments = -1;
501 static gint hf_mp_fragment = -1;
502 static gint hf_mp_fragment_overlap = -1;
503 static gint hf_mp_fragment_overlap_conflicts = -1;
504 static gint hf_mp_fragment_multiple_tails = -1;
505 static gint hf_mp_fragment_too_long_fragment = -1;
506 static gint hf_mp_fragment_error = -1;
507 static gint hf_mp_fragment_count = -1;
508 static gint hf_mp_reassembled_in = -1;
509 static gint hf_mp_reassembled_length = -1;
510 
511 static int ett_mp = -1;
512 static int ett_mp_flags = -1;
513 static gint ett_mp_fragment = -1;
514 static gint ett_mp_fragments = -1;
515 
516 static const fragment_items mp_frag_items = {
517     /* Fragment subtrees */
518     &ett_mp_fragment,
519     &ett_mp_fragments,
520     /* Fragment fields */
521     &hf_mp_fragments,
522     &hf_mp_fragment,
523     &hf_mp_fragment_overlap,
524     &hf_mp_fragment_overlap_conflicts,
525     &hf_mp_fragment_multiple_tails,
526     &hf_mp_fragment_too_long_fragment,
527     &hf_mp_fragment_error,
528     &hf_mp_fragment_count,
529     /* Reassembled in field */
530     &hf_mp_reassembled_in,
531     /* Reassembled length field */
532     &hf_mp_reassembled_length,
533     /* Reassembled data field */
534     NULL,
535     /* Tag */
536     "Message fragments"
537 };
538 
539 static int proto_mplscp = -1;
540 static gint ett_mplscp = -1;
541 static gint ett_mplscp_options  = -1;
542 
543 static int proto_cdpcp = -1;
544 static gint ett_cdpcp = -1;
545 static gint ett_cdpcp_options   = -1;
546 
547 static int proto_pap = -1;           /* PAP vars */
548 static gint ett_pap = -1;
549 static gint ett_pap_data = -1;
550 
551 static gint hf_pap_code = -1;
552 static gint hf_pap_identifier = -1;
553 static gint hf_pap_length = -1;
554 static gint hf_pap_data = -1;
555 static gint hf_pap_peer_id = -1;
556 static gint hf_pap_peer_id_length = -1;
557 static gint hf_pap_password = -1;
558 static gint hf_pap_password_length = -1;
559 static gint hf_pap_message = -1;
560 static gint hf_pap_message_length = -1;
561 static gint hf_pap_stuff = -1;
562 
563 static int proto_chap = -1;           /* CHAP vars */
564 static gint ett_chap = -1;
565 static gint ett_chap_data = -1;
566 
567 
568 static gint hf_chap_code = -1;
569 static gint hf_chap_identifier = -1;
570 static gint hf_chap_length = -1;
571 static gint hf_chap_data = -1;
572 static gint hf_chap_value_size = -1;
573 static gint hf_chap_value = -1;
574 static gint hf_chap_name = -1;
575 static gint hf_chap_message = -1;
576 static int hf_chap_stuff = -1;
577 
578 static int proto_ipv6cp = -1;  /* IPv6CP vars */
579 static int proto_ipv6cp_option_if_id = -1;
580 static int proto_ipv6cp_option_compress = -1;
581 
582 /* Generated from convert_proto_tree_add_text.pl */
583 static int hf_ipv6cp_opt_type = -1;
584 static int hf_ipv6cp_opt_length = -1;
585 static int hf_ipv6cp_interface_identifier = -1;
586 
587 static gint ett_ipv6cp = -1;
588 static gint ett_ipv6cp_options = -1;
589 static gint ett_ipv6cp_if_id_opt = -1;
590 static gint ett_ipv6cp_compress_opt = -1;
591 
592 static dissector_table_t ipv6cp_option_table;
593 
594 static int proto_iphc_crtp = -1;            /* CRTP vars */
595 static int proto_iphc_crtp_cudp16 = -1;
596 static int proto_iphc_crtp_cudp8 = -1;
597 static int proto_iphc_crtp_cs = -1;
598 static int proto_iphc_crtp_cntcp = -1;
599 
600 static int hf_iphc_crtp_cid8 = -1;
601 static int hf_iphc_crtp_cid16 = -1;
602 static int hf_iphc_crtp_gen = -1;
603 static int hf_iphc_crtp_seq = -1;
604 static int hf_iphc_crtp_fh_flags = -1;
605 static int hf_iphc_crtp_fh_cidlenflag = -1;
606 static int hf_iphc_crtp_fh_dataflag = -1;
607 static int hf_iphc_crtp_cs_flags = -1;
608 static int hf_iphc_crtp_cs_cnt = -1;
609 static int hf_iphc_crtp_cs_invalid = -1;
610 static int hf_iphc_crtp_ip_id = -1;
611 static int hf_iphc_crtp_data = -1;
612 
613 static gint ett_iphc_crtp = -1;
614 static gint ett_iphc_crtp_hdr = -1;
615 static gint ett_iphc_crtp_info = -1;
616 static gint ett_iphc_crtp_fh_flags = -1;
617 
618 static expert_field ei_iphc_crtp_ip_version = EI_INIT;
619 static expert_field ei_iphc_crtp_next_protocol = EI_INIT;
620 static expert_field ei_iphc_crtp_seq_nonzero = EI_INIT;
621 
622 static dissector_table_t ppp_subdissector_table;
623 static dissector_handle_t chdlc_handle;
624 static dissector_handle_t eth_withfcs_handle;
625 static dissector_handle_t eth_withoutfcs_handle;
626 
627 static capture_dissector_handle_t chdlc_cap_handle;
628 
629 static const value_string ppp_direction_vals[] = {
630     {P2P_DIR_RECV, "DCE->DTE"},
631     {P2P_DIR_SENT, "DTE->DCE"},
632     {0,            NULL}
633 };
634 
635 /* options */
636 static gint ppp_fcs_decode = 0; /* 0 = No FCS, 1 = 16 bit FCS, 2 = 32 bit FCS */
637 #define NO_FCS 0
638 #define FCS_16 1
639 #define FCS_32 2
640 
641 const enum_val_t fcs_options[] = {
642     {"none",   "None",   NO_FCS},
643     {"16-bit", "16-Bit", FCS_16},
644     {"32-bit", "32-Bit", FCS_32},
645     {NULL,     NULL,     -1}
646 };
647 
648 /*
649  * For Default Protocol ID negotiated with PPPMuxCP. We need to
650  * this ID so that if the first subframe doesn't have protocol
651  * ID, we can use it
652  */
653 
654 static guint pppmux_def_prot_id = 0;
655 
656 /* PPP definitions */
657 
658 /*
659  * Used by the GTP dissector as well.
660  * www.iana.org/assignments/ppp-numbers
661  */
662 static const value_string ppp_vals[] = {
663     {PPP_PADDING,     "Padding Protocol"},
664     {PPP_ROHC_SCID,   "ROHC small-CID"},
665     {PPP_ROHC_LCID,   "ROHC large-CID"},
666     {PPP_IP,          "Internet Protocol version 4"},
667     {PPP_OSI,         "OSI Network Layer"},
668     {PPP_XNSIDP,      "Xerox NS IDP"},
669     {PPP_DEC4,        "DECnet Phase IV"},
670     {PPP_AT,          "Appletalk"},
671     {PPP_IPX,         "Novell IPX"},
672     {PPP_VJC_COMP,    "Van Jacobson Compressed TCP/IP"},
673     {PPP_VJC_UNCOMP,  "Van Jacobson Uncompressed TCP/IP"},
674     {PPP_BCP_BPDU,    "Bridging PDU"},
675     {PPP_ST,          "Stream Protocol (ST-II)"},
676     {PPP_VINES,       "Banyan Vines"},
677     {PPP_AT_EDDP,     "AppleTalk EDDP"},
678     {PPP_AT_SB,       "AppleTalk SmartBuffered"},
679     {PPP_MP,          "Multi-Link"},
680     {PPP_NB,          "NETBIOS Framing"},
681     {PPP_CISCO,       "Cisco Systems"},
682     {PPP_ASCOM,       "Ascom Timeplex"},
683     {PPP_LBLB,        "Fujitsu Link Backup and Load Balancing (LBLB)"},
684     {PPP_RL,          "DCA Remote Lan"},
685     {PPP_SDTP,        "Serial Data Transport Protocol (PPP-SDTP)"},
686     {PPP_LLC,         "SNA over 802.2"},
687     {PPP_SNA,         "SNA"},
688     {PPP_IPV6HC,      "IPv6 Header Compression "},
689     {PPP_KNX,         "KNX Bridging Data"},
690     {PPP_ENCRYPT,     "Encryption"},
691     {PPP_ILE,         "Individual Link Encryption"},
692     {PPP_IPV6,        "Internet Protocol version 6"},
693     {PPP_MUX,         "PPP Muxing"},
694     {PPP_VSNP,        "Vendor-Specific Network Protocol (VSNP)"},
695     {PPP_TNP,         "TRILL Network Protocol (TNP)"},
696     {PPP_RTP_FH,      "RTP IPHC Full Header"},
697     {PPP_RTP_CTCP,    "RTP IPHC Compressed TCP"},
698     {PPP_RTP_CNTCP,   "RTP IPHC Compressed Non TCP"},
699     {PPP_RTP_CUDP8,   "RTP IPHC Compressed UDP 8"},
700     {PPP_RTP_CRTP8,   "RTP IPHC Compressed RTP 8"},
701     {PPP_STAMPEDE,    "Stampede Bridging"},
702     {PPP_MPPLUS,      "MP+ Protocol"},
703     {PPP_NTCITS_IPI,  "NTCITS IPI"},
704     {PPP_ML_SLCOMP,   "Single link compression in multilink"},
705     {PPP_COMP,        "Compressed datagram"},
706     {PPP_STP_HELLO,   "802.1d Hello Packets"},
707     {PPP_IBM_SR,      "IBM Source Routing BPDU"},
708     {PPP_DEC_LB,      "DEC LANBridge100 Spanning Tree"},
709     {PPP_CDP,         "Cisco Discovery Protocol"},
710     {PPP_NETCS,       "Netcs Twin Routing"},
711     {PPP_STP,         "STP - Scheduled Transfer Protocol"},
712     {PPP_EDP,         "EDP - Extreme Discovery Protocol"},
713     {PPP_OSCP,        "Optical Supervisory Channel Protocol (OSCP)"},
714     {PPP_OSCP2,       "Optical Supervisory Channel Protocol (OSCP)"},
715     {PPP_LUXCOM,      "Luxcom"},
716     {PPP_SIGMA,       "Sigma Network Systems"},
717     {PPP_ACSP,        "Apple Client Server Protocol"},
718     {PPP_MPLS_UNI,    "MPLS Unicast"},
719     {PPP_MPLS_MULTI,  "MPLS Multicast"},
720     {PPP_P12844,      "IEEE p1284.4 standard - data packets"},
721     {PPP_TETRA,       "ETSI TETRA Network Protocol Type 1"},
722     {PPP_MFTP,        "Multichannel Flow Treatment Protocol"},
723     {PPP_RTP_CTCPND,  "RTP IPHC Compressed TCP No Delta"},
724     {PPP_RTP_CS,      "RTP IPHC Context State"},
725     {PPP_RTP_CUDP16,  "RTP IPHC Compressed UDP 16"},
726     {PPP_RTP_CRDP16,  "RTP IPHC Compressed RTP 16"},
727     {PPP_CCCP,        "Cray Communications Control Protocol"},
728     {PPP_CDPD_MNRP,   "CDPD Mobile Network Registration Protocol"},
729     {PPP_EXPANDAP,    "Expand accelerator protocol"},
730     {PPP_ODSICP,      "ODSICP NCP"},
731     {PPP_DOCSIS,      "DOCSIS DLL"},
732     {PPP_CETACEANNDP, "Cetacean Network Detection Protocol"},
733     {PPP_LZS,         "Stacker LZS"},
734     {PPP_REFTEK,      "RefTek Protocol"},
735     {PPP_FC,          "Fibre Channel"},
736     {PPP_EMIT,        "EMIT Protocols"},
737     {PPP_VSP,         "Vendor-Specific Protocol (VSP)"},
738     {PPP_TLSP,        "TRILL Link State Protocol (TLSP)"},
739     {PPP_IPCP,        "Internet Protocol Control Protocol"},
740     {PPP_OSINLCP,     "OSI Network Layer Control Protocol"},
741     {PPP_XNSIDPCP,    "Xerox NS IDP Control Protocol"},
742     {PPP_DECNETCP,    "DECnet Phase IV Control Protocol"},
743     {PPP_ATCP,        "AppleTalk Control Protocol"},
744     {PPP_IPXCP,       "Novell IPX Control Protocol"},
745     {PPP_BCP_NCP,     "Bridging NCP"},
746     {PPP_SPCP,        "Stream Protocol Control Protocol"},
747     {PPP_BVCP,        "Banyan Vines Control Protocol"},
748     {PPP_MLCP,        "Multi-Link Control Protocol"},
749     {PPP_NBCP,        "NETBIOS Framing Control Protocol"},
750     {PPP_CISCOCP,     "Cisco Systems Control Protocol"},
751     {PPP_ASCOMCP,     "Ascom Timeplex"},
752     {PPP_LBLBCP,      "Fujitsu LBLB Control Protocol"},
753     {PPP_RLNCP,       "DCA Remote Lan Network Control Protocol (RLNCP)"},
754     {PPP_SDCP,        "Serial Data Control Protocol (PPP-SDCP)"},
755     {PPP_LLCCP,       "SNA over 802.2 Control Protocol"},
756     {PPP_SNACP,       "SNA Control Protocol"},
757     {PPP_IP6HCCP,     "IP6 Header Compression Control Protocol"},
758     {PPP_KNXCP,       "KNX Bridging Control Protocol"},
759     {PPP_ECP,         "Encryption Control Protocol"},
760     {PPP_ILECP,       "Individual Link Encryption Control Protocol"},
761     {PPP_IPV6CP,      "IPv6 Control Protocol"},
762     {PPP_MUXCP,       "PPP Muxing Control Protocol"},
763     {PPP_VSNCP,       "Vendor-Specific Network Control Protocol (VSNCP)"},
764     {PPP_TNCP,        "TRILL Network Control Protocol"},
765     {PPP_STAMPEDECP,  "Stampede Bridging Control Protocol"},
766     {PPP_MPPCP,       "MP+ Control Protocol"},
767     {PPP_IPICP,       "NTCITS IPI Control Protocol"},
768     {PPP_SLCC,        "Single link compression in multilink control"},
769     {PPP_CCP,         "Compression Control Protocol"},
770     {PPP_CDPCP,       "Cisco Discovery Protocol Control Protocol"},
771     {PPP_NETCSCP,     "Netcs Twin Routing"},
772     {PPP_STPCP,       "STP - Control Protocol"},
773     {PPP_EDPCP,       "EDPCP - Extreme Discovery Protocol Control Protocol"},
774     {PPP_ACSPC,       "Apple Client Server Protocol Control"},
775     {PPP_MPLSCP,      "MPLS Control Protocol"},
776     {PPP_P12844CP,    "IEEE p1284.4 standard - Protocol Control"},
777     {PPP_TETRACP,     "ETSI TETRA TNP1 Control Protocol"},
778     {PPP_MFTPCP,      "Multichannel Flow Treatment Protocol"},
779     {PPP_LCP,         "Link Control Protocol"},
780     {PPP_PAP,         "Password Authentication Protocol"},
781     {PPP_LQR,         "Link Quality Report"},
782     {PPP_SPAP,        "Shiva Password Authentication Protocol"},
783     {PPP_CBCP,        "Callback Control Protocol (CBCP)"},
784     {PPP_BACP,        "BACP Bandwidth Allocation Control Protocol"},
785     {PPP_BAP,         "BAP Bandwidth Allocation Protocol"},
786     {PPP_VSAP,        "Vendor-Specific Authentication Protocol (VSAP)"},
787     {PPP_CONTCP,      "Container Control Protocol"},
788     {PPP_CHAP,        "Challenge Handshake Authentication Protocol"},
789     {PPP_RSAAP,       "RSA Authentication Protocol"},
790     {PPP_EAP,         "Extensible Authentication Protocol"},
791     {PPP_SIEP,        "Mitsubishi Security Information Exchange Protocol (SIEP)"},
792     {PPP_SBAP,        "Stampede Bridging Authorization Protocol"},
793     {PPP_PRPAP,       "Proprietary Authentication Protocol"},
794     {PPP_PRPAP2,      "Proprietary Authentication Protocol"},
795     {PPP_PRPNIAP,     "Proprietary Node ID Authentication Protocol"},
796     {0,               NULL}
797 };
798 value_string_ext ppp_vals_ext = VALUE_STRING_EXT_INIT(ppp_vals);
799 
800 /* CP (LCP, CCP, IPCP, etc.) codes.
801  * from pppd fsm.h
802  */
803 #define VNDRSPCFC  0  /* Vendor Specific: RFC 2153 */
804 #define CONFREQ    1  /* Configuration Request */
805 #define CONFACK    2  /* Configuration Ack */
806 #define CONFNAK    3  /* Configuration Nak */
807 #define CONFREJ    4  /* Configuration Reject */
808 #define TERMREQ    5  /* Termination Request */
809 #define TERMACK    6  /* Termination Ack */
810 #define CODEREJ    7  /* Code Reject */
811 
812 static const value_string cp_vals[] = {
813     {VNDRSPCFC, "Vendor Specific"},
814     {CONFREQ,   "Configuration Request"},
815     {CONFACK,   "Configuration Ack"},
816     {CONFNAK,   "Configuration Nak"},
817     {CONFREJ,   "Configuration Reject"},
818     {TERMREQ,   "Termination Request"},
819     {TERMACK,   "Termination Ack"},
820     {CODEREJ,   "Code Reject"},
821     {0,         NULL}
822 };
823 
824 /*
825  * LCP-specific packet types.
826  */
827 #define PROTREJ    8  /* Protocol Reject */
828 #define ECHOREQ    9  /* Echo Request */
829 #define ECHOREP    10 /* Echo Reply */
830 #define DISCREQ    11 /* Discard Request */
831 #define IDENT      12 /* Identification */
832 #define TIMEREMAIN 13 /* Time remaining */
833 
834 /*
835  * CCP-specific packet types.
836  */
837 #define RESETREQ   14  /* Reset Request */
838 #define RESETACK   15  /* Reset Ack */
839 
840 /*
841  * CBCP-specific packet types.
842  */
843 #define CBREQ      1  /* Callback Request */
844 #define CBRES      2  /* Callback Response */
845 #define CBACK      3  /* Callback Ack */
846 
847 #define CBCP_OPT  6 /* Use callback control protocol */
848 
849 /*
850  * BAP-specific packet types.
851  */
852 #define BAP_CREQ   1  /* Call Request */
853 #define BAP_CRES   2  /* Call Response */
854 #define BAP_CBREQ  3  /* Callback Request */
855 #define BAP_CBRES  4  /* Callback Response */
856 #define BAP_LDQREQ 5  /* Link Drop Query Request */
857 #define BAP_LDQRES 6  /* Link Drop Query Response */
858 #define BAP_CSI    7  /* Call Status Indication */
859 #define BAP_CSRES  8  /* Call Status Response */
860 
861 static const value_string lcp_vals[] = {
862     {VNDRSPCFC,  "Vendor Specific"},
863     {CONFREQ,    "Configuration Request"},
864     {CONFACK,    "Configuration Ack"},
865     {CONFNAK,    "Configuration Nak"},
866     {CONFREJ,    "Configuration Reject"},
867     {TERMREQ,    "Termination Request"},
868     {TERMACK,    "Termination Ack"},
869     {CODEREJ,    "Code Reject"},
870     {PROTREJ,    "Protocol Reject"},
871     {ECHOREQ,    "Echo Request"},
872     {ECHOREP,    "Echo Reply"},
873     {DISCREQ,    "Discard Request"},
874     {IDENT,      "Identification"},
875     {TIMEREMAIN, "Time Remaining"},
876     {0,          NULL}
877 };
878 
879 static const value_string ccp_vals[] = {
880     {VNDRSPCFC, "Vendor Specific"},
881     {CONFREQ,   "Configuration Request"},
882     {CONFACK,   "Configuration Ack"},
883     {CONFNAK,   "Configuration Nak"},
884     {CONFREJ,   "Configuration Reject"},
885     {TERMREQ,   "Termination Request"},
886     {TERMACK,   "Termination Ack"},
887     {CODEREJ,   "Code Reject"},
888     {RESETREQ,  "Reset Request"},
889     {RESETACK,  "Reset Ack"},
890     {0,         NULL}
891 };
892 
893 static const value_string cbcp_vals[] = {
894     {CBREQ, "Callback Request"},
895     {CBRES, "Callback Response"},
896     {CBACK, "Callback Ack"},
897     {0,     NULL}
898 };
899 
900 static const value_string bap_vals[] = {
901     {BAP_CREQ,   "Call Request"},
902     {BAP_CRES,   "Call Response"},
903     {BAP_CBREQ,  "Callback Request"},
904     {BAP_CBRES,  "Callback Response"},
905     {BAP_LDQREQ, "Link Drop Query Request"},
906     {BAP_LDQRES, "Link Drop Query Response"},
907     {BAP_CSI,    "Call Status Indication"},
908     {BAP_CSRES,  "Call Status Response"},
909     {0,          NULL}
910 };
911 
912 #define BAP_RESP_CODE_REQACK     0x00
913 #define BAP_RESP_CODE_REQNAK     0x01
914 #define BAP_RESP_CODE_REQREJ     0x02
915 #define BAP_RESP_CODE_REQFULLNAK 0x03
916 static const value_string bap_resp_code_vals[] = {
917     {BAP_RESP_CODE_REQACK,     "Request Ack"},
918     {BAP_RESP_CODE_REQNAK,     "Request Nak"},
919     {BAP_RESP_CODE_REQREJ,     "Request Rej"},
920     {BAP_RESP_CODE_REQFULLNAK, "Request Full Nak"},
921     {0,                        NULL}
922 };
923 
924 #define BAP_LINK_TYPE_ISDN      0       /* ISDN */
925 #define BAP_LINK_TYPE_X25       1       /* X.25 */
926 #define BAP_LINK_TYPE_ANALOG    2       /* Analog */
927 #define BAP_LINK_TYPE_SD        3       /* Switched Digital (non-ISDN) */
928 #define BAP_LINK_TYPE_ISDNOV    4       /* ISDN data over voice */
929 #define BAP_LINK_TYPE_RESV5     5       /* Reserved */
930 #define BAP_LINK_TYPE_RESV6     6       /* Reserved */
931 #define BAP_LINK_TYPE_RESV7     7       /* Reserved */
932 static const value_string bap_link_type_vals[] = {
933     {BAP_LINK_TYPE_ISDN,   "ISDN"},
934     {BAP_LINK_TYPE_X25,    "X.25"},
935     {BAP_LINK_TYPE_ANALOG, "Analog"},
936     {BAP_LINK_TYPE_SD,     "Switched Digital (non-ISDN)"},
937     {BAP_LINK_TYPE_ISDNOV, "ISDN data over voice"},
938     {BAP_LINK_TYPE_RESV5,  "Reserved"},
939     {BAP_LINK_TYPE_RESV6,  "Reserved"},
940     {BAP_LINK_TYPE_RESV7,  "Reserved"},
941     {0,                    NULL}
942 };
943 
944 #define BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT       1 /* Unique Digit */
945 #define BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM        2 /* Subscriber Number */
946 #define BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR 3 /* Phone Number Sub Address */
947 static const value_string bap_phone_delta_subopt_vals[] = {
948     {BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT,       "Unique Digit"},
949     {BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM,        "Subscriber Number"},
950     {BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR, "Phone Number Sub Address"},
951     {0,                                       NULL}
952 };
953 
954 /*
955  * Cause codes for Cause.
956  *
957  * The following code table is taken from packet-q931.c but is slightly
958  * adapted to BAP protocol.
959  */
960 static const value_string q931_cause_code_vals[] = {
961     {0x00, "Call successful"},
962     {0x01, "Unallocated (unassigned) number"},
963     {0x02, "No route to specified transit network"},
964     {0x03, "No route to destination"},
965     {0x04, "Send special information tone"},
966     {0x05, "Misdialled trunk prefix"},
967     {0x06, "Channel unacceptable"},
968     {0x07, "Call awarded and being delivered in an established channel"},
969     {0x08, "Prefix 0 dialed but not allowed"},
970     {0x09, "Prefix 1 dialed but not allowed"},
971     {0x0A, "Prefix 1 dialed but not required"},
972     {0x0B, "More digits received than allowed, call is proceeding"},
973     {0x10, "Normal call clearing"},
974     {0x11, "User busy"},
975     {0x12, "No user responding"},
976     {0x13, "No answer from user (user alerted)"},
977     {0x14, "Subscriber absent"},
978     {0x15, "Call rejected"},
979     {0x16, "Number changed"},
980     {0x17, "Reverse charging rejected"},
981     {0x18, "Call suspended"},
982     {0x19, "Call resumed"},
983     {0x1A, "Non-selected user clearing"},
984     {0x1B, "Destination out of order"},
985     {0x1C, "Invalid number format (incomplete number)"},
986     {0x1D, "Facility rejected"},
987     {0x1E, "Response to STATUS ENQUIRY"},
988     {0x1F, "Normal unspecified"},
989     {0x21, "Circuit out of order"},
990     {0x22, "No circuit/channel available"},
991     {0x23, "Destination unattainable"},
992     {0x25, "Degraded service"},
993     {0x26, "Network out of order"},
994     {0x27, "Transit delay range cannot be achieved"},
995     {0x28, "Throughput range cannot be achieved"},
996     {0x29, "Temporary failure"},
997     {0x2A, "Switching equipment congestion"},
998     {0x2B, "Access information discarded"},
999     {0x2C, "Requested circuit/channel not available"},
1000     {0x2D, "Pre-empted"},
1001     {0x2E, "Precedence call blocked"},
1002     {0x2F, "Resources unavailable, unspecified"},
1003     {0x31, "Quality of service unavailable"},
1004     {0x32, "Requested facility not subscribed"},
1005     {0x33, "Reverse charging not allowed"},
1006     {0x34, "Outgoing calls barred"},
1007     {0x35, "Outgoing calls barred within CUG"},
1008     {0x36, "Incoming calls barred"},
1009     {0x37, "Incoming calls barred within CUG"},
1010     {0x38, "Call waiting not subscribed"},
1011     {0x39, "Bearer capability not authorized"},
1012     {0x3A, "Bearer capability not presently available"},
1013     {0x3E, "Inconsistency in designated outgoing access information and subscriber class"},
1014     {0x3F, "Service or option not available, unspecified"},
1015     {0x41, "Bearer capability not implemented"},
1016     {0x42, "Channel type not implemented"},
1017     {0x43, "Transit network selection not implemented"},
1018     {0x44, "Message not implemented"},
1019     {0x45, "Requested facility not implemented"},
1020     {0x46, "Only restricted digital information bearer capability is available"},
1021     {0x4F, "Service or option not implemented, unspecified"},
1022     {0x51, "Invalid call reference value"},
1023     {0x52, "Identified channel does not exist"},
1024     {0x53, "Call identity does not exist for suspended call"},
1025     {0x54, "Call identity in use"},
1026     {0x55, "No call suspended"},
1027     {0x56, "Call having the requested call identity has been cleared"},
1028     {0x57, "Called user not member of CUG"},
1029     {0x58, "Incompatible destination"},
1030     {0x59, "Non-existent abbreviated address entry"},
1031     {0x5A, "Destination address missing, and direct call not subscribed"},
1032     {0x5B, "Invalid transit network selection (national use)"},
1033     {0x5C, "Invalid facility parameter"},
1034     {0x5D, "Mandatory information element is missing"},
1035     {0x5F, "Invalid message, unspecified"},
1036     {0x60, "Mandatory information element is missing"},
1037     {0x61, "Message type non-existent or not implemented"},
1038     {0x62, "Message not compatible with call state or message type non-existent or not implemented"},
1039     {0x63, "Information element non-existent or not implemented"},
1040     {0x64, "Invalid information element contents"},
1041     {0x65, "Message not compatible with call state"},
1042     {0x66, "Recovery on timer expiry"},
1043     {0x67, "Parameter non-existent or not implemented - passed on"},
1044     {0x6E, "Message with unrecognized parameter discarded"},
1045     {0x6F, "Protocol error, unspecified"},
1046     {0x7F, "Internetworking, unspecified"},
1047     {0xFF, "Non-specific failure"},
1048     {0,    NULL}
1049 };
1050 static value_string_ext q931_cause_code_vals_ext = VALUE_STRING_EXT_INIT(q931_cause_code_vals);
1051 
1052 static const value_string bap_call_status_opt_action_vals[] = {
1053     {0, "No retry"},
1054     {1, "Retry"},
1055     {0, NULL}
1056 };
1057 
1058 #define STAC_CM_NONE            0
1059 #define STAC_CM_LCB             1
1060 #define STAC_CM_CRC             2
1061 #define STAC_CM_SN              3
1062 #define STAC_CM_EXTMODE         4
1063 static const value_string stac_checkmode_vals[] = {
1064     {STAC_CM_NONE,    "None"},
1065     {STAC_CM_LCB,     "LCB"},
1066     {STAC_CM_CRC,     "CRC"},
1067     {STAC_CM_SN,      "Sequence Number"},
1068     {STAC_CM_EXTMODE, "Extended Mode"},
1069     {0,               NULL}
1070 };
1071 
1072 #define LZSDCP_CM_NONE          0
1073 #define LZSDCP_CM_LCB           1
1074 #define LZSDCP_CM_SN            2
1075 #define LZSDCP_CM_SN_LCB        3
1076 static const value_string lzsdcp_checkmode_vals[] = {
1077     {LZSDCP_CM_NONE,   "None"},
1078     {LZSDCP_CM_LCB,    "LCB"},
1079     {LZSDCP_CM_SN,     "Sequence Number"},
1080     {LZSDCP_CM_SN_LCB, "Sequence Number + LCB (default)"},
1081     {0,                NULL}
1082 };
1083 
1084 #define LZSDCP_PM_NONE          0
1085 #define LZSDCP_PM_PROC_UNCOMP   1
1086 static const value_string lzsdcp_processmode_vals[] = {
1087     {LZSDCP_PM_NONE,        "None (default)"},
1088     {LZSDCP_PM_PROC_UNCOMP, "Process-Uncompressed"},
1089     {0,                     NULL}
1090 };
1091 
1092 #define DCE_MODE_1  1
1093 #define DCE_MODE_2  2
1094 static const value_string dce_mode_vals[] = {
1095     {DCE_MODE_1, "No Additional Negotiation"},
1096     {DCE_MODE_2, "Full PPP Negotiation and State Machine"},
1097     {0,          NULL}
1098 };
1099 
1100 /*
1101  * Options.  (LCP)
1102  */
1103 #define CI_VENDORSPECIFIC       0   /* Vendor Specific [RFC2153] */
1104 #define CI_MRU                  1   /* Maximum Receive Unit [RFC1661] */
1105 #define CI_ASYNCMAP             2   /* Async Control Character Map */
1106 #define CI_AUTHPROT             3   /* Authentication Protocol [RFC1661] */
1107 #define CI_QUALITY              4   /* Quality Protocol [RFC1661] */
1108 #define CI_MAGICNUMBER          5   /* Magic Number [RFC1661] */
1109 #define CI_LINKQUALMON          6   /* DEPRECATED (Quality Protocol) [RFC1172] */
1110 #define CI_PCOMPRESSION         7   /* Protocol Field Compression [RFC1661] */
1111 #define CI_ACCOMPRESSION        8   /* Address/Control Field Compression
1112                                        [RFC1661] */
1113 #define CI_FCS_ALTERNATIVES     9   /* FCS Alternatives [RFC1570] */
1114 #define CI_SELF_DESCRIBING_PAD  10  /* Self-Describing Pad [RFC1570] */
1115 #define CI_NUMBERED_MODE        11  /* Numbered Mode [RFC1663] */
1116 #define CI_MULTILINK_PROC       12  /* DEPRECATED (Multi-Link Procedure) */
1117 #define CI_CALLBACK             13  /* Callback [RFC1570] */
1118 #define CI_CONNECTTIME          14  /* DEPRECATED (Connect Time) */
1119 #define CI_COMPOUND_FRAMES      15  /* DEPRECATED (Compound Frames) [RFC1570] */
1120 #define CI_NOMDATAENCAP         16  /* DEPRECATED (Nominal Data Encapsulation) */
1121 /* NOTE: IANA lists CI_NOMDATAENCAP as 16, but it is listed as 14 in
1122  *       https://tools.ietf.org/html/draft-ietf-pppext-dataencap-03.
1123  *       Which is correct is anyone's guess. */
1124 #define CI_MULTILINK_MRRU       17  /* Multilink MRRU [RFC1990] */
1125 #define CI_MULTILINK_SSNH       18  /* Multilink Short Sequence Number Header
1126                                        [RFC1990] */
1127 #define CI_MULTILINK_EP_DISC    19  /* Multilink Endpoint Discriminator
1128                                        [RFC1990] */
1129 #define CI_PROP_KEN             20  /* Proprietary [Ken Culbert] ken@funk.com */
1130 #define CI_DCE_IDENTIFIER       21  /* DCE Identifier [RFC1976]: Warning:
1131                                        Option type 25 in the RFC is incorrect */
1132 #define CI_MULTILINK_PLUS_PROC  22  /* Multilink Plus Procedure [RFC1934] */
1133 #define CI_LINK_DISC_FOR_BACP   23  /* Link Discriminator for BACP [RFC2125] */
1134 #define CI_LCP_AUTHENTICATION   24  /* LCP Authentication Option [Culbert] */
1135 #define CI_COBS                 25  /* Consistent Overhead Byte Stuffing (COBS)
1136                                        [Carlson] */
1137 #define CI_PREFIX_ELISION       26  /* Prefix elision [RFC2686][RFC2687] */
1138 #define CI_MULTILINK_HDR_FMT    27  /* Multilink header format
1139                                        [RFC2686][RFC2687] */
1140 #define CI_INTERNATIONALIZATION 28  /* Internationalization [RFC2484] */
1141 #define CI_SDL_ON_SONET_SDH     29  /* Simple Data Link on SONET/SDH
1142                                       [RFC2823] */
1143 #define CI_UNASSIGNED           30  /* Unassigned ... but so are 31-255, so
1144                                        why do they bother specifically
1145                                        mentioning this one, I wonder? */
1146 
1147 static int hf_lcp_magic_number = -1;
1148 static int hf_lcp_data = -1;
1149 static int hf_lcp_message = -1;
1150 static int hf_lcp_secs_remaining = -1;
1151 static int hf_lcp_rej_proto = -1;
1152 static int hf_lcp_opt_type = -1;
1153 static int hf_lcp_opt_length = -1;
1154 static int hf_lcp_opt_oui = -1;
1155 static int hf_lcp_opt_kind = -1;
1156 static int hf_lcp_opt_data = -1;
1157 static int hf_lcp_opt_mru = -1;
1158 static int hf_lcp_opt_asyncmap = -1;
1159 static int hf_lcp_opt_asyncmap_nul = -1;
1160 static int hf_lcp_opt_asyncmap_soh = -1;
1161 static int hf_lcp_opt_asyncmap_stx = -1;
1162 static int hf_lcp_opt_asyncmap_etx = -1;
1163 static int hf_lcp_opt_asyncmap_eot = -1;
1164 static int hf_lcp_opt_asyncmap_enq = -1;
1165 static int hf_lcp_opt_asyncmap_ack = -1;
1166 static int hf_lcp_opt_asyncmap_bel = -1;
1167 static int hf_lcp_opt_asyncmap_bs = -1;
1168 static int hf_lcp_opt_asyncmap_ht = -1;
1169 static int hf_lcp_opt_asyncmap_lf = -1;
1170 static int hf_lcp_opt_asyncmap_vt = -1;
1171 static int hf_lcp_opt_asyncmap_ff = -1;
1172 static int hf_lcp_opt_asyncmap_cr = -1;
1173 static int hf_lcp_opt_asyncmap_so = -1;
1174 static int hf_lcp_opt_asyncmap_si = -1;
1175 static int hf_lcp_opt_asyncmap_dle = -1;
1176 static int hf_lcp_opt_asyncmap_dc1 = -1;
1177 static int hf_lcp_opt_asyncmap_dc2 = -1;
1178 static int hf_lcp_opt_asyncmap_dc3 = -1;
1179 static int hf_lcp_opt_asyncmap_dc4 = -1;
1180 static int hf_lcp_opt_asyncmap_nak = -1;
1181 static int hf_lcp_opt_asyncmap_syn = -1;
1182 static int hf_lcp_opt_asyncmap_etb = -1;
1183 static int hf_lcp_opt_asyncmap_can = -1;
1184 static int hf_lcp_opt_asyncmap_em = -1;
1185 static int hf_lcp_opt_asyncmap_sub = -1;
1186 static int hf_lcp_opt_asyncmap_esc = -1;
1187 static int hf_lcp_opt_asyncmap_fs = -1;
1188 static int hf_lcp_opt_asyncmap_gs = -1;
1189 static int hf_lcp_opt_asyncmap_rs = -1;
1190 static int hf_lcp_opt_asyncmap_us = -1;
1191 static int hf_lcp_opt_auth_protocol = -1;
1192 static int hf_lcp_opt_algorithm = -1;
1193 static int hf_lcp_opt_quality_protocol = -1;
1194 static int hf_lcp_opt_magic_number = -1;
1195 static int hf_lcp_opt_reportingperiod = -1;
1196 static int hf_lcp_opt_fcs_alternatives = -1;
1197 static int hf_lcp_opt_fcs_alternatives_null = -1;
1198 static int hf_lcp_opt_fcs_alternatives_ccitt16 = -1;
1199 static int hf_lcp_opt_fcs_alternatives_ccitt32 = -1;
1200 static int hf_lcp_opt_maximum = -1;
1201 static int hf_lcp_opt_window = -1;
1202 static int hf_lcp_opt_hdlc_address = -1;
1203 static int hf_lcp_opt_operation = -1;
1204 static int hf_lcp_opt_message = -1;
1205 static int hf_lcp_opt_mrru = -1;
1206 static int hf_lcp_opt_ep_disc_class = -1;
1207 static int hf_lcp_opt_ip_address = -1;
1208 static int hf_lcp_opt_802_1_address = -1;
1209 static int hf_lcp_opt_magic_block = -1;
1210 static int hf_lcp_opt_psndn = -1;
1211 static int hf_lcp_opt_mode = -1;
1212 static int hf_lcp_opt_unused = -1;
1213 static int hf_lcp_opt_link_discrim = -1;
1214 static int hf_lcp_opt_id = -1;
1215 static int hf_lcp_opt_cobs_flags = -1;
1216 static int hf_lcp_opt_cobs_flags_res = -1;
1217 static int hf_lcp_opt_cobs_flags_pre = -1;
1218 static int hf_lcp_opt_cobs_flags_zxe = -1;
1219 static int hf_lcp_opt_class = -1;
1220 static int hf_lcp_opt_prefix = -1;
1221 static int hf_lcp_opt_code = -1;
1222 static int hf_lcp_opt_max_susp_classes = -1;
1223 static int hf_lcp_opt_MIBenum = -1;
1224 static int hf_lcp_opt_language_tag = -1;
1225 
1226 static gboolean
ppp_option_len_check(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,int proto,guint len,guint optlen)1227 ppp_option_len_check(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, int proto, guint len, guint optlen)
1228 {
1229     if (len != optlen) {
1230         /* Bogus - option length isn't what it's supposed to be for this option. */
1231         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
1232                             "%s (with option length = %u byte%s; should be %u)",
1233                             proto_get_protocol_short_name(find_protocol_by_id(proto)),
1234                             len, plurality(len, "", "s"), optlen);
1235         return FALSE;
1236     }
1237 
1238     return TRUE;
1239 }
1240 
1241  /* Started as a copy of dissect_ip_tcp_options(), but was changed to support
1242     options as a dissector table */
1243 static void
ppp_dissect_options(tvbuff_t * tvb,int offset,guint length,dissector_table_t const option_dissectors,packet_info * pinfo,proto_tree * opt_tree)1244 ppp_dissect_options(tvbuff_t *tvb, int offset, guint length, dissector_table_t const option_dissectors,
1245                        packet_info *pinfo, proto_tree *opt_tree)
1246 {
1247     guchar            opt;
1248     guint             optlen;
1249     const char       *name;
1250     dissector_handle_t option_dissector = NULL;
1251     tvbuff_t         *next_tvb;
1252 
1253     while (length > 0) {
1254         opt = tvb_get_guint8(tvb, offset);
1255         --length;      /* account for type byte */
1256         if (option_dissectors != NULL) {
1257             option_dissector = dissector_get_uint_handle(option_dissectors, opt);
1258             if (option_dissector == NULL) {
1259                 name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
1260             } else {
1261                 name = dissector_handle_get_short_name(option_dissector);
1262             }
1263         } else {
1264             name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
1265         }
1266 
1267         /* Option has a length. Is it in the packet? */
1268         if (length == 0) {
1269             /* Bogus - packet must at least include option code byte and
1270                 length byte! */
1271             proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, 1,
1272                                             "%s (length byte past end of options)", name);
1273             return;
1274         }
1275 
1276         optlen = tvb_get_guint8(tvb, offset + 1);  /* total including type, len */
1277         --length;    /* account for length byte */
1278 
1279         if (optlen < 2) {
1280             /* Bogus - option length is too short to include option code and
1281                 option length. */
1282             proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, 2,
1283                                 "%s (with too-short option length = %u byte%s)",
1284                                 name, optlen, plurality(optlen, "", "s"));
1285             return;
1286         } else if (optlen - 2 > length) {
1287             /* Bogus - option goes past the end of the header. */
1288             proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, length,
1289                                 "%s (option length = %u byte%s says option goes past end of options)",
1290                                 name, optlen, plurality(optlen, "", "s"));
1291             return;
1292         }
1293 
1294         if (option_dissector == NULL) {
1295             proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, ett_ppp_unknown_opt, NULL, "%s (%u byte%s)",
1296                                             name, optlen, plurality(optlen, "", "s"));
1297         } else {
1298             next_tvb = tvb_new_subset_length(tvb, offset, optlen);
1299             call_dissector(option_dissector, next_tvb, pinfo, opt_tree);
1300             proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);
1301         }
1302         offset += optlen;
1303         length -= (optlen-2); //already accounted for type and len bytes
1304     }
1305 }
1306 
1307 static void
dissect_lcp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)1308 dissect_lcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
1309     const char *name)
1310 {
1311     guint8 type;
1312 
1313     type = tvb_get_guint8(tvb, offset);
1314     proto_tree_add_uint_format_value(tree, hf_lcp_opt_type, tvb, offset, 1,
1315         type, "%s (%u)", name, type);
1316     proto_tree_add_item(tree, hf_lcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
1317 }
1318 
1319 static gboolean
dissect_lcp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)1320 dissect_lcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1321                              int proto, int ett, int expected_length,
1322                              proto_tree** ret_tree, proto_item** ret_item)
1323 {
1324     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
1325         return FALSE;
1326 
1327     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
1328     *ret_tree = proto_item_add_subtree(*ret_item, ett);
1329 
1330     dissect_lcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
1331     return TRUE;
1332 }
1333 
1334 static gboolean
dissect_lcp_var_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)1335 dissect_lcp_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1336                              int proto, int ett, int expected_length,
1337                              proto_tree** ret_tree, proto_item** ret_item)
1338 {
1339     int len = tvb_reported_length(tvb);
1340 
1341     if (len < expected_length) {
1342         /* Bogus - option length isn't what it's supposed to be for this option. */
1343         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
1344                             "%s (with option length = %u byte%s; should be at least %u)",
1345                             proto_get_protocol_short_name(find_protocol_by_id(proto_lcp_option_vendor)),
1346                             len, plurality(len, "", "s"), 6);
1347         return FALSE;
1348     }
1349 
1350     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
1351     *ret_tree = proto_item_add_subtree(*ret_item, ett);
1352 
1353     dissect_lcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
1354     return TRUE;
1355 }
1356 
1357 /* Used for:
1358  *  Protocol Field Compression
1359  *  Address and Control Field Compression
1360  *  Compound Frames (Deprecated)
1361  *  Nominal Data Encapsulation (Deprecated)
1362  *  Multilink Short Sequence Number Header
1363  *  Simple Data Link on SONET/SDH
1364  */
1365 static int
dissect_lcp_simple_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett)1366 dissect_lcp_simple_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett)
1367 {
1368     proto_tree *field_tree;
1369     proto_item *ti;
1370 
1371     dissect_lcp_fixed_opt(tvb, pinfo, tree, proto, ett, 2, &field_tree, &ti);
1372     return tvb_captured_length(tvb);
1373 }
1374 
1375 /* 3GPP2 X.S0057-B v1.0
1376  * 9.1.4.1 3GPP2 VSNCP Configuration Options
1377  * Options.  (VSNCP)
1378  */
1379 
1380 #define CI_PDN_IDENTIFIER       1
1381 #define CI_ACCESS_POINT_NM      2
1382 #define CI_PDN_TYPE             3
1383 #define CI_PDN_ADDRESS          4
1384 #define CI_PROTOCOL_CONFIG      5
1385 #define CI_ERROR_CODE           6
1386 #define CI_ATTACH_TYPE          7
1387 #define CI_IPv4DEFAULT_ROUTER   8
1388 #define CI_ADDRESS_ALLOC        9
1389 #define CI_APN_AMBR             10
1390 #define CI_IPv6_HSGW_LLA_IID    11
1391 
1392 /*
1393  * CHAP Algorithms
1394  */
1395 /* 0-4: Reserved */
1396 #define CHAP_ALG_MD5    5       /* CHAP with MD5 */
1397 #define CHAP_AGL_SHA1   6       /* CHAP with SHA-1 [Black] */
1398 /* 7-127: Unassigned */
1399 #define CHAP_ALG_MSV1   128     /* MS-CHAP */
1400 #define CHAP_ALG_MSV2   129     /* MS-CHAP-2 */
1401 
1402 static const range_string chap_alg_rvals[] = {
1403     {0,             4,             "Reserved"},
1404     {CHAP_ALG_MD5,  CHAP_ALG_MD5,  "CHAP with MD5"},
1405     {CHAP_AGL_SHA1, CHAP_AGL_SHA1, "CHAP with SHA-1"},
1406     {CHAP_ALG_MSV1, CHAP_ALG_MSV1, "MS-CHAP"},
1407     {CHAP_ALG_MSV2, CHAP_ALG_MSV2, "MS-CHAP-2"},
1408     {0,             0,             NULL}
1409 };
1410 
1411 
1412 /*
1413  * Options.  (IPCP)
1414  * https://tools.ietf.org/html/rfc1172
1415  * https://tools.ietf.org/html/rfc1332
1416  * https://tools.ietf.org/html/rfc1877
1417  * https://tools.ietf.org/html/rfc2290
1418  * https://tools.ietf.org/html/rfc3241
1419  * https://tools.ietf.org/html/rfc3545
1420  */
1421 #define CI_ADDRS            1       /* IP Addresses (deprecated) (RFC 1172) */
1422 #define CI_COMPRESS_PROTO   2       /* Compression Protocol (RFC 1332) */
1423 #define CI_ADDR             3       /* IP Address (RFC 1332) */
1424 #define CI_MOBILE_IPv4      4       /* Mobile IPv4 (RFC 2290) */
1425 #define CI_PRI_DNS          129     /* Primary DNS value (RFC 1877) */
1426 #define CI_PRI_NBNS         130     /* Primary NBNS value (RFC 1877) */
1427 #define CI_SEC_DNS          131     /* Secondary DNS value (RFC 1877) */
1428 #define CI_SEC_NBNS         132     /* Secondary NBNS value (RFC 1877) */
1429 
1430 static int hf_ipcp_opt_type = -1;
1431 static int hf_ipcp_opt_length = -1;
1432 static int hf_ipcp_opt_src_address = -1;
1433 static int hf_ipcp_opt_dst_address = -1;
1434 static int hf_ipcp_opt_compress_proto = -1;
1435 static int hf_ipcp_opt_max_cid = -1;
1436 static int hf_ipcp_opt_mrru = -1;
1437 static int hf_ipcp_opt_max_slot_id = -1;
1438 static int hf_ipcp_opt_comp_slot_id = -1;
1439 static int hf_ipcp_opt_tcp_space = -1;
1440 static int hf_ipcp_opt_non_tcp_space = -1;
1441 static int hf_ipcp_opt_f_max_period = -1;
1442 static int hf_ipcp_opt_f_max_time = -1;
1443 static int hf_ipcp_opt_max_header = -1;
1444 static int hf_ipcp_data = -1;
1445 static int hf_ipcp_opt_ip_address = -1;
1446 static int hf_ipcp_opt_mobilenodehomeaddr = -1;
1447 static int hf_ipcp_opt_pri_dns_address = -1;
1448 static int hf_ipcp_opt_pri_nbns_address = -1;
1449 static int hf_ipcp_opt_sec_dns_address = -1;
1450 static int hf_ipcp_opt_sec_nbns_address = -1;
1451 
1452 static int hf_ipcp_opt_rohc_type = -1;
1453 static int hf_ipcp_opt_rohc_length = -1;
1454 static int hf_ipcp_opt_rohc_profile = -1;
1455 static int hf_ipcp_opt_iphc_type = -1;
1456 static int hf_ipcp_opt_iphc_length = -1;
1457 static int hf_ipcp_opt_iphc_param = -1;
1458 
1459 /*
1460  * IP Compression options
1461  */
1462 #define IPCP_ROHC               0x0003  /* RFC3241 */
1463 #define IPCP_COMPRESS_VJ_1172   0x0037  /* value defined in RFC1172 (typo) */
1464 #define IPCP_COMPRESS_VJ        0x002d  /* value defined in RFC1332 (correct) */
1465 #define IPCP_COMPRESS_IPHC      0x0061  /* RFC3544 (and RFC2509) */
1466 
1467 static const value_string ipcp_compress_proto_vals[] = {
1468     {IPCP_ROHC,             "Robust Header Compression (ROHC)"},
1469     {IPCP_COMPRESS_VJ,      "VJ compression"},
1470     {IPCP_COMPRESS_VJ_1172, "VJ compression (RFC1172-typo)"},
1471     {IPCP_COMPRESS_IPHC,    "IPHC compression"},
1472     {0,                     NULL}
1473 };
1474 
1475 /* IPHC suboptions (RFC2508, 3544) */
1476 #define IPCP_IPHC_CRTP          1
1477 #define IPCP_IPHC_ECRTP         2
1478 #define IPCP_IPHC_NEGHC         3
1479 
1480 static const value_string ipcp_iphc_parameter_vals[] = {
1481     {1, "The number of contexts for TCP Space is 0"},
1482     {2, "The number of contexts for Non TCP Space is 0"},
1483     {0, NULL}
1484 };
1485 
1486 
1487 /* ROHC suboptions */
1488 #define IPCP_ROHC_PROFILES      1
1489 
1490 /* From https://tools.ietf.org/html/rfc3095 */
1491 static const value_string ipcp_rohc_profile_vals[] = {
1492     {0x0000, "ROHC uncompressed -- no compression"},
1493     {0x0002, "ROHC UDP -- non-RTP UDP/IP compression"},
1494     {0x0003, "ROHC ESP -- ESP/IP compression"},
1495     {0,      NULL}
1496 };
1497 
1498 /*
1499 * Options.  (bcp_ncp)
1500 1       Bridge-Identification
1501 2       Line-Identification
1502 3       MAC-Support
1503 4       Tinygram-Compression
1504 5       LAN-Identification (obsoleted)
1505 6       MAC-Address
1506 7       Spanning-Tree-Protocol (old formatted)
1507 8       IEEE 802 Tagged Frame
1508 9       Management Inline
1509 10       Bridge Control Packet Indicator
1510 
1511 */
1512 #define CI_BCPNCP_BRIDGE_ID 1
1513 #define CI_BCPNCP_LINE_ID 2
1514 #define CI_BCPNCP_MAC_SUPPORT 3
1515 #define CI_BCPNCP_TINYGRAM_COMP 4
1516 #define CI_BCPNCP_LAN_ID 5
1517 #define CI_BCPNCP_MAC_ADDRESS 6
1518 #define CI_BCPNCP_STP 7
1519 #define CI_BCPNCP_IEEE_802_TAGGED_FRAME 8
1520 #define CI_BCPNCP_MANAGEMENT_INLINE 9
1521 #define CI_BCPNCP_BCP_IND 10
1522 
1523 /*
1524  * Options.  (OSINLCP)
1525  */
1526 #define CI_OSINLCP_ALIGN_NPDU    1  /* Alignment of the OSI NPDU (RFC 1377) */
1527 
1528 static int hf_osinlcp_opt_type = -1;
1529 static int hf_osinlcp_opt_length = -1;
1530 static int hf_osinlcp_opt_alignment = -1;
1531 
1532 /*
1533  * Options.  (CCP)
1534  */
1535 #define CI_CCP_OUI      0       /* OUI (RFC1962) */
1536 #define CI_CCP_PREDICT1 1       /* Predictor type 1 (RFC1962) */
1537 #define CI_CCP_PREDICT2 2       /* Predictor type 2 (RFC1962) */
1538 #define CI_CCP_PUDDLE   3       /* Puddle Jumper (RFC1962) */
1539 #define CI_CCP_HPPPC    16      /* Hewlett-Packard PPC (RFC1962) */
1540 #define CI_CCP_STAC     17      /* stac Electronics LZS (RFC1974) */
1541 #define CI_CCP_MPPE     18      /* Microsoft PPE/C (RFC2118/3078) */
1542 #define CI_CCP_GFZA     19      /* Gandalf FZA (RFC1962) */
1543 #define CI_CCP_V42BIS   20      /* V.42bis compression */
1544 #define CI_CCP_BSDLZW   21      /* BSD LZW Compress (RFC1977) */
1545 #define CI_CCP_LZSDCP   23      /* LZS-DCP (RFC1967) */
1546 #define CI_CCP_MVRCA    24      /* MVRCA (Magnalink) (RFC1975) */
1547 #define CI_CCP_DCE      25      /* DCE (RFC1976) */
1548 #define CI_CCP_DEFLATE  26      /* Deflate (RFC1979) */
1549 #define CI_CCP_V44LZJH  27      /* V.44/LZJH (https://tools.ietf.org/html/draft-heath-ppp-v44-01) */
1550 #define CI_CCP_RESERVED 255     /* Reserved (RFC1962) */
1551 
1552 static int hf_ccp_opt_type = -1;
1553 static int hf_ccp_opt_length = -1;
1554 static int hf_ccp_opt_oui = -1;
1555 static int hf_ccp_opt_subtype = -1;
1556 static int hf_ccp_opt_data = -1;
1557 static int hf_ccp_opt_history_count = -1;
1558 static int hf_ccp_opt_cm = -1;
1559 static int hf_ccp_opt_cm_reserved = -1;
1560 static int hf_ccp_opt_cm_check_mode = -1;
1561 static int hf_ccp_opt_supported_bits = -1;
1562 static int hf_ccp_opt_supported_bits_h = -1;
1563 static int hf_ccp_opt_supported_bits_m = -1;
1564 static int hf_ccp_opt_supported_bits_s = -1;
1565 static int hf_ccp_opt_supported_bits_l = -1;
1566 static int hf_ccp_opt_supported_bits_d = -1;
1567 static int hf_ccp_opt_supported_bits_c = -1;
1568 static int hf_ccp_opt_history = -1;
1569 static int hf_ccp_opt_version = -1;
1570 static int hf_ccp_opt_vd = -1;
1571 static int hf_ccp_opt_vd_vers = -1;
1572 static int hf_ccp_opt_vd_dict = -1;
1573 static int hf_ccp_opt_check_mode = -1;
1574 static int hf_ccp_opt_process_mode = -1;
1575 static int hf_ccp_opt_fe = -1;
1576 static int hf_ccp_opt_p = -1;
1577 static int hf_ccp_opt_History = -1; /* Different than hf_ccp_opt_history */
1578 static int hf_ccp_opt_contexts = -1;
1579 static int hf_ccp_opt_mode = -1;
1580 static int hf_ccp_opt_window = -1;
1581 static int hf_ccp_opt_method = -1;
1582 static int hf_ccp_opt_mbz = -1;
1583 static int hf_ccp_opt_chk = -1;
1584 static int hf_ccp_opt_mode_dictcount = -1;
1585 static int hf_ccp_opt_dict_size = -1;
1586 static int hf_ccp_opt_history_length = -1;
1587 
1588 /*
1589  * Options.  (CBCP)
1590  */
1591 #define CI_CBCP_NO_CALLBACK     1  /* No callback */
1592 #define CI_CBCP_CB_USER         2  /* Callback to a user-specified number */
1593 #define CI_CBCP_CB_PRE          3  /* Callback to a pre-specified or
1594                                       administrator specified number */
1595 #define CI_CBCP_CB_ANY          4  /* Callback to any of a list of numbers */
1596 
1597 /*
1598  * Options.  (BACP)
1599  */
1600 #define CI_BACP_FAVORED_PEER    1  /* Favored-Peer */
1601 
1602 /*
1603  * Options.  (BAP)
1604  */
1605 #define CI_BAP_LINK_TYPE           1  /* Link Type */
1606 #define CI_BAP_PHONE_DELTA         2  /* Phone-Delta */
1607 #define CI_BAP_NO_PHONE_NUM_NEEDED 3  /* No Phone Number Needed */
1608 #define CI_BAP_REASON              4  /* Reason */
1609 #define CI_BAP_LINK_DISC           5  /* Link Discriminator */
1610 #define CI_BAP_CALL_STATUS         6  /* Call Status */
1611 
1612 static int dissect_ppp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
1613 
1614 static const value_string pap_vals[] = {
1615     {CONFREQ, "Authenticate-Request"},
1616     {CONFACK, "Authenticate-Ack"},
1617     {CONFNAK, "Authenticate-Nak"},
1618     {0,       NULL}
1619 };
1620 
1621 #define CHAP_CHAL  1  /* CHAP Challenge */
1622 #define CHAP_RESP  2  /* CHAP Response */
1623 #define CHAP_SUCC  3  /* CHAP Success */
1624 #define CHAP_FAIL  4  /* CHAP Failure */
1625 
1626 static const value_string chap_vals[] = {
1627     {CHAP_CHAL, "Challenge"},
1628     {CHAP_RESP, "Response"},
1629     {CHAP_SUCC, "Success"},
1630     {CHAP_FAIL, "Failure"},
1631     {0,         NULL}
1632 };
1633 
1634 static const value_string pppmuxcp_vals[] = {
1635     {CONFREQ, "Configuration Request"},
1636     {CONFACK, "Configuration Ack"},
1637     {0,       NULL}
1638 };
1639 
1640 /*
1641  * PPPMuxCP options
1642  */
1643 
1644 #define CI_DEFAULT_PID   1
1645 
1646 static const true_false_string tfs_pppmux_length_field = { "2 bytes", "1 byte" };
1647 
1648 /*
1649  * Options.  (IPv6CP)
1650  */
1651 #define CI_IPV6CP_IF_ID         1       /* Interface Identifier (RFC 2472) */
1652 #define CI_IPV6CP_COMPRESSTYPE  2       /* Compression Type (RFC 2472) */
1653 
1654 /*
1655 *******************************************************************************
1656 * DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data.
1657 *******************************************************************************
1658 */
1659 static guint16
fcs16(tvbuff_t * tvbuff)1660 fcs16(tvbuff_t *tvbuff)
1661 {
1662     guint len = tvb_reported_length(tvbuff) - 2;
1663 
1664     /* Check for Invalid Length */
1665     if (len == 0)
1666         return (0x0000);
1667     return crc16_ccitt_tvb(tvbuff, len);
1668 }
1669 
1670 /*
1671 *******************************************************************************
1672 * DETAILS : Calculate a new FCS-32 given the current FCS-32 and the new data.
1673 *******************************************************************************
1674 */
1675 static guint32
fcs32(tvbuff_t * tvbuff)1676 fcs32(tvbuff_t *tvbuff)
1677 {
1678     guint len = tvb_reported_length(tvbuff) - 4;
1679 
1680     /* Check for invalid Length */
1681     if (len == 0)
1682         return (0x00000000);
1683     return crc32_ccitt_tvb(tvbuff, len);
1684 }
1685 
1686 tvbuff_t *
decode_fcs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * fh_tree,int fcs_decode,int proto_offset)1687 decode_fcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *fh_tree, int fcs_decode, int proto_offset)
1688 {
1689     tvbuff_t *next_tvb;
1690     gint      len, reported_len;
1691 
1692     /*
1693      * Remove the FCS, if any, from the packet data.
1694      */
1695     switch (fcs_decode) {
1696 
1697     case NO_FCS:
1698         next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
1699         break;
1700 
1701     case FCS_16:
1702         /*
1703          * Do we have the entire packet, and does it include a 2-byte FCS?
1704          */
1705         len = tvb_captured_length_remaining(tvb, proto_offset);
1706         reported_len = tvb_reported_length_remaining(tvb, proto_offset);
1707         if (reported_len < 2 || len < 0) {
1708             /*
1709              * The packet is claimed not to even have enough data for a 2-byte
1710              * FCS, or we're already past the end of the captured data.
1711              * Don't slice anything off.
1712              */
1713             next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
1714         } else if (len < reported_len) {
1715             /*
1716              * The packet is claimed to have enough data for a 2-byte FCS, but
1717              * we didn't capture all of the packet.
1718              * Slice off the 2-byte FCS from the reported length, and trim the
1719              * captured length so it's no more than the reported length; that
1720              * will slice off what of the FCS, if any, is in the captured
1721              * length.
1722              */
1723             reported_len -= 2;
1724             if (len > reported_len)
1725                 len = reported_len;
1726             next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
1727         } else {
1728             /*
1729              * We have the entire packet, and it includes a 2-byte FCS.
1730              * Slice it off.
1731              */
1732             len -= 2;
1733             reported_len -= 2;
1734             next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
1735 
1736             /*
1737              * Compute the FCS and put it into the tree.
1738              */
1739             proto_tree_add_checksum(fh_tree, tvb, proto_offset + len, hf_ppp_fcs_16, hf_ppp_fcs_status, &ei_ppp_fcs, pinfo, fcs16(tvb),
1740                             ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1741         }
1742         break;
1743 
1744     case FCS_32:
1745         /*
1746          * Do we have the entire packet, and does it include a 4-byte FCS?
1747          */
1748         len = tvb_captured_length_remaining(tvb, proto_offset);
1749         reported_len = tvb_reported_length_remaining(tvb, proto_offset);
1750         if (reported_len < 4) {
1751             /*
1752              * The packet is claimed not to even have enough data for a 4-byte
1753              * FCS.  Just pass on the tvbuff as is.
1754              */
1755             next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
1756         } else if (len < reported_len) {
1757             /*
1758              * The packet is claimed to have enough data for a 4-byte FCS, but
1759              * we didn't capture all of the packet.
1760              * Slice off the 4-byte FCS from the reported length, and trim the
1761              * captured length so it's no more than the reported length; that
1762              * will slice off what of the FCS, if any, is in the captured
1763              * length.
1764              */
1765             reported_len -= 4;
1766             if (len > reported_len)
1767                 len = reported_len;
1768             next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
1769         } else {
1770             /*
1771              * We have the entire packet, and it includes a 4-byte FCS.
1772              * Slice it off.
1773              */
1774             len -= 4;
1775             reported_len -= 4;
1776             next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
1777 
1778             /*
1779              * Compute the FCS and put it into the tree.
1780              */
1781             proto_tree_add_checksum(fh_tree, tvb, proto_offset + len, hf_ppp_fcs_32, hf_ppp_fcs_status, &ei_ppp_fcs, pinfo, fcs32(tvb),
1782                             ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1783         }
1784         break;
1785 
1786     default:
1787         DISSECTOR_ASSERT_NOT_REACHED();
1788         next_tvb = NULL;
1789         break;
1790     }
1791 
1792     return next_tvb;
1793 }
1794 
1795 static gboolean
capture_ppp_hdlc(const guchar * pd,int offset,int len,capture_packet_info_t * cpinfo,const union wtap_pseudo_header * pseudo_header _U_)1796 capture_ppp_hdlc(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
1797 {
1798     if (!BYTES_ARE_IN_FRAME(offset, len, 2))
1799         return FALSE;
1800 
1801     if (pd[0] == CHDLC_ADDR_UNICAST || pd[0] == CHDLC_ADDR_MULTICAST)
1802         return call_capture_dissector(chdlc_cap_handle, pd, offset, len, cpinfo, pseudo_header);
1803 
1804     if (!BYTES_ARE_IN_FRAME(offset, len, 4))
1805         return FALSE;
1806 
1807     return try_capture_dissector("ppp_hdlc", pntoh16(&pd[offset + 2]), pd, offset + 4, len, cpinfo, pseudo_header);
1808 }
1809 
1810 static int
dissect_lcp_vendor_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1811 dissect_lcp_vendor_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1812 {
1813     proto_tree *field_tree;
1814     proto_item *ti;
1815     int offset = 0;
1816     int len = tvb_reported_length(tvb);
1817 
1818     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_vendor, ett_lcp_vendor_opt, 6,
1819                              &field_tree, &ti))
1820         return tvb_captured_length(tvb);
1821 
1822     proto_tree_add_item(field_tree, hf_lcp_opt_oui, tvb, offset + 2, 3, ENC_BIG_ENDIAN);
1823 
1824     proto_tree_add_item(field_tree, hf_lcp_opt_kind, tvb, offset + 5, 1,
1825         ENC_BIG_ENDIAN);
1826     if (len > 6) {
1827         proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset + 6,
1828             len - 6, ENC_NA);
1829     }
1830 
1831     return tvb_captured_length(tvb);
1832 }
1833 
1834 static int
dissect_lcp_mru_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1835 dissect_lcp_mru_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1836 {
1837     proto_tree *field_tree;
1838     proto_item *ti;
1839     guint32 mru;
1840     int offset = 0;
1841 
1842     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
1843                              proto_lcp_option_mru, ett_lcp_mru_opt, 4,
1844                              &field_tree, &ti))
1845         return tvb_captured_length(tvb);
1846 
1847     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mru, tvb, offset + 2, 2,
1848         ENC_BIG_ENDIAN, &mru);
1849     proto_item_append_text(ti, ": %u", mru);
1850     return tvb_captured_length(tvb);
1851 }
1852 
1853 static int
dissect_lcp_async_map_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1854 dissect_lcp_async_map_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1855 {
1856     proto_tree *field_tree;
1857     proto_item *tf, *ti;
1858     int offset = 0;
1859     static int * const asyncmap_fields[] = {
1860         &hf_lcp_opt_asyncmap_us,  &hf_lcp_opt_asyncmap_rs,
1861         &hf_lcp_opt_asyncmap_gs,  &hf_lcp_opt_asyncmap_fs,
1862         &hf_lcp_opt_asyncmap_esc, &hf_lcp_opt_asyncmap_sub,
1863         &hf_lcp_opt_asyncmap_em,  &hf_lcp_opt_asyncmap_can,
1864         &hf_lcp_opt_asyncmap_etb, &hf_lcp_opt_asyncmap_syn,
1865         &hf_lcp_opt_asyncmap_nak, &hf_lcp_opt_asyncmap_dc4,
1866         &hf_lcp_opt_asyncmap_dc3, &hf_lcp_opt_asyncmap_dc2,
1867         &hf_lcp_opt_asyncmap_dc1, &hf_lcp_opt_asyncmap_dle,
1868         &hf_lcp_opt_asyncmap_si,  &hf_lcp_opt_asyncmap_so,
1869         &hf_lcp_opt_asyncmap_cr,  &hf_lcp_opt_asyncmap_ff,
1870         &hf_lcp_opt_asyncmap_vt,  &hf_lcp_opt_asyncmap_lf,
1871         &hf_lcp_opt_asyncmap_ht,  &hf_lcp_opt_asyncmap_bs,
1872         &hf_lcp_opt_asyncmap_bel, &hf_lcp_opt_asyncmap_ack,
1873         &hf_lcp_opt_asyncmap_enq, &hf_lcp_opt_asyncmap_eot,
1874         &hf_lcp_opt_asyncmap_etx, &hf_lcp_opt_asyncmap_stx,
1875         &hf_lcp_opt_asyncmap_soh, &hf_lcp_opt_asyncmap_nul,
1876         NULL
1877     };
1878 
1879     static const char *ctrlchars[32] = {
1880         "NUL", "SOH",       "STX", "ETX",        "EOT", "ENQ", "ACK", "BEL",
1881         "BS",  "HT",        "LF",  "VT",         "FF",  "CR",  "SO",  "SI",
1882         "DLE", "DC1 (XON)", "DC2", "DC3 (XOFF)", "DC4", "NAK", "SYN", "ETB",
1883         "CAN", "EM",        "SUB", "ESC",        "FS",  "GS",  "RS",  "US"
1884     };
1885 
1886     guint32 map;
1887     gboolean anyctrlchars;
1888     int i;
1889 
1890     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
1891                              proto_lcp_option_async_map, ett_lcp_asyncmap_opt, 6,
1892                              &field_tree, &tf))
1893         return tvb_captured_length(tvb);
1894 
1895     map = tvb_get_ntohl(tvb, offset + 2);
1896     proto_item_append_text(tf, ": 0x%08x", map);
1897 
1898     ti = proto_tree_add_bitmask(field_tree, tvb, offset + 2,
1899         hf_lcp_opt_asyncmap, ett_lcp_asyncmap_opt, asyncmap_fields,
1900         ENC_BIG_ENDIAN);
1901 
1902     if (map == 0x00000000) {
1903         proto_item_append_text(tf, " (None)");
1904         proto_item_append_text(ti, " (None)");
1905     } else if (map == 0xffffffff) {
1906         proto_item_append_text(tf, " (All)");
1907         proto_item_append_text(ti, " (All)");
1908     } else {
1909         for (anyctrlchars = FALSE, i = 31; i >= 0; i--) {
1910             if (map & (1 << i)) {
1911                 if (anyctrlchars)
1912                     proto_item_append_text(tf, ", %s", ctrlchars[i]);
1913                 else {
1914                     anyctrlchars = TRUE;
1915                     proto_item_append_text(tf, "%s", ctrlchars[i]);
1916                 }
1917             }
1918         }
1919         proto_item_append_text(tf, ")");
1920     }
1921 
1922     return tvb_captured_length(tvb);
1923 }
1924 
1925 static int
dissect_lcp_authprot_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1926 dissect_lcp_authprot_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1927 {
1928     proto_tree *field_tree;
1929     proto_item *ti;
1930     guint32 protocol;
1931     int offset = 0;
1932     int length = tvb_reported_length(tvb);
1933 
1934     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_authprot, ett_lcp_authprot_opt, 4,
1935                              &field_tree, &ti))
1936         return tvb_captured_length(tvb);
1937 
1938     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_auth_protocol, tvb, offset + 2,
1939         2, ENC_BIG_ENDIAN, &protocol);
1940     proto_item_append_text(ti, ": %s (0x%02x)", val_to_str_ext_const(protocol, &ppp_vals_ext, "Unknown"),
1941         protocol);
1942 
1943     if (length > 4) {
1944         offset += 4;
1945         length -= 4;
1946         if (protocol == PPP_CHAP) {
1947             proto_tree_add_item(field_tree, hf_lcp_opt_algorithm, tvb, offset,
1948                 1, ENC_BIG_ENDIAN);
1949             if (length > 1) {
1950                 proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb,
1951                     offset + 1, length - 1, ENC_NA);
1952             }
1953         } else {
1954             proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
1955                 length, ENC_NA);
1956         }
1957     }
1958 
1959     return tvb_captured_length(tvb);
1960 }
1961 
1962 static int
dissect_lcp_qualprot_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1963 dissect_lcp_qualprot_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1964 {
1965     proto_tree *field_tree;
1966     proto_item *ti;
1967     guint32 protocol;
1968     int offset = 0;
1969     int length = tvb_reported_length(tvb);
1970 
1971     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_qualprot, ett_lcp_qualprot_opt, 4,
1972                              &field_tree, &ti))
1973         return tvb_captured_length(tvb);
1974 
1975     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_quality_protocol, tvb, offset + 2,
1976         2, ENC_BIG_ENDIAN, &protocol);
1977     proto_item_append_text(ti, ": %s (0x%02x)", val_to_str_ext_const(protocol, &ppp_vals_ext, "Unknown"),
1978         protocol);
1979 
1980     if (length > 4) {
1981         proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset + 4,
1982             length + 4, ENC_NA);
1983     }
1984 
1985     return tvb_captured_length(tvb);
1986 }
1987 
1988 static int
dissect_lcp_magicnumber_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1989 dissect_lcp_magicnumber_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1990 {
1991     proto_tree *field_tree;
1992     proto_item *ti;
1993     guint32 magic_number;
1994     int offset = 0;
1995 
1996     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
1997                              proto_lcp_option_magicnumber, ett_lcp_magicnumber_opt, 6,
1998                              &field_tree, &ti))
1999         return tvb_captured_length(tvb);
2000 
2001     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_magic_number, tvb, offset + 2,
2002         4, ENC_BIG_ENDIAN, &magic_number);
2003     proto_item_append_text(ti, ": 0x%08x", magic_number);
2004 
2005     return tvb_captured_length(tvb);
2006 }
2007 
2008 static int
dissect_lcp_linkqualmon_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2009 dissect_lcp_linkqualmon_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2010 {
2011     proto_tree *field_tree;
2012     proto_item *ti, *tf;
2013     guint32 reportingperiod;
2014     int offset = 0;
2015 
2016     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2017                              proto_lcp_option_linkqualmon, ett_lcp_linkqualmon_opt, 6,
2018                              &field_tree, &tf))
2019         return tvb_captured_length(tvb);
2020 
2021     ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_reportingperiod,
2022         tvb, offset + 2, 4, ENC_BIG_ENDIAN, &reportingperiod);
2023     proto_item_append_text(tf, ": %u microsecond%s", reportingperiod, plurality(reportingperiod, "", "s"));
2024     if (reportingperiod == 0)
2025     {
2026         proto_item_append_text(ti, " [illegal]");
2027         proto_item_append_text(tf, " [illegal]");
2028     }
2029 
2030     return tvb_captured_length(tvb);
2031 }
2032 
2033 static int
dissect_lcp_field_compress(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2034 dissect_lcp_field_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2035 {
2036     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_field_compress, ett_lcp_pcomp_opt);
2037 }
2038 
2039 static int
dissect_lcp_addr_field_compress(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2040 dissect_lcp_addr_field_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2041 {
2042     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_addr_field_compress, ett_lcp_acccomp_opt);
2043 }
2044 
2045 static int
dissect_lcp_fcs_alternatives_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2046 dissect_lcp_fcs_alternatives_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2047 {
2048     proto_tree *field_tree;
2049     proto_item *tf;
2050     int offset = 0;
2051     static int * const fcs_alternatives_fields[] = {
2052         &hf_lcp_opt_fcs_alternatives_ccitt32,
2053         &hf_lcp_opt_fcs_alternatives_ccitt16,
2054         &hf_lcp_opt_fcs_alternatives_null,
2055         NULL
2056     };
2057 
2058     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2059                              proto_lcp_option_fcs_alternatives, ett_lcp_fcs_alternatives_opt, 3,
2060                              &field_tree, &tf))
2061         return tvb_captured_length(tvb);
2062 
2063     proto_tree_add_bitmask(field_tree, tvb, offset + 2,
2064         hf_lcp_opt_fcs_alternatives, ett_lcp_fcs_alternatives_opt,
2065         fcs_alternatives_fields, ENC_NA);
2066     proto_item_append_text(tf, ": 0x%02x", tvb_get_guint8(tvb, offset + 2));
2067     return tvb_captured_length(tvb);
2068 }
2069 
2070 static int
dissect_lcp_self_describing_pad_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2071 dissect_lcp_self_describing_pad_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2072 {
2073     proto_tree *field_tree;
2074     proto_item *tf, *ti;
2075     guint32 maximum;
2076     int offset = 0;
2077 
2078     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2079                              proto_lcp_option_self_desc_pad, ett_lcp_self_desc_pad_opt, 3,
2080                              &field_tree, &tf))
2081         return tvb_captured_length(tvb);
2082 
2083     ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_maximum, tvb,
2084         offset + 2, 1, ENC_BIG_ENDIAN, &maximum);
2085     proto_item_append_text(tf, ": %u octet%s", maximum, plurality(maximum, "", "s"));
2086     if (maximum == 0)
2087     {
2088         proto_item_append_text(ti, " [invalid]");
2089         proto_item_append_text(tf, " [invalid]");
2090     }
2091 
2092     return tvb_captured_length(tvb);
2093 }
2094 
2095 static int
dissect_lcp_numbered_mode_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2096 dissect_lcp_numbered_mode_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2097 {
2098     proto_tree *field_tree;
2099     proto_item *tf, *ti;
2100     guint32 window;
2101     int offset = 0;
2102     int length = tvb_reported_length(tvb);
2103 
2104     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_numbered_mode, ett_lcp_numbered_mode_opt, 3,
2105                              &field_tree, &tf))
2106         return tvb_captured_length(tvb);
2107 
2108     ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_window, tvb,
2109         offset + 2, 1, ENC_BIG_ENDIAN, &window);
2110     proto_item_append_text(tf, ": %u frame%s", window, plurality(window, "", "s"));
2111     if (window == 0 || window > 127)
2112     {
2113         proto_item_append_text(ti, " [invalid]");
2114         proto_item_append_text(tf, " [invalid]");
2115     }
2116     if (length > 3) {
2117         proto_tree_add_item(field_tree, hf_lcp_opt_hdlc_address, tvb,
2118             offset + 3, length - 3, ENC_NA);
2119     }
2120 
2121     return tvb_captured_length(tvb);
2122 }
2123 
2124 /* https://tools.ietf.org/html/rfc1570#section-2.3 only lists 0-4, but
2125  * https://tools.ietf.org/html/draft-ietf-pppext-callback-ds-02 lists 5 as
2126  * "E.165 number", rather than "unassigned", and
2127  * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cbcp/efee6372-3251-471e-a141-71d1e7fef21f
2128  * does indicate 6 as below.  Since 5 is only mentioned in the draft, leave it
2129  * as "unassigned"?
2130  */
2131 static const value_string callback_op_vals[] = {
2132     {0, "Location is determined by user authentication"},
2133     {1, "Message is dialing string"},
2134     {2, "Message is location identifier"},
2135     {3, "Message is E.164"},
2136     {4, "Message is distinguished name"},
2137     {5, "unassigned"}, /* "Message is E.165"? */
2138     {6, "Location is determined during CBCP negotiation"},
2139     {0, NULL}
2140 };
2141 
2142 static int
dissect_lcp_callback_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2143 dissect_lcp_callback_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2144 {
2145     proto_tree *field_tree;
2146     proto_item *tf;
2147     guint32 operation;
2148     int offset = 0;
2149     int length = tvb_reported_length(tvb);
2150 
2151     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_callback, ett_lcp_callback_opt, 3,
2152                              &field_tree, &tf))
2153         return tvb_captured_length(tvb);
2154 
2155     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_operation, tvb, offset + 2, 1,
2156         ENC_BIG_ENDIAN, &operation);
2157     proto_item_append_text(tf, ": %s", val_to_str_const(operation, callback_op_vals, "Unknown"));
2158 
2159     if (length > 3) {
2160         proto_tree_add_item(field_tree, hf_lcp_opt_message, tvb, offset + 3,
2161             length - 3, ENC_NA);
2162     }
2163     return tvb_captured_length(tvb);
2164 }
2165 
2166 static int
dissect_lcp_compound_frames_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2167 dissect_lcp_compound_frames_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2168 {
2169     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_compound_frames, ett_lcp_compound_frames_opt);
2170 }
2171 
2172 static int
dissect_lcp_nomdataencap_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2173 dissect_lcp_nomdataencap_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2174 {
2175     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_nomdataencap, ett_lcp_nomdataencap_opt);
2176 }
2177 
2178 /* https://tools.ietf.org/html/rfc1990#section-5.1.1 */
2179 static int
dissect_lcp_multilink_mrru_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2180 dissect_lcp_multilink_mrru_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2181 {
2182     proto_tree *field_tree;
2183     proto_item *tf;
2184     guint32 mrru;
2185     int offset = 0;
2186 
2187     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2188                              proto_lcp_option_multilink_mrru, ett_lcp_multilink_mrru_opt, 4,
2189                              &field_tree, &tf))
2190         return tvb_captured_length(tvb);
2191 
2192     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mrru, tvb, offset + 2, 2,
2193         ENC_BIG_ENDIAN, &mrru);
2194     proto_item_append_text(tf, ": %u", mrru);
2195     return tvb_captured_length(tvb);
2196 }
2197 
2198 static int
dissect_lcp_multilink_ssnh_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2199 dissect_lcp_multilink_ssnh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2200 {
2201     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_multilink_ssnh, ett_lcp_multilink_ssnh_opt);
2202 }
2203 
2204 #define CLASS_NULL                      0
2205 #define CLASS_LOCAL                     1
2206 #define CLASS_IP                        2
2207 #define CLASS_IEEE_802_1                3
2208 #define CLASS_PPP_MAGIC_NUMBER          4
2209 #define CLASS_PSDN_DIRECTORY_NUMBER     5
2210 
2211 static const value_string multilink_ep_disc_class_vals[] = {
2212     {CLASS_NULL,                  "Null"},
2213     {CLASS_LOCAL,                 "Locally assigned address"},
2214     {CLASS_IP,                    "Internet Protocol (IP) address"},
2215     {CLASS_IEEE_802_1,            "IEEE 802.1 globally assigned MAC address"},
2216     {CLASS_PPP_MAGIC_NUMBER,      "PPP magic-number block"},
2217     {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number"},
2218     {0,                           NULL}
2219 };
2220 
2221 static int
dissect_lcp_multilink_ep_disc_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2222 dissect_lcp_multilink_ep_disc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2223 {
2224     proto_tree *field_tree, *magic_tree;
2225     proto_item *tf, *tm;
2226     guint32 ep_disc_class;
2227     int offset = 0;
2228     int length = tvb_reported_length(tvb);
2229 
2230     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_multilink_ep_disc, ett_lcp_multilink_ep_disc_opt, 3,
2231                              &field_tree, &tf))
2232         return tvb_captured_length(tvb);
2233 
2234     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_ep_disc_class, tvb, offset + 2,
2235         1, ENC_BIG_ENDIAN, &ep_disc_class);
2236     proto_item_append_text(tf, ": Class: %s", val_to_str_const(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"));
2237 
2238     if (length <= 3)
2239         return tvb_captured_length(tvb);
2240 
2241     length -= 3;
2242     offset += 3;
2243     switch (ep_disc_class) {
2244     case CLASS_NULL:
2245         break;
2246 
2247     case CLASS_LOCAL:
2248         proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
2249             length <= 20 ? length : 20, ENC_NA);
2250         break;
2251 
2252     case CLASS_IP:
2253         if (length >= 4) {
2254             proto_tree_add_item(field_tree, hf_lcp_opt_ip_address, tvb, offset,
2255                 4, ENC_BIG_ENDIAN);
2256         } else {
2257             proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
2258                 length, ENC_NA);
2259         }
2260         break;
2261 
2262     case CLASS_IEEE_802_1:
2263         if (length >= 6) {
2264             proto_tree_add_item(field_tree, hf_lcp_opt_802_1_address, tvb,
2265                 offset, 6, ENC_NA);
2266         } else {
2267             proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
2268                 length, ENC_NA);
2269         }
2270         break;
2271 
2272     case CLASS_PPP_MAGIC_NUMBER:
2273         if (length % 4) {
2274             proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
2275                 length, ENC_NA);
2276         } else {
2277             tm = proto_tree_add_item(field_tree, hf_lcp_opt_magic_block, tvb,
2278                 offset, length <= 20 ? length : 20, ENC_NA);
2279             magic_tree = proto_item_add_subtree(tm, ett_lcp_magic_block);
2280             for ( ; length >= 4; length -= 4, offset += 4) {
2281                 proto_tree_add_item(magic_tree, hf_lcp_opt_magic_number, tvb,
2282                     offset, 4, ENC_BIG_ENDIAN);
2283             }
2284         }
2285         break;
2286 
2287     case CLASS_PSDN_DIRECTORY_NUMBER:
2288         proto_tree_add_item(field_tree, hf_lcp_opt_psndn, tvb, offset,
2289             length > 15 ? 15 : length, ENC_NA);
2290         break;
2291 
2292     default:
2293         proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset, length,
2294             ENC_NA);
2295         break;
2296     }
2297     return tvb_captured_length(tvb);
2298 }
2299 
2300 static const value_string dce_id_mode_vals[] = {
2301     {1, "Mode-1 (No Additional Negotiation)"},
2302     {2, "Mode-2 (Full PPP Negotiation and State Machine)"},
2303     {0, NULL}
2304 };
2305 
2306 static int
dissect_lcp_dce_identifier_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2307 dissect_lcp_dce_identifier_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2308 {
2309     proto_tree *field_tree;
2310     proto_item *tf;
2311     int offset = 0;
2312     guint32 mode;
2313 
2314     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2315                              proto_lcp_option_dce_identifier, ett_lcp_dce_identifier_opt, 3,
2316                              &field_tree, &tf))
2317         return tvb_captured_length(tvb);
2318 
2319     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mode, tvb, offset + 2, 1,
2320         ENC_BIG_ENDIAN, &mode);
2321     proto_item_append_text(tf, ": %s", val_to_str_const(mode, dce_id_mode_vals, "Unknown"));
2322 
2323     return tvb_captured_length(tvb);
2324 }
2325 
2326 static int
dissect_lcp_multilink_pp_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2327 dissect_lcp_multilink_pp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2328 {
2329     proto_tree *field_tree;
2330     proto_item *tf;
2331     int offset = 0;
2332 
2333     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2334                              proto_lcp_option_multilink_pp, ett_lcp_multilink_pp_opt, 4,
2335                              &field_tree, &tf))
2336         return tvb_captured_length(tvb);
2337 
2338     proto_tree_add_item(field_tree, hf_lcp_opt_unused, tvb, offset + 2, 2, ENC_NA);
2339     return tvb_captured_length(tvb);
2340 }
2341 
2342 static int
dissect_lcp_bacp_link_discriminator_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2343 dissect_lcp_bacp_link_discriminator_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2344 {
2345     proto_tree *field_tree;
2346     proto_item *tf;
2347     int offset = 0;
2348     guint32 link_discrim;
2349 
2350     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2351                              proto_lcp_option_link_discrim, ett_lcp_bacp_link_discrim_opt, 4,
2352                              &field_tree, &tf))
2353         return tvb_captured_length(tvb);
2354 
2355     proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_link_discrim, tvb, offset + 2,
2356         2, ENC_BIG_ENDIAN, &link_discrim);
2357     proto_item_append_text(tf, ": %u (0x%04x)", link_discrim, link_discrim);
2358     return tvb_captured_length(tvb);
2359 }
2360 
2361 /* Assuming it's this one:
2362  * https://tools.ietf.org/html/draft-ietf-pppext-link-negot-00
2363  */
2364 static int
dissect_lcp_auth_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2365 dissect_lcp_auth_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2366 {
2367     proto_tree *field_tree;
2368     proto_item *tf;
2369     guint32 id_len;
2370     int offset = 0;
2371     int length;
2372 
2373     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_auth, ett_lcp_auth_opt, 3,
2374                              &field_tree, &tf))
2375         return tvb_captured_length(tvb);
2376 
2377     offset += 2;
2378     proto_tree_add_item_ret_length(field_tree, hf_lcp_opt_id, tvb, offset, 1, ENC_BIG_ENDIAN, &id_len);
2379 
2380     length = tvb_reported_length_remaining(tvb, offset);
2381     if ((int)id_len < length) {
2382         length -= id_len;
2383         offset += id_len;
2384         proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
2385             length, ENC_NA);
2386     }
2387     return tvb_captured_length(tvb);
2388 }
2389 
2390 /* Assuming it's this one:
2391  * https://tools.ietf.org/html/draft-ietf-pppext-cobs-00
2392  */
2393 static int
dissect_lcp_cobs_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2394 dissect_lcp_cobs_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2395 {
2396     proto_tree *field_tree;
2397     proto_item *tf;
2398     int offset = 0;
2399     static int * const cobs_flags_fields[] = {
2400         &hf_lcp_opt_cobs_flags_res,
2401         &hf_lcp_opt_cobs_flags_pre,
2402         &hf_lcp_opt_cobs_flags_zxe,
2403         NULL
2404     };
2405 
2406     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2407                              proto_lcp_option_cobs, ett_lcp_cobs_opt, 3,
2408                              &field_tree, &tf))
2409         return tvb_captured_length(tvb);
2410 
2411     proto_tree_add_bitmask(field_tree, tvb, offset + 2, hf_lcp_opt_cobs_flags,
2412         ett_lcp_cobs_opt, cobs_flags_fields, ENC_NA);
2413     return tvb_captured_length(tvb);
2414 }
2415 
2416 static int
dissect_lcp_prefix_elision_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2417 dissect_lcp_prefix_elision_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2418 {
2419     proto_tree *field_tree;
2420     proto_item *tf;
2421     guint8 pre_len;
2422     int offset = 0;
2423     int length = tvb_reported_length(tvb);
2424 
2425     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_prefix_elision, ett_lcp_prefix_elision_opt, 2,
2426                              &field_tree, &tf))
2427         return tvb_captured_length(tvb);
2428 
2429     if (length > 2) {
2430         length -= 2;
2431         offset += 2;
2432         while (length >= 2) {
2433             proto_tree_add_item(field_tree, hf_lcp_opt_class, tvb, offset, 1,
2434                 ENC_BIG_ENDIAN);
2435             pre_len = tvb_get_guint8(tvb, offset + 1);
2436             if (pre_len + 2 <= length) {
2437                 proto_tree_add_item(field_tree, hf_lcp_opt_prefix, tvb,
2438                     offset + 2, 1, ENC_NA);
2439                 length -= (2 + pre_len);
2440             } else {
2441                 /* Prefix length doesn't make sense, so bail out */
2442                 length = 0;
2443             }
2444         }
2445     }
2446 
2447     return tvb_captured_length(tvb);
2448 }
2449 
2450 static const value_string ml_hdr_fmt_code_vals[] = {
2451     {2, "Long sequence number fragment format with classes"},
2452     {6, "Short sequence number fragment format with classes"},
2453     {0, NULL}
2454 };
2455 
2456 static int
dissect_lcp_multilink_hdr_fmt_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2457 dissect_lcp_multilink_hdr_fmt_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2458 {
2459     proto_tree *field_tree;
2460     proto_item *tf;
2461     int offset = 0;
2462 
2463     if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
2464                              proto_lcp_option_multilink_hdr_fmt, ett_multilink_hdr_fmt_opt, 4,
2465                              &field_tree, &tf))
2466         return tvb_captured_length(tvb);
2467 
2468     proto_tree_add_item(field_tree, hf_lcp_opt_code, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
2469     proto_tree_add_item(field_tree, hf_lcp_opt_max_susp_classes, tvb,
2470         offset + 3, 1, ENC_BIG_ENDIAN);
2471     return tvb_captured_length(tvb);
2472 }
2473 
2474 
2475 /* Character sets from https://www.iana.org/assignments/character-sets. */
2476 static const value_string charset_vals[] = {
2477     {3,    "ANSI_X3.4-1968"},
2478     {4,    "ISO_8859-1:1987"},
2479     {5,    "ISO_8859-2:1987"},
2480     {6,    "ISO_8859-3:1988"},
2481     {7,    "ISO_8859-4:1988"},
2482     {8,    "ISO_8859-5:1988"},
2483     {9,    "ISO_8859-6:1987"},
2484     {10,   "ISO_8859-7:1987"},
2485     {11,   "ISO_8859-8:1988"},
2486     {12,   "ISO_8859-9:1989"},
2487     {13,   "ISO-8859-10"},
2488     {14,   "ISO_6937-2-add"},
2489     {15,   "JIS_X0201"},
2490     {16,   "JIS_Encoding"},
2491     {17,   "Shift_JIS"},
2492     {18,   "Extended_UNIX_Code_Packed_Format_for_Japanese"},
2493     {19,   "Extended_UNIX_Code_Fixed_Width_for_Japanese"},
2494     {20,   "BS_4730"},
2495     {21,   "SEN_850200_C"},
2496     {22,   "IT"},
2497     {23,   "ES"},
2498     {24,   "DIN_66003"},
2499     {25,   "NS_4551-1"},
2500     {26,   "NF_Z_62-010"},
2501     {27,   "ISO-10646-UTF-1"},
2502     {28,   "ISO_646.basic:1983"},
2503     {29,   "INVARIANT"},
2504     {30,   "ISO_646.irv:1983"},
2505     {31,   "NATS-SEFI"},
2506     {32,   "NATS-SEFI-ADD"},
2507     {33,   "NATS-DANO"},
2508     {34,   "NATS-DANO-ADD"},
2509     {35,   "SEN_850200_B"},
2510     {36,   "KS_C_5601-1987"},
2511     {37,   "ISO-2022-KR"},
2512     {38,   "EUC-KR"},
2513     {39,   "ISO-2022-JP"},
2514     {40,   "ISO-2022-JP-2"},
2515     {41,   "JIS_C6220-1969-jp"},
2516     {42,   "JIS_C6220-1969-ro"},
2517     {43,   "PT"},
2518     {44,   "greek7-old"},
2519     {45,   "latin-greek"},
2520     {46,   "NF_Z_62-010_(1973)"},
2521     {47,   "Latin-greek-1"},
2522     {48,   "ISO_5427"},
2523     {49,   "JIS_C6226-1978"},
2524     {50,   "BS_viewdata"},
2525     {51,   "INIS"},
2526     {52,   "INIS-8"},
2527     {53,   "INIS-cyrillic"},
2528     {54,   "ISO_5427:1981"},
2529     {55,   "ISO_5428:1980"},
2530     {56,   "GB_1988-80"},
2531     {57,   "GB_2312-80"},
2532     {58,   "NS_4551-2"},
2533     {59,   "videotex-suppl"},
2534     {60,   "PT2"},
2535     {61,   "ES2"},
2536     {62,   "MSZ_7795.3"},
2537     {63,   "JIS_C6226-1983"},
2538     {64,   "greek7"},
2539     {65,   "ASMO_449"},
2540     {66,   "iso-ir-90"},
2541     {67,   "JIS_C6229-1984-a"},
2542     {68,   "JIS_C6229-1984-b"},
2543     {69,   "JIS_C6229-1984-b-add"},
2544     {70,   "JIS_C6229-1984-hand"},
2545     {71,   "JIS_C6229-1984-hand-add"},
2546     {72,   "JIS_C6229-1984-kana"},
2547     {73,   "ISO_2033-1983"},
2548     {74,   "ANSI_X3.110-1983"},
2549     {75,   "T.61-7bit"},
2550     {76,   "T.61-8bit"},
2551     {77,   "ECMA-cyrillic"},
2552     {78,   "CSA_Z243.4-1985-1"},
2553     {79,   "CSA_Z243.4-1985-2"},
2554     {80,   "CSA_Z243.4-1985-gr"},
2555     {81,   "ISO_8859-6-E"},
2556     {82,   "ISO_8859-6-I"},
2557     {83,   "T.101-G2"},
2558     {84,   "ISO_8859-8-E"},
2559     {85,   "ISO_8859-8-I"},
2560     {86,   "CSN_369103"},
2561     {87,   "JUS_I.B1.002"},
2562     {88,   "IEC_P27-1"},
2563     {89,   "JUS_I.B1.003-serb"},
2564     {90,   "JUS_I.B1.003-mac"},
2565     {91,   "greek-ccitt"},
2566     {92,   "NC_NC00-10:81"},
2567     {93,   "ISO_6937-2-25"},
2568     {94,   "GOST_19768-74"},
2569     {95,   "ISO_8859-supp"},
2570     {96,   "ISO_10367-box"},
2571     {97,   "latin-lap"},
2572     {98,   "JIS_X0212-1990"},
2573     {99,   "DS_2089"},
2574     {100,  "us-dk"},
2575     {101,  "dk-us"},
2576     {102,  "KSC5636"},
2577     {103,  "UNICODE-1-1-UTF-7"},
2578     {104,  "ISO-2022-CN"},
2579     {105,  "ISO-2022-CN-EXT"},
2580     {106,  "UTF-8"},
2581     {109,  "ISO-8859-13"},
2582     {110,  "ISO-8859-14"},
2583     {111,  "ISO-8859-15"},
2584     {112,  "ISO-8859-16"},
2585     {113,  "GBK"},
2586     {114,  "GB18030"},
2587     {115,  "OSD_EBCDIC_DF04_15"},
2588     {116,  "OSD_EBCDIC_DF03_IRV"},
2589     {117,  "OSD_EBCDIC_DF04_1"},
2590     {118,  "ISO-11548-1"},
2591     {119,  "KZ-1048"},
2592     {1000, "ISO-10646-UCS-2"},
2593     {1001, "ISO-10646-UCS-4"},
2594     {1002, "ISO-10646-UCS-Basic"},
2595     {1003, "ISO-10646-Unicode-Latin1"},
2596     {1004, "ISO-10646-J-1"},
2597     {1005, "ISO-Unicode-IBM-1261"},
2598     {1006, "ISO-Unicode-IBM-1268"},
2599     {1007, "ISO-Unicode-IBM-1276"},
2600     {1008, "ISO-Unicode-IBM-1264"},
2601     {1009, "ISO-Unicode-IBM-1265"},
2602     {1010, "UNICODE-1-1"},
2603     {1011, "SCSU"},
2604     {1012, "UTF-7"},
2605     {1013, "UTF-16BE"},
2606     {1014, "UTF-16LE"},
2607     {1015, "UTF-16"},
2608     {1016, "CESU-8"},
2609     {1017, "UTF-32"},
2610     {1018, "UTF-32BE"},
2611     {1019, "UTF-32LE"},
2612     {1020, "BOCU-1"},
2613     {2000, "ISO-8859-1-Windows-3.0-Latin-1"},
2614     {2001, "ISO-8859-1-Windows-3.1-Latin-1"},
2615     {2002, "ISO-8859-2-Windows-Latin-2"},
2616     {2003, "ISO-8859-9-Windows-Latin-5"},
2617     {2004, "hp-roman8"},
2618     {2005, "Adobe-Standard-Encoding"},
2619     {2006, "Ventura-US"},
2620     {2007, "Ventura-International"},
2621     {2008, "DEC-MCS"},
2622     {2009, "IBM850"},
2623     {2010, "IBM852"},
2624     {2011, "IBM437"},
2625     {2012, "PC8-Danish-Norwegian"},
2626     {2013, "IBM862"},
2627     {2014, "PC8-Turkish"},
2628     {2015, "IBM-Symbols"},
2629     {2016, "IBM-Thai"},
2630     {2017, "HP-Legal"},
2631     {2018, "HP-Pi-font"},
2632     {2019, "HP-Math8"},
2633     {2020, "Adobe-Symbol-Encoding"},
2634     {2021, "HP-DeskTop"},
2635     {2022, "Ventura-Math"},
2636     {2023, "Microsoft-Publishing"},
2637     {2024, "Windows-31J"},
2638     {2025, "GB2312"},
2639     {2026, "Big5"},
2640     {2027, "macintosh"},
2641     {2028, "IBM037"},
2642     {2029, "IBM038"},
2643     {2030, "IBM273"},
2644     {2031, "IBM274"},
2645     {2032, "IBM275"},
2646     {2033, "IBM277"},
2647     {2034, "IBM278"},
2648     {2035, "IBM280"},
2649     {2036, "IBM281"},
2650     {2037, "IBM284"},
2651     {2038, "IBM285"},
2652     {2039, "IBM290"},
2653     {2040, "IBM297"},
2654     {2041, "IBM420"},
2655     {2042, "IBM423"},
2656     {2043, "IBM424"},
2657     {2044, "IBM500"},
2658     {2045, "IBM851"},
2659     {2046, "IBM855"},
2660     {2047, "IBM857"},
2661     {2048, "IBM860"},
2662     {2049, "IBM861"},
2663     {2050, "IBM863"},
2664     {2051, "IBM864"},
2665     {2052, "IBM865"},
2666     {2053, "IBM868"},
2667     {2054, "IBM869"},
2668     {2055, "IBM870"},
2669     {2056, "IBM871"},
2670     {2057, "IBM880"},
2671     {2058, "IBM891"},
2672     {2059, "IBM903"},
2673     {2060, "IBM904"},
2674     {2061, "IBM905"},
2675     {2062, "IBM918"},
2676     {2063, "IBM1026"},
2677     {2064, "EBCDIC-AT-DE"},
2678     {2065, "EBCDIC-AT-DE-A"},
2679     {2066, "EBCDIC-CA-FR"},
2680     {2067, "EBCDIC-DK-NO"},
2681     {2068, "EBCDIC-DK-NO-A"},
2682     {2069, "EBCDIC-FI-SE"},
2683     {2070, "EBCDIC-FI-SE-A"},
2684     {2071, "EBCDIC-FR"},
2685     {2072, "EBCDIC-IT"},
2686     {2073, "EBCDIC-PT"},
2687     {2074, "EBCDIC-ES"},
2688     {2075, "EBCDIC-ES-A"},
2689     {2076, "EBCDIC-ES-S"},
2690     {2077, "EBCDIC-UK"},
2691     {2078, "EBCDIC-US"},
2692     {2079, "UNKNOWN-8BIT"},
2693     {2080, "MNEMONIC"},
2694     {2081, "MNEM"},
2695     {2082, "VISCII"},
2696     {2083, "VIQR"},
2697     {2084, "KOI8-R"},
2698     {2085, "HZ-GB-2312"},
2699     {2086, "IBM866"},
2700     {2087, "IBM775"},
2701     {2088, "KOI8-U"},
2702     {2089, "IBM00858"},
2703     {2090, "IBM00924"},
2704     {2091, "IBM01140"},
2705     {2092, "IBM01141"},
2706     {2093, "IBM01142"},
2707     {2094, "IBM01143"},
2708     {2095, "IBM01144"},
2709     {2096, "IBM01145"},
2710     {2097, "IBM01146"},
2711     {2098, "IBM01147"},
2712     {2099, "IBM01148"},
2713     {2100, "IBM01149"},
2714     {2101, "Big5-HKSCS"},
2715     {2102, "IBM1047"},
2716     {2103, "PTCP154"},
2717     {2104, "Amiga-1251"},
2718     {2105, "KOI7-switched"},
2719     {2106, "BRF"},
2720     {2107, "TSCII"},
2721     {2108, "CP51932"},
2722     {2109, "windows-874"},
2723     {2250, "windows-1250"},
2724     {2251, "windows-1251"},
2725     {2252, "windows-1252"},
2726     {2253, "windows-1253"},
2727     {2254, "windows-1254"},
2728     {2255, "windows-1255"},
2729     {2256, "windows-1256"},
2730     {2257, "windows-1257"},
2731     {2258, "windows-1258"},
2732     {2259, "TIS-620"},
2733     {2260, "CP50220"},
2734     {0,    NULL}
2735 };
2736 static value_string_ext charset_vals_ext = VALUE_STRING_EXT_INIT(charset_vals);
2737 
2738 static int
dissect_lcp_internationalization_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2739 dissect_lcp_internationalization_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2740 {
2741     proto_tree *field_tree;
2742     proto_item *tf;
2743     int offset = 0;
2744     int length = tvb_reported_length(tvb);
2745 
2746     if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_internationalization, ett_lcp_internationalization_opt, 7,
2747                              &field_tree, &tf))
2748         return tvb_captured_length(tvb);
2749 
2750     proto_tree_add_item(field_tree, hf_lcp_opt_MIBenum, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
2751     proto_tree_add_item(field_tree, hf_lcp_opt_language_tag, tvb, offset + 6,
2752         length - 6, ENC_ASCII|ENC_NA);
2753 
2754     return tvb_captured_length(tvb);
2755 }
2756 
2757 static int
dissect_lcp_sonet_sdh_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2758 dissect_lcp_sonet_sdh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2759 {
2760     return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_sonet_sdh, ett_lcp_sonet_sdh_opt);
2761 }
2762 
2763 static void
dissect_ipcp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)2764 dissect_ipcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
2765     const char *name)
2766 {
2767     guint8 type;
2768 
2769     type = tvb_get_guint8(tvb, offset);
2770     proto_tree_add_uint_format_value(tree, hf_ipcp_opt_type, tvb, offset, 1,
2771         type, "%s (%u)", name, type);
2772     proto_tree_add_item(tree, hf_ipcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2773 }
2774 
2775 static gboolean
dissect_ipcp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)2776 dissect_ipcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2777                              int proto, int ett, int expected_length,
2778                              proto_tree** ret_tree, proto_item** ret_item)
2779 {
2780     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
2781         return FALSE;
2782 
2783     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
2784     *ret_tree = proto_item_add_subtree(*ret_item, ett);
2785 
2786     dissect_ipcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
2787     return TRUE;
2788 }
2789 
2790 /* https://tools.ietf.org/html/rfc1172#section-5.1 */
2791 static int
dissect_ipcp_addrs_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2792 dissect_ipcp_addrs_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2793 {
2794     proto_tree *field_tree;
2795     proto_item *tf;
2796     int offset = 0;
2797 
2798     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_addrs , ett_ipcp_ipaddrs_opt, 10,
2799                                   &field_tree, &tf))
2800         return tvb_captured_length(tvb);
2801 
2802     proto_tree_add_item(field_tree, hf_ipcp_opt_src_address, tvb, offset + 2,
2803         4, ENC_BIG_ENDIAN);
2804     proto_tree_add_item(field_tree, hf_ipcp_opt_dst_address, tvb, offset + 6,
2805         4, ENC_BIG_ENDIAN);
2806     return tvb_captured_length(tvb);
2807 }
2808 
2809 static const true_false_string tfs_comp_slot_id = {
2810     "The slot identifier may be compressed",
2811     "The slot identifier must not be compressed"
2812 };
2813 
2814 /* https://tools.ietf.org/html/rfc1332#section-3.2 */
2815 static int
dissect_ipcp_compress_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2816 dissect_ipcp_compress_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2817 {
2818     proto_tree *field_tree;
2819     proto_item *tf;
2820     int offset = 0;
2821     int length = tvb_reported_length(tvb);
2822     guint16     us;
2823 
2824     tf = proto_tree_add_item(tree, proto_ipcp_option_compress, tvb, 0, length, ENC_NA);
2825     field_tree = proto_item_add_subtree(tf, ett_ipcp_compress_opt);
2826 
2827     dissect_ipcp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_ipcp_option_compress));
2828     proto_tree_add_item(field_tree, hf_ipcp_opt_compress_proto, tvb,
2829         offset + 2, 2, ENC_BIG_ENDIAN);
2830     us = tvb_get_ntohs(tvb, offset + 2);
2831     switch (us) {
2832     case IPCP_ROHC:
2833         proto_tree_add_item(field_tree, hf_ipcp_opt_max_cid, tvb, offset + 4,
2834             2, ENC_BIG_ENDIAN);
2835         proto_tree_add_item(field_tree, hf_ipcp_opt_mrru, tvb, offset + 6, 2,
2836             ENC_BIG_ENDIAN);
2837         proto_tree_add_item(field_tree, hf_ipcp_opt_max_header, tvb,
2838             offset + 8, 2, ENC_BIG_ENDIAN);
2839 
2840         if (length > 10) {
2841             proto_tree *subopt_tree;
2842 
2843             /* suboptions */
2844             offset += 10;
2845             length -= 10;
2846             subopt_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, length,
2847                 ett_ipcp_compress_opt, NULL, "Suboptions: (%u byte%s)", length, plurality(length, "", "s"));
2848 
2849             ppp_dissect_options(tvb, offset, length, ipcp_rohc_suboption_table, pinfo, subopt_tree);
2850         }
2851         break;
2852 
2853     case IPCP_COMPRESS_VJ_1172:
2854     case IPCP_COMPRESS_VJ:
2855         proto_tree_add_item(field_tree, hf_ipcp_opt_max_slot_id, tvb,
2856             offset + 4, 1, ENC_BIG_ENDIAN);
2857         proto_tree_add_item(field_tree, hf_ipcp_opt_comp_slot_id, tvb,
2858             offset + 5, 1, ENC_NA);
2859       break;
2860 
2861     case IPCP_COMPRESS_IPHC:
2862         proto_tree_add_item(field_tree, hf_ipcp_opt_tcp_space, tvb, offset + 4,
2863             2, ENC_BIG_ENDIAN);
2864         proto_tree_add_item(field_tree, hf_ipcp_opt_non_tcp_space, tvb,
2865             offset + 6, 2, ENC_BIG_ENDIAN);
2866         us = tvb_get_ntohs(tvb, offset + 8);
2867         proto_tree_add_uint_format_value(field_tree, hf_ipcp_opt_f_max_period,
2868             tvb, offset + 8, 2, us, "%u%s", us,
2869             (us == 0) ? " (infinity)" : "");
2870         us = tvb_get_ntohs(tvb, offset + 10);
2871         proto_tree_add_uint_format_value(field_tree, hf_ipcp_opt_f_max_time,
2872             tvb, offset + 10, 2, us, "%u%s", us,
2873             (us == 0) ? " (infinity)" : "");
2874         proto_tree_add_item(field_tree, hf_ipcp_opt_max_header, tvb,
2875             offset + 12, 2, ENC_BIG_ENDIAN);
2876 
2877         if ( length > 14 ) {
2878             proto_tree *subopt_tree;
2879 
2880             /* suboptions */
2881             offset += 14;
2882             length -= 14;
2883             subopt_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, length,
2884                 ett_ipcp_compress_opt, NULL, "Suboptions: (%u byte%s)", length, plurality(length, "", "s"));
2885             ppp_dissect_options(tvb, offset, length, ipcp_iphc_suboption_table, pinfo, subopt_tree);
2886         }
2887         break;
2888 
2889     default:
2890         if (length > 4) {
2891             proto_tree_add_item(field_tree, hf_ipcp_data, tvb, offset + 4,
2892                 length - 4, ENC_NA);
2893         }
2894         break;
2895     }
2896 
2897     return tvb_captured_length(tvb);
2898 }
2899 
2900 static void
dissect_ipcp_opt_rohc_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)2901 dissect_ipcp_opt_rohc_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
2902     const char *name)
2903 {
2904     guint8 type;
2905 
2906     type = tvb_get_guint8(tvb, offset);
2907     proto_tree_add_uint_format_value(tree, hf_ipcp_opt_rohc_type, tvb, offset,
2908         1, type, "%s (%u)", name, type);
2909     proto_tree_add_item(tree, hf_ipcp_opt_rohc_length, tvb, offset + 1, 1,
2910         ENC_BIG_ENDIAN);
2911 }
2912 
2913 static int
dissect_ipcp_rohc_profiles_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2914 dissect_ipcp_rohc_profiles_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2915 {
2916     proto_tree *field_tree;
2917     proto_item *tf;
2918     int length = tvb_reported_length(tvb);
2919     int offset = 0;
2920 
2921     tf = proto_tree_add_item(tree, proto_ipcp_rohc_option_profiles, tvb, offset, length, ENC_NA);
2922     field_tree = proto_item_add_subtree(tf, ett_ipcp_rohc_profiles_opt);
2923 
2924     dissect_ipcp_opt_rohc_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_ipcp_rohc_option_profiles));
2925     if (length <= 2)
2926         return tvb_captured_length(tvb);
2927 
2928     for (offset += 2, length -= 2; length >= 2; length -= 2, offset += 2) {
2929         proto_tree_add_item(field_tree, hf_ipcp_opt_rohc_profile, tvb,
2930             offset, 2, ENC_BIG_ENDIAN);
2931     }
2932     return tvb_captured_length(tvb);
2933 }
2934 
2935 static void
dissect_ipcp_opt_iphc_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)2936 dissect_ipcp_opt_iphc_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
2937     const char *name)
2938 {
2939     guint8 type;
2940 
2941     type = tvb_get_guint8(tvb, offset);
2942     proto_tree_add_uint_format_value(tree, hf_ipcp_opt_iphc_type, tvb, offset,
2943         1, type, "%s (%u)", name, type);
2944     proto_tree_add_item(tree, hf_ipcp_opt_iphc_length, tvb, offset + 1, 1,
2945         ENC_BIG_ENDIAN);
2946 }
2947 
2948 static gboolean
dissect_ipcp_iphc_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)2949 dissect_ipcp_iphc_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2950                              int proto, int ett, int expected_length,
2951                              proto_tree** ret_tree, proto_item** ret_item)
2952 {
2953     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
2954         return FALSE;
2955 
2956     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
2957     *ret_tree = proto_item_add_subtree(*ret_item, ett);
2958 
2959     dissect_ipcp_opt_iphc_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
2960     return TRUE;
2961 }
2962 
2963 static int
dissect_ipcp_iphc_rtp_compress(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2964 dissect_ipcp_iphc_rtp_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2965 {
2966     proto_tree *field_tree;
2967     proto_item *tf;
2968 
2969     dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_rtp_compress, ett_ipcp_iphc_rtp_compress_opt, 2,
2970                                   &field_tree, &tf);
2971     return tvb_captured_length(tvb);
2972 }
2973 
2974 static int
dissect_ipcp_iphc_enhanced_rtp_compress(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2975 dissect_ipcp_iphc_enhanced_rtp_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2976 {
2977     proto_tree *field_tree;
2978     proto_item *tf;
2979 
2980     dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_enhanced_rtp_compress, ett_ipcp_iphc_enhanced_rtp_compress_opt, 2,
2981                                   &field_tree, &tf);
2982     return tvb_captured_length(tvb);
2983 }
2984 
2985 static int
dissect_ipcp_iphc_neghdrcomp_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2986 dissect_ipcp_iphc_neghdrcomp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2987 {
2988     proto_tree *field_tree;
2989     proto_item *tf;
2990     int offset = 0;
2991 
2992     if (!dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_neghdrcomp, ett_ipcp_iphc_neghdrcomp_opt, 3,
2993                                   &field_tree, &tf))
2994         return tvb_captured_length(tvb);
2995 
2996     proto_tree_add_item(field_tree, hf_ipcp_opt_iphc_param, tvb, offset + 2, 1,
2997         ENC_BIG_ENDIAN);
2998     return tvb_captured_length(tvb);
2999 }
3000 
3001 static int
dissect_ipcp_addr_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3002 dissect_ipcp_addr_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3003 {
3004     proto_tree *field_tree;
3005     proto_item *tf;
3006     int offset = 0;
3007 
3008     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_addr, ett_ipcp_ipaddr_opt, 6,
3009                                   &field_tree, &tf))
3010         return tvb_captured_length(tvb);
3011 
3012     proto_tree_add_item(field_tree, hf_ipcp_opt_ip_address, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
3013     return tvb_captured_length(tvb);
3014 }
3015 
3016 static int
dissect_ipcp_mobileipv4_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3017 dissect_ipcp_mobileipv4_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3018 {
3019     proto_tree *field_tree;
3020     proto_item *tf;
3021     int offset = 0;
3022 
3023     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_mobileipv4, ett_ipcp_mobileipv4_opt, 6,
3024                                   &field_tree, &tf))
3025         return tvb_captured_length(tvb);
3026 
3027     proto_tree_add_item(field_tree, hf_ipcp_opt_mobilenodehomeaddr, tvb,
3028         offset + 2, 4, ENC_BIG_ENDIAN);
3029     return tvb_captured_length(tvb);
3030 }
3031 
3032 static int
dissect_ipcp_pri_dns_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3033 dissect_ipcp_pri_dns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3034 {
3035     proto_tree *field_tree;
3036     proto_item *tf;
3037     int offset = 0;
3038 
3039     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_pri_dns, ett_ipcp_pridns_opt, 6,
3040                                   &field_tree, &tf))
3041         return tvb_captured_length(tvb);
3042 
3043     proto_tree_add_item(field_tree, hf_ipcp_opt_pri_dns_address, tvb,
3044         offset + 2, 4, ENC_BIG_ENDIAN);
3045     return tvb_captured_length(tvb);
3046 }
3047 
3048 static int
dissect_ipcp_pri_nbns_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3049 dissect_ipcp_pri_nbns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3050 {
3051     proto_tree *field_tree;
3052     proto_item *tf;
3053     int offset = 0;
3054 
3055     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_pri_nbns, ett_ipcp_prinbns_opt, 6,
3056                                   &field_tree, &tf))
3057         return tvb_captured_length(tvb);
3058 
3059     proto_tree_add_item(field_tree, hf_ipcp_opt_pri_nbns_address, tvb,
3060         offset + 2, 4, ENC_BIG_ENDIAN);
3061     return tvb_captured_length(tvb);
3062 }
3063 
3064 static int
dissect_ipcp_sec_dns_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3065 dissect_ipcp_sec_dns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3066 {
3067     proto_tree *field_tree;
3068     proto_item *tf;
3069     int offset = 0;
3070 
3071     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_sec_dns, ett_ipcp_secdns_opt, 6,
3072                                   &field_tree, &tf))
3073         return tvb_captured_length(tvb);
3074 
3075     proto_tree_add_item(field_tree, hf_ipcp_opt_sec_dns_address, tvb,
3076         offset + 2, 4, ENC_BIG_ENDIAN);
3077     return tvb_captured_length(tvb);
3078 }
3079 
3080 static int
dissect_ipcp_sec_nbns_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3081 dissect_ipcp_sec_nbns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3082 {
3083     proto_tree *field_tree;
3084     proto_item *tf;
3085     int offset = 0;
3086 
3087     if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_sec_nbns, ett_ipcp_secnbns_opt, 6,
3088                                   &field_tree, &tf))
3089         return tvb_captured_length(tvb);
3090 
3091     proto_tree_add_item(field_tree, hf_ipcp_opt_sec_nbns_address, tvb,
3092         offset + 2, 4, ENC_BIG_ENDIAN);
3093     return tvb_captured_length(tvb);
3094 }
3095 
3096 static void
dissect_bcp_ncp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3097 dissect_bcp_ncp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3098     const char *name)
3099 {
3100     guint8 type;
3101 
3102     type = tvb_get_guint8(tvb, offset);
3103     proto_tree_add_uint_format_value(tree, hf_bcp_ncp_opt_type, tvb, offset, 1,
3104         type, "%s (%u)", name, type);
3105     offset++;
3106     proto_tree_add_item(tree, hf_bcp_ncp_opt_length, tvb, offset, 1,
3107         ENC_BIG_ENDIAN);
3108 }
3109 
3110 static gboolean
dissect_bcp_ncp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)3111 dissect_bcp_ncp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3112                              int proto, int ett, int expected_length,
3113                              proto_tree** ret_tree, proto_item** ret_item)
3114 {
3115     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
3116         return FALSE;
3117 
3118     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
3119     *ret_tree = proto_item_add_subtree(*ret_item, ett);
3120 
3121     dissect_bcp_ncp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
3122     return TRUE;
3123 }
3124 
3125 /*
3126 0                   1                   2                   3
3127 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3129 |     Type      |    Length     | LAN Segment Number    |Bridge#|
3130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3131 
3132 */
3133 static int
dissect_bcp_ncp_bridge_id(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3134 dissect_bcp_ncp_bridge_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3135 {
3136     proto_tree* field_tree;
3137     proto_item* tf;
3138     int offset = 0;
3139 
3140     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_bridge_id, ett_bcp_ncp_bridge_id_opt, 4,
3141                                   &field_tree, &tf))
3142         return tvb_captured_length(tvb);
3143 
3144     proto_tree_add_item(field_tree, hf_bcp_ncp_lan_seg_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
3145     proto_tree_add_item(field_tree, hf_bcp_ncp_bridge_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
3146 
3147     return tvb_captured_length(tvb);
3148 }
3149 
3150 /*
3151 0                   1                   2                   3
3152 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3153 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3154 |     Type      |    Length     | LAN Segment Number    |Bridge#|
3155 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3156 */
3157 static int
dissect_bcp_ncp_line_id(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3158 dissect_bcp_ncp_line_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3159 {
3160     proto_tree* field_tree;
3161     proto_item* tf;
3162     int offset = 0;
3163 
3164     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_line_id, ett_bcp_ncp_line_id_opt, 4,
3165                                   &field_tree, &tf))
3166         return tvb_captured_length(tvb);
3167 
3168     proto_tree_add_item(field_tree, hf_bcp_ncp_lan_seg_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
3169     proto_tree_add_item(field_tree, hf_bcp_ncp_bridge_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
3170     return tvb_captured_length(tvb);
3171 }
3172 
3173 /*
3174 0                   1                   2
3175 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
3176 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3177 |     Type      |    Length     |    MAC Type   |
3178 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3179 
3180 MAC Type
3181 0: reserved
3182 1: IEEE 802.3/Ethernet  with canonical addresses
3183 2: IEEE 802.4           with canonical addresses
3184 3: IEEE 802.5           with non-canonical addresses
3185 4: FDDI                 with non-canonical addresses
3186 5-10: reserved
3187 11: IEEE 802.5           with canonical addresses
3188 12: FDDI                 with canonical addresses
3189 
3190 */
3191 static int
dissect_bcp_ncp_mac_sup(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3192 dissect_bcp_ncp_mac_sup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3193 {
3194     proto_tree* field_tree;
3195     proto_item* tf;
3196     int offset = 0;
3197 
3198     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_mac_sup, ett_bcp_ncp_mac_sup_opt, 3,
3199                                   &field_tree, &tf))
3200         return tvb_captured_length(tvb);
3201 
3202     proto_tree_add_item(field_tree, hf_bcp_bpdu_mac_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
3203     return tvb_captured_length(tvb);
3204 }
3205 
3206 /*
3207 0                   1                   2
3208 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
3209 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3210 |     Type      |    Length     | Enable/Disable|
3211 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3212 
3213 */
3214 static int
dissect_bcp_ncp_tinygram_comp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3215 dissect_bcp_ncp_tinygram_comp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3216 {
3217     proto_tree* field_tree;
3218     proto_item* tf;
3219     int offset = 0;
3220 
3221     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_tinygram_comp, ett_bcp_ncp_tinygram_comp_opt, 3,
3222                                   &field_tree, &tf))
3223         return tvb_captured_length(tvb);
3224 
3225     proto_tree_add_item(field_tree, hf_bcp_ncp_tinygram_comp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
3226     return tvb_captured_length(tvb);
3227 }
3228 
3229 static int
dissect_bcp_ncp_lan_id(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3230 dissect_bcp_ncp_lan_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3231 {
3232     proto_tree* field_tree;
3233     proto_item* tf;
3234 
3235     dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_lan_id, ett_bcp_ncp_lan_id_opt, 3,
3236                                   &field_tree, &tf);
3237     /* XXX - missing a field? */
3238     return tvb_captured_length(tvb);
3239 }
3240 
3241 /*
3242 0                   1                   2                   3
3243 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3244 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3245 |     Type      |    Length     |MAC byte 1 |L|M|  MAC byte 2   |
3246 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3247 |  MAC byte 3   |  MAC byte 4   |  MAC byte 5   |  MAC byte 6   |
3248 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3249 */
3250 static int
dissect_bcp_ncp_mac_addr(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3251 dissect_bcp_ncp_mac_addr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3252 {
3253     proto_tree* field_tree;
3254     proto_item* tf;
3255     int offset = 0;
3256 
3257     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_mac_addr, ett_bcp_ncp_mac_addr_opt, 8,
3258                                   &field_tree, &tf))
3259         return tvb_captured_length(tvb);
3260 
3261     proto_tree_add_item(field_tree, hf_bcp_ncp_mac, tvb, offset+2, 6, ENC_NA);
3262     proto_tree_add_item(field_tree, hf_bcp_ncp_mac_l, tvb, offset+2, 6, ENC_BIG_ENDIAN);
3263     proto_tree_add_item(field_tree, hf_bcp_ncp_mac_m, tvb, offset+2, 6, ENC_BIG_ENDIAN);
3264     return tvb_captured_length(tvb);
3265 }
3266 
3267 /*
3268 0                   1                   2                   3
3269 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
3270 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
3271 |     Type      |    Length     |  Protocol 1   |  Protocol 2   | ..
3272 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
3273 
3274 */
3275 
3276 static const value_string bcp_ncp_stp_prot_vals[] = {
3277     { 0, "Null (no Spanning Tree protocol supported)" },
3278     { 1, "IEEE 802.1D spanning tree" },
3279     { 2, "IEEE 802.1G extended spanning tree protocol" },
3280     { 3, "IBM Source Route Spanning tree protocol" },
3281     { 4, "DEC LANbridge 100 Spanning tree protocol" },
3282     { 0,            NULL }
3283 };
3284 
3285 static int
dissect_bcp_ncp_stp(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3286 dissect_bcp_ncp_stp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
3287 {
3288     proto_tree *field_tree;
3289     proto_item *tf;
3290     int offset = 0;
3291     int length = tvb_reported_length(tvb);
3292 
3293     tf = proto_tree_add_item(tree, proto_bcp_ncp_option_stp, tvb, offset, length, ENC_NA);
3294     field_tree = proto_item_add_subtree(tf, ett_bcp_ncp_stp_opt);
3295 
3296     dissect_bcp_ncp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_bcp_ncp_option_stp));
3297     offset += 2;
3298     length -= 2;
3299 
3300     while (length != 0) {
3301         proto_tree_add_item(field_tree, hf_bcp_ncp_stp_prot, tvb, offset, 1, ENC_BIG_ENDIAN);
3302         length--;
3303         offset++;
3304     }
3305     return tvb_captured_length(tvb);
3306 }
3307 
3308 /*
3309 0                   1                   2
3310 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
3311 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3312 |     Type      |    Length     | Enable/Disable|
3313 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3314 
3315 */
3316 static int
dissect_bcp_ncp_ieee_802_tagged_frame(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3317 dissect_bcp_ncp_ieee_802_tagged_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3318 {
3319     proto_tree* field_tree;
3320     proto_item* tf;
3321     int offset = 0;
3322 
3323     if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_ieee_802_tagged_frame,
3324                                   ett_bcp_ncp_ieee_802_tagged_frame_opt, 3, &field_tree, &tf))
3325         return tvb_captured_length(tvb);
3326 
3327     proto_tree_add_item(field_tree, hf_bcp_ncp_ieee_802_tagged_frame, tvb, offset+2, 1, ENC_BIG_ENDIAN);
3328     return tvb_captured_length(tvb);
3329 }
3330 
3331 /*
3332 0                   1
3333 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
3334 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3335 |     Type      |    Length     |
3336 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3337 
3338 */
3339 static int
dissect_bcp_ncp_management_inline(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3340 dissect_bcp_ncp_management_inline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3341 {
3342     proto_tree* field_tree;
3343     proto_item* tf;
3344 
3345     dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_management_inline, ett_bcp_ncp_management_inline_opt, 3,
3346                                   &field_tree, &tf);
3347     return tvb_captured_length(tvb);
3348 }
3349 
3350 /*
3351 0                   1
3352 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
3353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3354 |     Type      |    Length     |
3355 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3356 
3357 */
3358 static int
dissect_bcp_ncp_bcp_ncp_bcp_ind(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3359 dissect_bcp_ncp_bcp_ncp_bcp_ind(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3360 {
3361     proto_tree* field_tree;
3362     proto_item* tf;
3363 
3364     dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_bcp_ind, ett_bcp_ncp_bcp_ind_opt, 3,
3365                                   &field_tree, &tf);
3366     return tvb_captured_length(tvb);
3367 }
3368 
3369 
3370 static void
dissect_osinlcp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3371 dissect_osinlcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3372     const char *name)
3373 {
3374     guint8 type;
3375 
3376     type = tvb_get_guint8(tvb, offset);
3377     proto_tree_add_uint_format_value(tree, hf_osinlcp_opt_type, tvb, offset, 1,
3378         type, "%s (%u)", name, type);
3379     proto_tree_add_item(tree, hf_osinlcp_opt_length, tvb, offset + 1, 1,
3380         ENC_BIG_ENDIAN);
3381 }
3382 
3383 static gboolean
dissect_osinlcp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)3384 dissect_osinlcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3385                              int proto, int ett, int expected_length,
3386                              proto_tree** ret_tree, proto_item** ret_item)
3387 {
3388     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
3389         return FALSE;
3390 
3391     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
3392     *ret_tree = proto_item_add_subtree(*ret_item, ett);
3393 
3394     dissect_osinlcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
3395     return TRUE;
3396 }
3397 
3398 static int
dissect_osinlcp_align_npdu_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3399 dissect_osinlcp_align_npdu_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3400 {
3401     proto_tree *field_tree;
3402     proto_item *tf;
3403     int offset = 0;
3404 
3405     if (!dissect_osinlcp_fixed_opt(tvb, pinfo, tree, proto_osinlcp_option_align_npdu, ett_osinlcp_align_npdu_opt, 3,
3406                                   &field_tree, &tf))
3407         return tvb_captured_length(tvb);
3408 
3409     proto_tree_add_item(field_tree, hf_osinlcp_opt_alignment, tvb, offset + 2,
3410         1, ENC_BIG_ENDIAN);
3411     return tvb_captured_length(tvb);
3412 }
3413 
3414 static void
dissect_pppmuxcp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3415 dissect_pppmuxcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3416     const char *name)
3417 {
3418     guint8 type;
3419 
3420     type = tvb_get_guint8(tvb, offset);
3421     proto_tree_add_uint_format_value(tree, hf_pppmuxcp_opt_type, tvb, offset, 1,
3422         type, "%s (%u)", name, type);
3423     proto_tree_add_item(tree, hf_pppmuxcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
3424 }
3425 
3426 static gboolean
dissect_pppmuxcp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)3427 dissect_pppmuxcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3428                              int proto, int ett, int expected_length,
3429                              proto_tree** ret_tree, proto_item** ret_item)
3430 {
3431     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
3432         return FALSE;
3433 
3434     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
3435     *ret_tree = proto_item_add_subtree(*ret_item, ett);
3436 
3437     dissect_pppmuxcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
3438     return TRUE;
3439 }
3440 
3441 static int
dissect_pppmuxcp_def_pid_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3442 dissect_pppmuxcp_def_pid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3443 {
3444     proto_tree* field_tree;
3445     proto_item* tf;
3446     int offset = 0;
3447 
3448     if (!dissect_pppmuxcp_fixed_opt(tvb, pinfo, tree, proto_pppmuxcp_option_def_pid, ett_pppmuxcp_def_pid_opt, 4,
3449                                   &field_tree, &tf))
3450         return tvb_captured_length(tvb);
3451 
3452     proto_tree_add_item_ret_uint(tree, hf_pppmux_def_prot_id, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &pppmux_def_prot_id);
3453     return tvb_captured_length(tvb);
3454 }
3455 
3456 
3457 static void
dissect_ccp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3458 dissect_ccp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3459     const char *name)
3460 {
3461     guint8 type;
3462 
3463     type = tvb_get_guint8(tvb, offset);
3464     proto_tree_add_uint_format_value(tree, hf_ccp_opt_type, tvb, offset, 1,
3465         type, "%s (%u)", name, type);
3466     proto_tree_add_item(tree, hf_ccp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
3467 }
3468 
3469 static gboolean
dissect_ccp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)3470 dissect_ccp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3471                              int proto, int ett, int expected_length,
3472                              proto_tree** ret_tree, proto_item** ret_item)
3473 {
3474     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
3475         return FALSE;
3476 
3477     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
3478     *ret_tree = proto_item_add_subtree(*ret_item, ett);
3479 
3480     dissect_ccp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
3481     return TRUE;
3482 }
3483 
3484 static gboolean
dissect_ccp_var_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)3485 dissect_ccp_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3486                              int proto, int ett, int expected_length,
3487                              proto_tree** ret_tree, proto_item** ret_item)
3488 {
3489     int len = tvb_reported_length(tvb);
3490 
3491     if (len < expected_length) {
3492         /* Bogus - option length isn't what it's supposed to be for this option. */
3493         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
3494                             "%s (with option length = %u byte%s; should be at least %u)",
3495                             proto_get_protocol_short_name(find_protocol_by_id(proto)),
3496                             len, plurality(len, "", "s"), expected_length);
3497         return FALSE;
3498     }
3499 
3500     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
3501     *ret_tree = proto_item_add_subtree(*ret_item, ett);
3502 
3503     dissect_ccp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
3504     return TRUE;
3505 }
3506 
3507 
3508 /* https://tools.ietf.org/html/rfc1962 */
dissect_ccp_oui_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3509 static int dissect_ccp_oui_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3510 {
3511     proto_tree *field_tree;
3512     proto_item *tf;
3513     int offset = 0;
3514     int length = tvb_reported_length(tvb);
3515 
3516     if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_oui, ett_ccp_oui_opt, 6,
3517                                   &field_tree, &tf))
3518         return tvb_captured_length(tvb);
3519 
3520     proto_tree_add_item(field_tree, hf_ccp_opt_oui, tvb, offset + 2, 3, ENC_BIG_ENDIAN);
3521 
3522     proto_tree_add_item(field_tree, hf_ccp_opt_subtype, tvb, offset + 5, 1,
3523         ENC_BIG_ENDIAN);
3524     if (length > 6) {
3525         proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 6,
3526             length - 6, ENC_NA);
3527     }
3528     return tvb_captured_length(tvb);
3529 }
3530 
3531 /* The following configuration option types are mentioned at
3532  * https://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml as referencing RFC1962; however,
3533  * RFC1962 only mentions Proprietary Compression OUI in section 4.1.  These
3534  * others are therefore being treated as section 4.2 "Other Compression Types",
3535  * in terms of how they are dissected:
3536  *      1)  Predictor type 1
3537  *      2)  Predictor type 2
3538  *      3)  Puddle Jumper
3539  *      16) Hewlett-Packard PPC
3540  *      20) V.42bis compression
3541  */
dissect_ccp_other_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,int proto,int ett)3542 static int dissect_ccp_other_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int proto, int ett)
3543 {
3544     proto_tree *field_tree;
3545     proto_item *tf;
3546     int offset = 0;
3547     int length = tvb_reported_length(tvb);
3548 
3549     tf = proto_tree_add_item(tree, proto, tvb, 0, length, ENC_NA);
3550     field_tree = proto_item_add_subtree(tf, ett);
3551 
3552     dissect_ccp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto));
3553 
3554     if (length > 2) {
3555         proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2,
3556             length - 2, ENC_NA);
3557     }
3558 
3559     return tvb_captured_length(tvb);
3560 }
3561 
dissect_ccp_predict1_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3562 static int dissect_ccp_predict1_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3563 {
3564     return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_predict1, ett_ccp_predict1_opt);
3565 }
3566 
dissect_ccp_predict2_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3567 static int dissect_ccp_predict2_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3568 {
3569     return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_predict2, ett_ccp_predict2_opt);
3570 }
3571 
dissect_ccp_puddle_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3572 static int dissect_ccp_puddle_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3573 {
3574     return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_puddle, ett_ccp_puddle_opt);
3575 }
3576 
dissect_ccp_hpppc_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3577 static int dissect_ccp_hpppc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3578 {
3579     return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_hpppc, ett_ccp_hpppc_opt);
3580 }
3581 
3582 /* https://tools.ietf.org/html/rfc1974 */
3583 static int
dissect_ccp_stac_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3584 dissect_ccp_stac_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3585 {
3586     proto_tree *field_tree;
3587     proto_item *tf;
3588     int offset = 0;
3589     int length = tvb_reported_length(tvb);
3590     static int * const check_mode_fields[] = {
3591         &hf_ccp_opt_cm_reserved,
3592         &hf_ccp_opt_cm_check_mode,
3593         NULL
3594     };
3595 
3596     /* In RFC 1974, this is a fixed-length field of size 5, but in
3597      * Ascend Proprietary STAC compression this field is 6 octets. */
3598 
3599     if (!dissect_ccp_var_opt(tvb, pinfo, tree,
3600                                   (length == 6) ? proto_ccp_option_stac_ascend : proto_ccp_option_stac,
3601                                   ett_ccp_stac_opt, 5, &field_tree, &tf))
3602         return tvb_captured_length(tvb);
3603 
3604 
3605     if (length == 6) {
3606         /* We don't know how to decode the following 4 octets, since
3607            there are no public documents that describe their usage. */
3608         proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2,
3609             length - 2, ENC_NA);
3610     } else {
3611         proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb,
3612             offset + 2, 2, ENC_BIG_ENDIAN);
3613         proto_tree_add_bitmask(field_tree, tvb, offset + 4, hf_ccp_opt_cm,
3614             ett_ccp_stac_opt_check_mode, check_mode_fields, ENC_NA);
3615     }
3616     return tvb_captured_length(tvb);
3617 }
3618 
3619 /*
3620  * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE)
3621  * supported bits.
3622  */
3623 #define MPPC_SUPPORTED_BITS_C   0x00000001      /* MPPC negotiation */
3624 #define MPPE_SUPPORTED_BITS_D   0x00000010      /* Obsolete */
3625 #define MPPE_SUPPORTED_BITS_L   0x00000020      /* 40-bit encryption */
3626 #define MPPE_SUPPORTED_BITS_S   0x00000040      /* 128-bit encryption */
3627 #define MPPE_SUPPORTED_BITS_M   0x00000080      /* 56-bit encryption */
3628 #define MPPE_SUPPORTED_BITS_H   0x01000000      /* stateless mode */
3629 
3630 static const true_false_string ccp_mppe_h_tfs = {
3631     "Stateless mode ON",
3632     "Stateless mode OFF"
3633 };
3634 static const true_false_string ccp_mppe_m_tfs = {
3635     "56-bit encryption ON",
3636     "56-bit encryption OFF"
3637 };
3638 static const true_false_string ccp_mppe_s_tfs = {
3639     "128-bit encryption ON",
3640     "128-bit encryption OFF"
3641 };
3642 static const true_false_string ccp_mppe_l_tfs = {
3643     "40-bit encryption ON",
3644     "40-bit encryption OFF"
3645 };
3646 static const true_false_string ccp_mppe_d_tfs = {
3647     "Obsolete (should NOT be 1)",
3648     "Obsolete (should ALWAYS be 0)"
3649 };
3650 static const true_false_string ccp_mppe_c_tfs = {
3651     "Desire to negotiate MPPC",
3652     "No desire to negotiate MPPC"
3653 };
3654 
3655 /* https://tools.ietf.org/html/rfc2118,
3656  * https://tools.ietf.org/html/rfc3078 */
3657 static int
dissect_ccp_mppe_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3658 dissect_ccp_mppe_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3659 {
3660     proto_tree *field_tree;
3661     proto_item *tf;
3662     int offset = 0;
3663     static int * const supported_bits_fields[] = {
3664         &hf_ccp_opt_supported_bits_h,
3665         &hf_ccp_opt_supported_bits_m,
3666         &hf_ccp_opt_supported_bits_s,
3667         &hf_ccp_opt_supported_bits_l,
3668         &hf_ccp_opt_supported_bits_d,
3669         &hf_ccp_opt_supported_bits_c,
3670         NULL
3671     };
3672 
3673     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_mppe, ett_ccp_mppe_opt, 6,
3674                                   &field_tree, &tf))
3675         return tvb_captured_length(tvb);
3676 
3677     proto_tree_add_bitmask(field_tree, tvb, offset + 2,
3678         hf_ccp_opt_supported_bits, ett_ccp_mppe_opt_supp_bits,
3679         supported_bits_fields, ENC_BIG_ENDIAN);
3680     return tvb_captured_length(tvb);
3681 }
3682 
3683 /* https://tools.ietf.org/html/rfc1993 */
dissect_ccp_gfza_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3684 static int dissect_ccp_gfza_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3685 {
3686     proto_tree *field_tree;
3687     proto_item *tf;
3688     int offset = 0;
3689     int length = tvb_reported_length(tvb);
3690 
3691     if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_gfza, ett_ccp_gfza_opt, 3,
3692                                   &field_tree, &tf))
3693         return tvb_captured_length(tvb);
3694 
3695     proto_tree_add_item(field_tree, hf_ccp_opt_history, tvb, offset + 2, 1,
3696         ENC_BIG_ENDIAN);
3697 
3698     if (length > 3) {
3699         proto_tree_add_item(field_tree, hf_ccp_opt_version, tvb, offset + 3,
3700             length - 3, ENC_NA);
3701     }
3702     return tvb_captured_length(tvb);
3703 }
3704 
dissect_ccp_v42bis_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3705 static int dissect_ccp_v42bis_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3706 {
3707     return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_v42bis, ett_ccp_v42bis_opt);
3708 }
3709 
3710 /* https://tools.ietf.org/html/rfc1977 */
3711 static int
dissect_ccp_bsdcomp_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3712 dissect_ccp_bsdcomp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3713 {
3714     proto_tree *field_tree;
3715     proto_item *tf;
3716     int offset = 0;
3717     static int * const vd_fields[] = {
3718         &hf_ccp_opt_vd_vers,
3719         &hf_ccp_opt_vd_dict,
3720         NULL
3721     };
3722 
3723     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_bsdcomp, ett_ccp_bsdcomp_opt, 3,
3724                                   &field_tree, &tf))
3725         return tvb_captured_length(tvb);
3726 
3727     proto_tree_add_bitmask(field_tree, tvb, offset + 2, hf_ccp_opt_vd,
3728         ett_ccp_bsdcomp_opt, vd_fields, ENC_BIG_ENDIAN);
3729     return tvb_captured_length(tvb);
3730 }
3731 
3732 /* https://tools.ietf.org/html/rfc1967 */
3733 static int
dissect_ccp_lzsdcp_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3734 dissect_ccp_lzsdcp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3735 {
3736     proto_tree *field_tree;
3737     proto_item *tf;
3738     int offset = 0;
3739 
3740     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_lzsdcp, ett_ccp_lzsdcp_opt, 6,
3741                                   &field_tree, &tf))
3742         return tvb_captured_length(tvb);
3743 
3744     proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb,
3745         offset + 2, 2, ENC_BIG_ENDIAN);
3746     proto_tree_add_item(field_tree, hf_ccp_opt_check_mode, tvb, offset + 4, 1,
3747         ENC_BIG_ENDIAN);
3748     proto_tree_add_item(field_tree, hf_ccp_opt_process_mode, tvb, offset + 5,
3749         1, ENC_BIG_ENDIAN);
3750     return tvb_captured_length(tvb);
3751 }
3752 
3753 /* https://tools.ietf.org/html/rfc1975 */
3754 static int
dissect_ccp_mvrca_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3755 dissect_ccp_mvrca_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3756 {
3757     proto_tree *field_tree;
3758     proto_item *tf;
3759     int offset = 0;
3760 
3761     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_mvrca, ett_ccp_mvrca_opt, 4,
3762                                   &field_tree, &tf))
3763         return tvb_captured_length(tvb);
3764 
3765     proto_tree_add_item(field_tree, hf_ccp_opt_fe, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
3766     proto_tree_add_item(field_tree, hf_ccp_opt_p, tvb, offset + 2, 1, ENC_NA);
3767     proto_tree_add_item(field_tree, hf_ccp_opt_History, tvb, offset + 2, 1,
3768         ENC_BIG_ENDIAN);
3769     proto_tree_add_item(field_tree, hf_ccp_opt_contexts, tvb, offset + 3, 1,
3770         ENC_BIG_ENDIAN);
3771     return tvb_captured_length(tvb);
3772 }
3773 
3774 /* https://tools.ietf.org/html/rfc1976 */
3775 static int
dissect_ccp_dce_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3776 dissect_ccp_dce_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3777 {
3778     proto_tree *field_tree;
3779     proto_item *tf;
3780     int offset = 0;
3781 
3782     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_dce, ett_ccp_dce_opt, 3,
3783                                   &field_tree, &tf))
3784         return tvb_captured_length(tvb);
3785 
3786     proto_tree_add_item(field_tree, hf_ccp_opt_mode, tvb, offset + 2, 1,
3787         ENC_BIG_ENDIAN);
3788     return tvb_captured_length(tvb);
3789 }
3790 
3791 static const value_string deflate_method_vals[] = {
3792     {8, "zlib compression"},
3793     {0, NULL}
3794 };
3795 
3796 static const value_string deflate_chk_vals[] = {
3797     {0, "sequence number check method"},
3798     {0, NULL}
3799 };
3800 
3801 /* https://tools.ietf.org/html/rfc1979 */
3802 static int
dissect_ccp_deflate_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3803 dissect_ccp_deflate_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3804 {
3805     proto_tree *field_tree;
3806     proto_item *tf;
3807     int offset = 0;
3808     guint8 window;
3809 
3810     /* RFC1979 says the length is 3 but it's actually 4. */
3811     if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_deflate, ett_ccp_deflate_opt, 4,
3812                                   &field_tree, &tf))
3813         return tvb_captured_length(tvb);
3814 
3815     window = tvb_get_guint8(tvb, offset + 2);
3816     proto_tree_add_uint_format_value(field_tree, hf_ccp_opt_window, tvb,
3817         offset + 2, 1, window, "%u", 1 << (hi_nibble(window) + 8));
3818     proto_tree_add_item(field_tree, hf_ccp_opt_method, tvb, offset + 2, 1,
3819         ENC_BIG_ENDIAN);
3820     proto_tree_add_item(field_tree, hf_ccp_opt_mbz, tvb, offset + 3, 1,
3821         ENC_BIG_ENDIAN);
3822     proto_tree_add_item(field_tree, hf_ccp_opt_chk, tvb, offset + 3, 1,
3823         ENC_BIG_ENDIAN);
3824     return tvb_captured_length(tvb);
3825 }
3826 
3827 static const range_string v44lzjh_mode_dict_rvals[] = {
3828     {0, 0, "Datagram Mode (one dictionary and no history)"},
3829     {1, 1, "Multi-Datagram Mode (one dictionary with history)"},
3830     {2, G_MAXUINT16, "Individual Link Mode" /* "(and proposed number of
3831                                                  dictionaries each with a
3832                                                  corresponding history" */},
3833     {0, 0, NULL}
3834 };
3835 
3836 /* https://tools.ietf.org/html/draft-heath-ppp-v44-01 */
dissect_ccp_v44lzjh_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3837 static int dissect_ccp_v44lzjh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3838 {
3839     proto_tree *field_tree;
3840     proto_item *tf;
3841     int offset = 0;
3842     int length = tvb_reported_length(tvb);
3843 
3844     if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_v44lzjh, ett_ccp_v44lzjh_opt, 4,
3845                                   &field_tree, &tf))
3846         return tvb_captured_length(tvb);
3847 
3848     proto_tree_add_item(field_tree, hf_ccp_opt_mode_dictcount, tvb, offset + 2,
3849         2, ENC_BIG_ENDIAN);
3850 
3851     if (length > 4) {
3852         proto_tree_add_item(field_tree, hf_ccp_opt_dict_size, tvb, offset + 4,
3853             2, ENC_BIG_ENDIAN);
3854         if (length > 6) {
3855             proto_tree_add_item(field_tree, hf_ccp_opt_history_length, tvb,
3856                 offset + 6, 2, ENC_BIG_ENDIAN);
3857         }
3858     }
3859     return tvb_captured_length(tvb);
3860 }
3861 
3862 static int
dissect_cbcp_callback_opt_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,int length)3863 dissect_cbcp_callback_opt_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length)
3864 {
3865     proto_tree *addr_tree;
3866     proto_item *ti;
3867     guint8      addr_type;
3868     guint       addr_len;
3869 
3870     proto_tree_add_item(tree, hf_cbcp_callback_delay, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
3871     offset += 3;
3872     length -= 3;
3873 
3874     while (length > 0) {
3875         addr_tree = proto_tree_add_subtree(tree, tvb, offset, length,
3876             ett_cbcp_callback_opt_addr, NULL, "Callback Address");
3877         addr_type = tvb_get_guint8(tvb, offset);
3878         ti = proto_tree_add_uint_format_value(addr_tree, hf_cbcp_address_type, tvb, offset, 1, addr_type,
3879              "%s (%u)", ((addr_type == 1) ? "PSTN/ISDN" : "Other"), addr_type);
3880         offset++;
3881         length--;
3882         addr_len = tvb_strsize(tvb, offset);
3883         if (addr_len > (guint)length) {
3884             expert_add_info(pinfo, ti, &ei_cbcp_address);
3885             break;
3886         }
3887         proto_tree_add_item(addr_tree, hf_cbcp_address, tvb, offset, addr_len, ENC_NA|ENC_ASCII);
3888         offset += addr_len;
3889         length -= addr_len;
3890     }
3891 
3892     return tvb_captured_length(tvb);
3893 }
3894 
3895 static void
dissect_cbcp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3896 dissect_cbcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3897     const char *name)
3898 {
3899     guint8 type;
3900 
3901     type = tvb_get_guint8(tvb, offset);
3902     proto_tree_add_uint_format_value(tree, hf_cbcp_opt_type, tvb, offset, 1,
3903         type, "%s (%u)", name, type);
3904     proto_tree_add_item(tree, hf_cbcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
3905 }
3906 
3907 static int
dissect_cbcp_no_callback_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3908 dissect_cbcp_no_callback_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
3909 {
3910     proto_tree* field_tree;
3911     proto_item* tf;
3912     int offset = 0;
3913     int length = tvb_reported_length(tvb);
3914 
3915     tf = proto_tree_add_item(tree, proto_cbcp_option_no_callback, tvb, offset, length, ENC_NA);
3916     field_tree = proto_item_add_subtree(tf, ett_cbcp_no_callback);
3917 
3918     dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_no_callback));
3919     proto_tree_add_item(field_tree, hf_cbcp_no_callback, tvb, offset+2, length-2, ENC_NA);
3920 
3921     return tvb_captured_length(tvb);
3922 }
3923 
3924 static int
dissect_cbcp_callback_user_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3925 dissect_cbcp_callback_user_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3926 {
3927     proto_tree* field_tree;
3928     proto_item* tf;
3929     int offset = 0;
3930     int length = tvb_reported_length(tvb);
3931 
3932     if (length < 4) {
3933         /* Bogus - option length isn't what it's supposed to be for this option. */
3934         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
3935                             "%s (with option length = %u byte%s; should be at least %u)",
3936                             proto_get_protocol_short_name(find_protocol_by_id(proto_cbcp_option_callback_user)),
3937                             length, plurality(length, "", "s"), 4);
3938         return tvb_captured_length(tvb);
3939     }
3940 
3941     tf = proto_tree_add_item(tree, proto_cbcp_option_callback_user, tvb, offset, length, ENC_NA);
3942     field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_user);
3943 
3944     dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_user));
3945 
3946     return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
3947 }
3948 
3949 static int
dissect_cbcp_callback_admin_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3950 dissect_cbcp_callback_admin_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3951 {
3952     proto_tree* field_tree;
3953     proto_item* tf;
3954     int offset = 0;
3955 
3956     if (!ppp_option_len_check(tree, pinfo, tvb, proto_cbcp_option_callback_admin, tvb_reported_length(tvb), 4))
3957         return tvb_captured_length(tvb);
3958 
3959     tf = proto_tree_add_item(tree, proto_cbcp_option_callback_admin, tvb, offset, -1, ENC_NA);
3960     field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_admin);
3961 
3962     dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_admin));
3963 
3964     return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
3965 }
3966 
3967 static int
dissect_cbcp_callback_list_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3968 dissect_cbcp_callback_list_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3969 {
3970     proto_tree* field_tree;
3971     proto_item* tf;
3972     int offset = 0;
3973     int length = tvb_reported_length(tvb);
3974 
3975     if (length < 4) {
3976         /* Bogus - option length isn't what it's supposed to be for this option. */
3977         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
3978                             "%s (with option length = %u byte%s; should be at least %u)",
3979                             proto_get_protocol_short_name(find_protocol_by_id(proto_cbcp_option_callback_list)),
3980                             length, plurality(length, "", "s"), 4);
3981         return tvb_captured_length(tvb);
3982     }
3983 
3984     tf = proto_tree_add_item(tree, proto_cbcp_option_callback_list, tvb, offset, length, ENC_NA);
3985     field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_list);
3986 
3987     dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_list));
3988 
3989     return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
3990 }
3991 
3992 static void
dissect_bacp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3993 dissect_bacp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
3994     const char *name)
3995 {
3996     guint8 type;
3997 
3998     type = tvb_get_guint8(tvb, offset);
3999     proto_tree_add_uint_format_value(tree, hf_bacp_opt_type, tvb, offset, 1,
4000         type, "%s (%u)", name, type);
4001     proto_tree_add_item(tree, hf_bacp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
4002 }
4003 
4004 static gboolean
dissect_bacp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)4005 dissect_bacp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4006                              int proto, int ett, int expected_length,
4007                              proto_tree** ret_tree, proto_item** ret_item)
4008 {
4009     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
4010         return FALSE;
4011 
4012     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
4013     *ret_tree = proto_item_add_subtree(*ret_item, ett);
4014 
4015     dissect_bacp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
4016     return TRUE;
4017 }
4018 
4019 static int
dissect_bacp_favored_peer_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4020 dissect_bacp_favored_peer_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4021 {
4022     proto_tree* field_tree;
4023     proto_item* tf;
4024     int offset = 0;
4025 
4026     if (!dissect_bacp_fixed_opt(tvb, pinfo, tree, proto_bacp_option_favored_peer, ett_bacp_favored_peer_opt, 6,
4027                                   &field_tree, &tf))
4028         return tvb_captured_length(tvb);
4029 
4030     proto_tree_add_item(field_tree, hf_bacp_magic_number, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
4031     return tvb_captured_length(tvb);
4032 }
4033 
4034 static void
dissect_bap_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4035 dissect_bap_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
4036     const char *name)
4037 {
4038     guint8 type;
4039 
4040     type = tvb_get_guint8(tvb, offset);
4041     proto_tree_add_uint_format_value(tree, hf_bap_opt_type, tvb, offset, 1,
4042         type, "%s (%u)", name, type);
4043     proto_tree_add_item(tree, hf_bap_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
4044 }
4045 
4046 static gboolean
dissect_bap_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)4047 dissect_bap_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4048                              int proto, int ett, int expected_length,
4049                              proto_tree** ret_tree, proto_item** ret_item)
4050 {
4051     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
4052         return FALSE;
4053 
4054     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
4055     *ret_tree = proto_item_add_subtree(*ret_item, ett);
4056 
4057     dissect_bap_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
4058     return TRUE;
4059 }
4060 
4061 static gboolean
dissect_bap_var_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)4062 dissect_bap_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4063                              int proto, int ett, int expected_length,
4064                              proto_tree** ret_tree, proto_item** ret_item)
4065 {
4066     int len = tvb_reported_length(tvb);
4067 
4068     if (len < expected_length) {
4069         /* Bogus - option length isn't what it's supposed to be for this option. */
4070         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
4071                             "%s (with option length = %u byte%s; should be at least %u)",
4072                             proto_get_protocol_short_name(find_protocol_by_id(proto)),
4073                             len, plurality(len, "", "s"), expected_length);
4074         return FALSE;
4075     }
4076 
4077     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
4078     *ret_tree = proto_item_add_subtree(*ret_item, ett);
4079 
4080     dissect_bap_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
4081     return TRUE;
4082 }
4083 
4084 static int
dissect_bap_link_type_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4085 dissect_bap_link_type_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4086 {
4087     proto_tree* field_tree;
4088     proto_item* tf;
4089     int offset = 0;
4090 
4091     if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_link_type, ett_bap_link_type_opt, 5,
4092                                   &field_tree, &tf))
4093         return tvb_captured_length(tvb);
4094 
4095     proto_tree_add_item(field_tree, hf_bacp_link_speed, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
4096     proto_tree_add_item(field_tree, hf_bacp_link_type, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
4097     return tvb_captured_length(tvb);
4098 }
4099 
4100 static int
dissect_bap_phone_delta_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4101 dissect_bap_phone_delta_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4102 {
4103     proto_tree *field_tree;
4104     proto_tree *suboption_tree;
4105     proto_item *tf, *ti;
4106     int offset = 0;
4107     int length = tvb_reported_length(tvb);
4108     guint8      subopt_type;
4109     guint8      subopt_len;
4110 
4111     if (!dissect_bap_var_opt(tvb, pinfo, tree, proto_bap_option_phone_delta, ett_bap_phone_delta_opt, 4,
4112                                   &field_tree, &tf))
4113         return tvb_captured_length(tvb);
4114 
4115     offset += 2;
4116     length -= 2;
4117 
4118     while (length > 0) {
4119         subopt_type = tvb_get_guint8(tvb, offset);
4120         subopt_len = tvb_get_guint8(tvb, offset + 1);
4121         suboption_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, subopt_len,
4122             ett_bap_phone_delta_subopt, NULL, "Sub-Option (%u byte%s)", subopt_len,
4123             plurality(subopt_len, "", "s"));
4124 
4125         proto_tree_add_item(suboption_tree, hf_bap_sub_option_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4126         ti = proto_tree_add_item(suboption_tree, hf_bap_sub_option_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
4127 
4128         if (subopt_len < 2) {
4129             expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4130                 "Sub-Option Length invalid, must be >= 2");
4131             break;
4132         }
4133         if (subopt_len > length) {
4134             expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4135                 "Sub-Option Length invalid, must be <= length remaining in option %u)", length);
4136             break;
4137         }
4138 
4139         switch (subopt_type) {
4140         case BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT:
4141             if (subopt_len == 3) {
4142                 proto_tree_add_item(suboption_tree, hf_bap_unique_digit, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
4143             } else {
4144                 expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4145                     "Invalid suboption length: %u (must be == 3)", subopt_len);
4146             }
4147             break;
4148         case BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM:
4149             if (subopt_len > 2) {
4150                 proto_tree_add_item(suboption_tree, hf_bap_subscriber_number, tvb, offset + 2, subopt_len - 2, ENC_NA|ENC_ASCII);
4151             } else {
4152                 expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4153                     "Invalid suboption length: %u (must be > 2)", subopt_len);
4154             }
4155             break;
4156         case BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR:
4157             if (subopt_len > 2) {
4158                 proto_tree_add_item(suboption_tree, hf_bap_phone_number_sub_address, tvb, offset + 2, subopt_len - 2, ENC_NA|ENC_ASCII);
4159             } else {
4160                 expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4161                     "Invalid suboption length: %u (must be > 2)", subopt_len);
4162             }
4163             break;
4164         default:
4165             if (subopt_len > 2) {
4166                 proto_tree_add_item(suboption_tree, hf_bap_unknown_option_data, tvb, offset + 2, subopt_len - 2, ENC_NA);
4167             } else {
4168                 expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
4169                     "Invalid suboption length: %u (must be > 2)", subopt_len);
4170             }
4171             break;
4172         }
4173         offset += subopt_len;
4174         length -= subopt_len;
4175     }
4176     return tvb_captured_length(tvb);
4177 }
4178 
4179 static int
dissect_bap_no_phone_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4180 dissect_bap_no_phone_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4181 {
4182     proto_tree* field_tree;
4183     proto_item* tf;
4184 
4185     dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_no_phone, ett_bap_no_phone_opt, 2,
4186                                   &field_tree, &tf);
4187     return tvb_captured_length(tvb);
4188 }
4189 
4190 static int
dissect_bap_reason_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4191 dissect_bap_reason_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4192 {
4193     proto_tree* field_tree;
4194     proto_item* tf;
4195     int offset = 0;
4196     int length = tvb_reported_length(tvb);
4197 
4198     if (!dissect_bap_var_opt(tvb, pinfo, tree, proto_bap_option_reason, ett_bap_reason_opt, 2,
4199                                   &field_tree, &tf))
4200         return tvb_captured_length(tvb);
4201 
4202     proto_tree_add_item(field_tree, hf_bap_reason, tvb, offset+2, length-2, ENC_NA|ENC_ASCII);
4203     return tvb_captured_length(tvb);
4204 }
4205 
4206 static int
dissect_bap_link_disc_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4207 dissect_bap_link_disc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4208 {
4209     proto_tree* field_tree;
4210     proto_item* tf;
4211     int offset = 0;
4212 
4213     if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_link_disc, ett_bap_link_disc_opt, 4,
4214                                   &field_tree, &tf))
4215         return tvb_captured_length(tvb);
4216 
4217     proto_tree_add_item(field_tree, hf_bap_link_discriminator, tvb, offset+2, 2, ENC_BIG_ENDIAN);
4218     return tvb_captured_length(tvb);
4219 }
4220 
4221 static int
dissect_bap_call_status_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4222 dissect_bap_call_status_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4223 {
4224     proto_tree* field_tree;
4225     proto_item* tf;
4226     int offset = 0;
4227 
4228     if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_call_status, ett_bap_call_status_opt, 4,
4229                                   &field_tree, &tf))
4230         return tvb_captured_length(tvb);
4231 
4232     proto_tree_add_item(field_tree, hf_bap_call_status, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
4233     proto_tree_add_item(field_tree, hf_bap_call_action, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
4234     return tvb_captured_length(tvb);
4235 }
4236 
4237 static void
dissect_vsncp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4238 dissect_vsncp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
4239     const char *name)
4240 {
4241     guint8 type;
4242 
4243     type = tvb_get_guint8(tvb, offset);
4244     proto_tree_add_uint_format_value(tree, hf_vsncp_opt_type, tvb, offset, 1,
4245         type, "%s (%u)", name, type);
4246     proto_tree_add_item(tree, hf_vsncp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
4247 }
4248 
4249 static gboolean
dissect_vsncp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)4250 dissect_vsncp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4251                              int proto, int ett, int expected_length,
4252                              proto_tree** ret_tree, proto_item** ret_item)
4253 {
4254     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
4255         return FALSE;
4256 
4257     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
4258     *ret_tree = proto_item_add_subtree(*ret_item, ett);
4259 
4260     dissect_vsncp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
4261     return TRUE;
4262 }
4263 
4264 static int
dissect_vsncp_pdnid_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4265 dissect_vsncp_pdnid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4266 {
4267     proto_tree *field_tree;
4268     proto_item *tf;
4269     int offset = 0;
4270 
4271     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4272                              proto_vsncp_option_pdnid, ett_vsncp_pdnid_opt, 3,
4273                              &field_tree, &tf))
4274         return tvb_captured_length(tvb);
4275 
4276     proto_tree_add_item(field_tree, hf_vsncp_pdn_identifier, tvb, offset+2, 1, ENC_BIG_ENDIAN);
4277     return tvb_captured_length(tvb);
4278 }
4279 
4280 static const value_string vsncp_attach_vals[] = {
4281     {1, "Initial Attach"},
4282     {3, "Handover Attach"},
4283     {0, NULL}
4284 };
4285 
4286 static int
dissect_vsncp_attachtype_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4287 dissect_vsncp_attachtype_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4288 {
4289     proto_tree *field_tree;
4290     proto_item *tf;
4291     int offset = 0;
4292 
4293     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4294                              proto_vsncp_option_attachtype, ett_vsncp_attachtype_opt, 3,
4295                              &field_tree, &tf))
4296         return tvb_captured_length(tvb);
4297 
4298     proto_tree_add_item(field_tree, hf_vsncp_attach_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
4299     return tvb_captured_length(tvb);
4300 }
4301 
4302 static const value_string vsncp_pdntype_vals[] = {
4303     {0, "Initial Request by UE"},
4304     {1, "IPv4"},
4305     {2, "IPv6"},
4306     {3, "IPv6/IPv4"},
4307     {0, NULL}
4308 };
4309 
4310 static int
dissect_vsncp_pdntype_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4311 dissect_vsncp_pdntype_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4312 {
4313     proto_tree *field_tree;
4314     proto_item *tf;
4315     int offset = 0;
4316 
4317     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4318                              proto_vsncp_option_pdntype, ett_vsncp_pdntype_opt, 3,
4319                              &field_tree, &tf))
4320         return tvb_captured_length(tvb);
4321 
4322     proto_tree_add_item(field_tree, hf_vsncp_pdn_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
4323     return tvb_captured_length(tvb);
4324 }
4325 
4326 static const value_string vsncp_errorcode_vals[] = {
4327     {0,  "General Error"},
4328     {1,  "Unauthorized APN"},
4329     {2,  "PDN Limit Exceeded"},
4330     {3,  "NO PG-W Available"},
4331     {4,  "P-GW Unreachable"},
4332     {5,  "P-GW Reject"},
4333     {6,  "Insufficient Parameters"},
4334     {7,  "Resource Unavailable"},
4335     {8,  "Admin Prohibited"},
4336     {9,  "PDN-ID Already in Use"},
4337     {10, "Subscription Limitation"},
4338     {11, "PDN connection already exists for APN"},
4339     {12, "Emergency services not supported"},
4340     {13, "Reconnect to this APN not allowed"},
4341     {14, "APN congested"},
4342     {0,  NULL}
4343 };
4344 
4345 static int
dissect_vsncp_errorcode_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4346 dissect_vsncp_errorcode_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4347 {
4348     proto_tree *field_tree;
4349     proto_item *tf;
4350     int offset = 0;
4351     int length = tvb_reported_length(tvb);
4352 
4353     if (length < 3) {
4354         /* Bogus - option length isn't what it's supposed to be for this option. */
4355         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
4356                             "%s (with option length = %u byte%s; should be at least %u)",
4357                             proto_get_protocol_short_name(find_protocol_by_id(proto_vsncp_option_errorcode )),
4358                             length, plurality(length, "", "s"), 3);
4359         return tvb_captured_length(tvb);
4360     }
4361 
4362     tf = proto_tree_add_item(tree, proto_vsncp_option_errorcode, tvb, 0, length, ENC_NA);
4363     field_tree = proto_item_add_subtree(tf, ett_vsncp_errorcode_opt);
4364 
4365     dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pdnaddress));
4366 
4367     proto_tree_add_item(field_tree, hf_vsncp_error_code, tvb, offset+2, 1, ENC_BIG_ENDIAN);
4368     return tvb_captured_length(tvb);
4369 }
4370 
4371 static int
dissect_vsncp_pdnaddress_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4372 dissect_vsncp_pdnaddress_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4373 {
4374     proto_tree *field_tree;
4375     proto_item *tf;
4376     int offset = 0;
4377     int length = tvb_reported_length(tvb);
4378     guint32 pdnaddtype;
4379 
4380     if (length < 3) {
4381         /* Bogus - option length isn't what it's supposed to be for this option. */
4382         proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
4383                             "%s (with option length = %u byte%s; should be at least %u)",
4384                             proto_get_protocol_short_name(find_protocol_by_id(proto_vsncp_option_pdnaddress )),
4385                             length, plurality(length, "", "s"), 3);
4386         return tvb_captured_length(tvb);
4387     }
4388 
4389     tf = proto_tree_add_item(tree, proto_vsncp_option_pdnaddress, tvb, 0, length, ENC_NA);
4390     field_tree = proto_item_add_subtree(tf, ett_vsncp_pdnaddress_opt);
4391 
4392     dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pdnaddress));
4393 
4394     proto_tree_add_item_ret_uint(field_tree, hf_vsncp_pdn_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN, &pdnaddtype);
4395 
4396     switch (pdnaddtype) {
4397     case 1:
4398         proto_tree_add_ipv4_format(field_tree, hf_vsncp_pdn_ipv4, tvb, offset + 3, 4,
4399             tvb_get_ntohl(tvb, offset + 3), "%s: %s",
4400             val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
4401             tvb_ip_to_str(pinfo->pool, tvb, offset + 3));
4402         break;
4403 
4404     case 2:
4405     {
4406         ws_in6_addr *ad = wmem_new0(pinfo->pool,ws_in6_addr);
4407         address addr;
4408 
4409         tvb_memcpy(tvb, &ad->bytes[8], offset + 3, 8);
4410         set_address(&addr, AT_IPv6, 16, ad->bytes);
4411         proto_tree_add_ipv6_format(field_tree, hf_vsncp_pdn_ipv6, tvb, offset + 3, length - 3, ad,
4412             "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
4413             address_to_str(pinfo->pool, &addr));
4414         break;
4415     }
4416 
4417     case 3:
4418     {
4419         ws_in6_addr *ad = wmem_new0(pinfo->pool, ws_in6_addr);
4420         address addr;
4421 
4422         tvb_memcpy(tvb, &ad->bytes[8], offset + 3, 8);
4423         set_address(&addr, AT_IPv6, 16, ad->bytes);
4424         proto_tree_add_ipv6_format(field_tree, hf_vsncp_pdn_ipv6, tvb, offset + 3, length - 3, ad,
4425             "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
4426             address_to_str(pinfo->pool, &addr));
4427         proto_tree_add_ipv4_format(field_tree, hf_vsncp_pdn_ipv4, tvb, offset + 11, length - 11,
4428             tvb_get_ntohl(tvb, offset + 11), "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
4429             tvb_ip_to_str(pinfo->pool, tvb, offset + 11));
4430         break;
4431     }
4432 
4433     default:
4434         break;
4435     }
4436 
4437     return tvb_captured_length(tvb);
4438 }
4439 
4440 static int
dissect_vsncp_ipv4address_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4441 dissect_vsncp_ipv4address_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4442 {
4443     proto_tree *field_tree;
4444     proto_item *tf;
4445     int offset = 0;
4446 
4447     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4448                              proto_vsncp_option_ipv4address, ett_vsncp_ipv4address_opt, 6,
4449                              &field_tree, &tf))
4450         return tvb_captured_length(tvb);
4451 
4452     proto_tree_add_item(field_tree, hf_vsncp_default_router_address, tvb, offset+2, 4, ENC_BIG_ENDIAN);
4453     return tvb_captured_length(tvb);
4454 }
4455 
4456 static int
dissect_vsncp_apname_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4457 dissect_vsncp_apname_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
4458 {
4459     proto_tree *field_tree;
4460     proto_item *tf;
4461     int offset = 0;
4462     int length = tvb_reported_length(tvb);
4463 
4464     tf = proto_tree_add_item(tree, proto_vsncp_option_apname, tvb, 0, length, ENC_NA);
4465     field_tree = proto_item_add_subtree(tf, ett_vsncp_apname_opt);
4466 
4467     dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_apname));
4468 
4469     if (length > 2) {
4470         guint8 i = 0;
4471         guint8 j = 1;
4472         guint8 lengthofapn;
4473         int off = offset + 2;
4474 
4475         while (i < (length - 2)) {
4476             lengthofapn = tvb_get_guint8(tvb, off++);
4477             proto_tree_add_string_format(field_tree, hf_vsncp_access_point_name, tvb, off, lengthofapn,
4478                 tvb_get_string_enc(pinfo->pool, tvb, off, lengthofapn, ENC_ASCII),
4479                 "Label%d (%d byte%s): %s", j++, lengthofapn,
4480                 plurality(lengthofapn, "", "s"),
4481                 tvb_format_text(pinfo->pool, tvb, off, lengthofapn));
4482             off += lengthofapn;
4483             i += lengthofapn + 1;
4484         }
4485     }
4486     return tvb_captured_length(tvb);
4487 }
4488 
4489 static const value_string vsncp_alloc_vals[] = {
4490     {0,   "Null Value (Attach or Handover)"},
4491     {18,  "New PDN type due to network preference"},
4492     {255, "Success"},
4493     {0,   NULL}
4494 };
4495 
4496 static int
dissect_vsncp_addressalloc_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4497 dissect_vsncp_addressalloc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4498 {
4499     proto_tree *field_tree;
4500     proto_item *tf;
4501     int offset = 0;
4502 
4503     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4504                              proto_vsncp_option_addressalloc, ett_vsncp_addressalloc_opt, 3,
4505                              &field_tree, &tf))
4506         return tvb_captured_length(tvb);
4507 
4508     proto_tree_add_item(field_tree, hf_vsncp_address_allocation_cause, tvb, offset+2, 1, ENC_BIG_ENDIAN);
4509     return tvb_captured_length(tvb);
4510 }
4511 
4512 static int
dissect_vsncp_apn_ambr_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4513 dissect_vsncp_apn_ambr_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
4514 {
4515     proto_tree *field_tree;
4516     proto_item *tf;
4517     int offset = 0;
4518     int length = tvb_reported_length(tvb);
4519 
4520     tf = proto_tree_add_item(tree, proto_vsncp_option_apn_ambr, tvb, 0, length, ENC_NA);
4521     field_tree = proto_item_add_subtree(tf, ett_vsncp_apn_ambr_opt);
4522 
4523     dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_apn_ambr ));
4524     proto_tree_add_item(field_tree, hf_vsncp_ambr_data, tvb, offset+2, length-2, ENC_NA);
4525 
4526     return tvb_captured_length(tvb);
4527 }
4528 
4529 static int
dissect_vsncp_ipv6_hsgw_lla_iid_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4530 dissect_vsncp_ipv6_hsgw_lla_iid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4531 {
4532     proto_tree *field_tree;
4533     proto_item *tf;
4534     int offset = 0;
4535 
4536     if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
4537                              proto_vsncp_option_ipv6_hsgw_lla_iid, ett_vsncp_ipv6_hsgw_lla_iid_opt, 10,
4538                              &field_tree, &tf))
4539         return tvb_captured_length(tvb);
4540 
4541     proto_tree_add_item(field_tree, hf_vsncp_ipv6_interface_identifier, tvb, offset+2, 8, ENC_NA);
4542     return tvb_captured_length(tvb);
4543 }
4544 
4545 /* Ch 10.5.6.3 3GPP TS 24.008 version 11.5.0 Release 11 */
4546 static const value_string vsncp_pco_vals[] = {
4547     {0x8021, "IPCP (DNS Address Request)"},
4548     {0x0001, "P-CSCF Address Request (IPv6)"},
4549     {0x0005, "MS Support of Network Requested Bearer Control indicator"},
4550     {0x0003, "DNS Server Address (IPv6)"},
4551     {0x000A, "IP address allocation via NAS signalling"},
4552     {0x000B, "IPv4 address allocation via DHCPv4"},
4553     {0x000D, "DNS Server IPv4 Address Request"},
4554     {0,      NULL}
4555 };
4556 
4557 static int
dissect_vsncp_pco_opt(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4558 dissect_vsncp_pco_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
4559 {
4560     guint8 len;
4561     proto_tree *field_tree;
4562     proto_item *tf;
4563     int length = tvb_reported_length(tvb);
4564     int offset = 3;
4565     guint8  i = 0;
4566 
4567     tf = proto_tree_add_item(tree, proto_vsncp_option_pco, tvb, 0, length, ENC_NA);
4568     field_tree = proto_item_add_subtree(tf, ett_vsncp_pco_opt);
4569 
4570     dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pco));
4571 
4572     while (i < (length - 3)) {
4573         len = tvb_get_guint8(tvb, (offset + 2));
4574         proto_tree_add_item(field_tree, hf_vsncp_protocol, tvb, offset, 2, ENC_BIG_ENDIAN);
4575         proto_tree_add_item(field_tree, hf_vsncp_protocol_configuration_length, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
4576         if (len > 0) {
4577             proto_tree_add_item(field_tree, hf_vsncp_protocol_configuration_data, tvb, offset + 3, len, ENC_NA);
4578         }
4579 
4580         offset += 3 + len;
4581         i += 3 + len;
4582     }
4583 
4584     return tvb_captured_length(tvb);
4585 }
4586 
4587 static void
dissect_cp(tvbuff_t * tvb,int proto_id,int proto_subtree_index,const value_string * proto_vals,int options_subtree_index,dissector_table_t option_table,packet_info * pinfo,proto_tree * tree)4588 dissect_cp(tvbuff_t *tvb, int proto_id, int proto_subtree_index,
4589     const value_string *proto_vals, int options_subtree_index,
4590     dissector_table_t option_table, packet_info *pinfo, proto_tree *tree)
4591 {
4592     proto_item *ti;
4593     proto_tree *fh_tree;
4594     guint8 code;
4595     int length, offset;
4596     guint32 oui;
4597     const gchar *manuf;
4598     guint32 secs_remaining;
4599 
4600     code   = tvb_get_guint8(tvb, 0);
4601     length = tvb_get_ntohs(tvb, 2);
4602 
4603     col_set_str(pinfo->cinfo, COL_PROTOCOL,
4604         proto_get_protocol_short_name(find_protocol_by_id(proto_id)));
4605     col_set_str(pinfo->cinfo, COL_INFO,
4606         val_to_str_const(code, proto_vals, "Unknown"));
4607 
4608     ti = proto_tree_add_item(tree, proto_id, tvb, 0, length, ENC_NA);
4609     fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
4610     proto_tree_add_uint_format_value(fh_tree, hf_ppp_code, tvb, 0, 1, code,
4611             "%s (%u)", val_to_str_const(code, proto_vals, "Unknown"), code);
4612     proto_tree_add_item(fh_tree, hf_ppp_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
4613     proto_tree_add_item(fh_tree, hf_ppp_length, tvb, 2, 2, ENC_BIG_ENDIAN);
4614 
4615     offset = 4;
4616     length -= 4;
4617 
4618     switch (code) {
4619     case VNDRSPCFC:
4620         proto_tree_add_item(fh_tree, hf_ppp_magic_number, tvb, offset, 4,
4621                 ENC_BIG_ENDIAN);
4622         oui = tvb_get_ntoh24(tvb, offset + 4);
4623         ti = proto_tree_add_uint_format_value(fh_tree, hf_ppp_oui, tvb,
4624                 offset + 4, 3, oui, "%02x:%02x:%02x", (oui >> 16) & 0xff,
4625                 (oui >> 8) & 0xff, oui & 0xff);
4626         manuf = uint_get_manuf_name_if_known(oui);
4627         if (manuf){
4628             proto_item_append_text(ti, "(%s)", manuf);
4629         }
4630         proto_tree_add_item(fh_tree, hf_ppp_kind, tvb, offset + 7, 1,
4631                 ENC_BIG_ENDIAN);
4632         if (length > 8) {
4633             proto_tree_add_item(fh_tree, hf_ppp_data, tvb, offset + 8,
4634                     length - 8, ENC_NA);
4635         }
4636         break;
4637 
4638     case CONFREQ:
4639     case CONFACK:
4640     case CONFNAK:
4641     case CONFREJ:
4642         if (length > 0) {
4643             proto_tree *field_tree;
4644 
4645             field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
4646                 options_subtree_index, NULL, "Options: (%d byte%s)", length, plurality(length, "", "s"));
4647             ppp_dissect_options(tvb, offset, length, option_table, pinfo, field_tree);
4648         }
4649         break;
4650 
4651     case CODEREJ:
4652         if (length > 0) {
4653             /* TODO: Decode the rejected packet here ... but wait until we have
4654              * a valid capture file with a CODEREJ, since the only capture file
4655              * with CODEREJ packets in it that I know of is pppoe.dump.gz from
4656              * the menagerie, and that file appears to have malformed CODEREJ
4657              * packets as they don't include the Code, Identifier or Length
4658              * fields so it's impossible to do the decode. */
4659             proto_tree_add_bytes_format(fh_tree, hf_ppp_data, tvb, offset,
4660                 length, NULL, "Rejected Packet (%d byte%s): %s", length,
4661                 plurality(length, "", "s"),
4662                 tvb_bytes_to_str(pinfo->pool, tvb, offset, length));
4663         }
4664         break;
4665 
4666     case PROTREJ:       /* LCP only: RFC 1661 */
4667         proto_tree_add_item(fh_tree, hf_lcp_rej_proto, tvb, offset, 2,
4668                 ENC_BIG_ENDIAN);
4669         if (length > 2) {
4670             gboolean save_in_error_pkt;
4671             tvbuff_t *next_tvb;
4672             guint16 protocol;
4673 
4674             protocol = tvb_get_ntohs(tvb, offset);
4675             offset += 2;
4676             length -= 2;
4677 
4678             /*
4679              * Save the current value of the "we're inside an error packet"
4680              * flag, and set that flag; subdissectors may treat packets that
4681              * are the payload of error packets differently from "real"
4682              * packets.
4683              */
4684             save_in_error_pkt = pinfo->flags.in_error_pkt;
4685             pinfo->flags.in_error_pkt = TRUE;
4686 
4687             /* Decode the rejected packet. */
4688             next_tvb = tvb_new_subset_length(tvb, offset, length);
4689             if (!dissector_try_uint(ppp_subdissector_table, protocol, next_tvb,
4690                 pinfo, fh_tree)) {
4691                 call_data_dissector(next_tvb, pinfo, fh_tree);
4692             }
4693 
4694             /* Restore the "we're inside an error packet" flag. */
4695             pinfo->flags.in_error_pkt = save_in_error_pkt;
4696         }
4697         break;
4698 
4699     case ECHOREQ: /* All 3 are LCP only: RFC 1661 */
4700     case ECHOREP:
4701     case DISCREQ:
4702         proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
4703                 ENC_BIG_ENDIAN);
4704         if (length > 4) {
4705             proto_tree_add_item(fh_tree, hf_lcp_data, tvb, offset + 4,
4706                     length - 4, ENC_NA);
4707         }
4708         break;
4709 
4710     case IDENT:         /* LCP only: RFC 1570 */
4711         proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
4712                 ENC_BIG_ENDIAN);
4713         if (length > 4) {
4714             proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 4,
4715                     length - 4, ENC_ASCII|ENC_NA);
4716         }
4717         break;
4718 
4719     case TIMEREMAIN:    /* LCP only: RFC 1570 */
4720         proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
4721                 ENC_BIG_ENDIAN);
4722         secs_remaining = tvb_get_ntohl(tvb, offset + 4);
4723         proto_tree_add_uint_format_value(fh_tree, hf_lcp_secs_remaining,
4724                 tvb, offset + 4, 4, secs_remaining, "%u %s", secs_remaining,
4725                 (secs_remaining == 0xffffffff) ? "(forever)" : "seconds");
4726         if (length > 8) {
4727             proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 8,
4728                     length - 8, ENC_ASCII|ENC_NA);
4729         }
4730         break;
4731 
4732     case TERMREQ:
4733     case TERMACK:
4734     case RESETREQ:  /* RESETREQ and RESETACK are CCP only: RFC 1962 */
4735     case RESETACK:
4736     default:
4737         if (length > 0) {
4738             proto_tree_add_item(fh_tree, hf_ppp_data, tvb, offset, length,
4739                 ENC_NA);
4740         }
4741         break;
4742     }
4743 }
4744 
4745 /* Protocol field compression */
4746 #define PFC_BIT 0x01
4747 
4748 static void
dissect_ppp_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * fh_tree,proto_item * ti,int proto_offset)4749 dissect_ppp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4750     proto_tree *fh_tree, proto_item *ti, int proto_offset)
4751 {
4752     guint16   ppp_prot;
4753     int       proto_len;
4754     tvbuff_t *next_tvb;
4755 
4756     /* Make direction information filterable */
4757     if (pinfo->p2p_dir == P2P_DIR_RECV || pinfo->p2p_dir == P2P_DIR_SENT) {
4758         proto_item *direction_ti = proto_tree_add_uint(fh_tree, hf_ppp_direction,
4759             tvb, 0, 0, pinfo->p2p_dir);
4760         proto_item_set_generated(direction_ti);
4761     }
4762 
4763     ppp_prot = tvb_get_guint8(tvb, 0);
4764     if (ppp_prot & PFC_BIT) {
4765         /* Compressed protocol field - just the byte we fetched. */
4766         proto_len = 1;
4767     } else {
4768         /* Uncompressed protocol field - fetch all of it. */
4769         ppp_prot = tvb_get_ntohs(tvb, 0);
4770         proto_len = 2;
4771     }
4772 
4773     /* If "ti" is not null, it refers to the top-level "proto_ppp" item
4774        for PPP, and proto_offset is the length of any stuff in the header
4775        preceding the protocol type, e.g. an HDLC header; add the length
4776        of the protocol type field to it, and set the length of that item
4777        to the result. */
4778     proto_item_set_len(ti, proto_offset + proto_len);
4779 
4780     proto_tree_add_uint(fh_tree, hf_ppp_protocol, tvb, 0, proto_len,
4781             ppp_prot);
4782 
4783     next_tvb = tvb_new_subset_remaining(tvb, proto_len);
4784 
4785     /* do lookup with the subdissector table */
4786     if (!dissector_try_uint(ppp_subdissector_table, ppp_prot, next_tvb, pinfo,
4787         tree)) {
4788         col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ppp_prot);
4789         col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
4790             val_to_str_ext_const(ppp_prot, &ppp_vals_ext, "Unknown"),
4791             ppp_prot);
4792         call_data_dissector(next_tvb, pinfo, tree);
4793     }
4794 }
4795 
4796 static int
dissect_lcp_options(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4797 dissect_lcp_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4798 {
4799     ppp_dissect_options(tvb, 0, tvb_reported_length(tvb), lcp_option_table, pinfo, tree);
4800     return tvb_captured_length(tvb);
4801 }
4802 
4803 /*
4804  * RFC's 1661, 2153 and 1570.
4805  */
4806 static int
dissect_lcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4807 dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4808 {
4809     dissect_cp(tvb, proto_lcp, ett_lcp, lcp_vals, ett_lcp_options, lcp_option_table, pinfo, tree);
4810     return tvb_captured_length(tvb);
4811 }
4812 
4813 static int
dissect_vsncp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4814 dissect_vsncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4815 {
4816     proto_item *ti;
4817     proto_tree *fh_tree;
4818     proto_tree *field_tree;
4819     guint8 code;
4820     int length, offset;
4821 
4822     code = tvb_get_guint8(tvb, 0);
4823     length = tvb_get_ntohs(tvb, 2);
4824 
4825     col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNCP");
4826     col_set_str(pinfo->cinfo, COL_INFO,
4827         val_to_str_const(code, cp_vals, "Unknown"));
4828 
4829     ti = proto_tree_add_item(tree, proto_vsncp, tvb, 0, length, ENC_NA);
4830     fh_tree = proto_item_add_subtree(ti, ett_vsncp);
4831     proto_tree_add_item(fh_tree, hf_vsncp_code, tvb, 0, 1, ENC_BIG_ENDIAN);
4832     proto_tree_add_item(fh_tree, hf_vsncp_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
4833     proto_tree_add_item(fh_tree, hf_vsncp_length, tvb, 2, 2, ENC_BIG_ENDIAN);
4834     proto_tree_add_item(fh_tree, hf_ppp_oui, tvb, 4, 3, ENC_BIG_ENDIAN);
4835 
4836     offset = 7;
4837     length -= 7;
4838 
4839     switch (code) {
4840     case CONFREQ:
4841     case CONFACK:
4842     case CONFNAK:
4843     case CONFREJ:
4844     case TERMREQ:
4845     case TERMACK:
4846         if (length > 0) {
4847             field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
4848                                      ett_vsncp_options, NULL, "Options: (%d byte%s)", length,
4849                                      plurality(length, "", "s"));
4850             ppp_dissect_options(tvb, offset, length, vsncp_option_table, pinfo, field_tree);
4851         }
4852         break;
4853 
4854     default:
4855         /* TODO? */
4856         break;
4857     }
4858     return tvb_captured_length(tvb);
4859 }
4860 
4861 static int
dissect_vsnp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4862 dissect_vsnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4863 {
4864     proto_item *vsnp_item;
4865     proto_tree *vsnp_tree;
4866     tvbuff_t *next_tvb;
4867 
4868     col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNP");
4869 
4870     vsnp_item = proto_tree_add_item(tree, proto_vsnp, tvb, 0, -1, ENC_NA);
4871     vsnp_tree = proto_item_add_subtree(vsnp_item, ett_vsnp);
4872     proto_tree_add_item(vsnp_tree, hf_vsnp_pdnid, tvb, 0, 1,
4873             ENC_BIG_ENDIAN);
4874 
4875     next_tvb = tvb_new_subset_remaining(tvb, 1);
4876     if (!dissector_try_uint(ppp_subdissector_table, PPP_IP, next_tvb, pinfo,
4877         tree)) {
4878         col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", PPP_IP);
4879         col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
4880             val_to_str_ext_const(PPP_IP, &ppp_vals_ext, "Unknown"), PPP_IP);
4881         call_data_dissector(next_tvb, pinfo, tree);
4882     }
4883     return tvb_captured_length(tvb);
4884 }
4885 
4886 /*
4887  * RFC 1332.
4888  */
4889 static int
dissect_ipcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4890 dissect_ipcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4891 {
4892     dissect_cp(tvb, proto_ipcp, ett_ipcp, cp_vals, ett_ipcp_options, ipcp_option_table,
4893                 pinfo, tree);
4894     return tvb_captured_length(tvb);
4895 }
4896 
4897 /*
4898  * RFC 3518
4899  */
4900 #define BCP_FCS_PRESENT         0x80
4901 #define BCP_ZEROPAD             0x20
4902 #define BCP_IS_BCONTROL         0x10
4903 #define BCP_PADS_MASK           0x0f
4904 
4905 #define BCP_MACT_ETHERNET       1
4906 #define BCP_MACT_802_4          2
4907 #define BCP_MACT_802_5_NONCANON 3
4908 #define BCP_MACT_FDDI_NONCANON  4
4909 #define BCP_MACT_802_5_CANON    11
4910 #define BCP_MACT_FDDI_CANON     12
4911 
4912 static const value_string bcp_bpdu_mac_type_vals[] = {
4913     {BCP_MACT_ETHERNET,       "IEEE 802.3/Ethernet"},
4914     {BCP_MACT_802_4,          "IEEE 802.4"},
4915     {BCP_MACT_802_5_NONCANON, "IEEE 802.5, non-canonical addresses"},
4916     {BCP_MACT_FDDI_NONCANON,  "FDDI, non-canonical addresses"},
4917     {BCP_MACT_802_5_CANON,    "IEEE 802.5, canonical addresses"},
4918     {BCP_MACT_FDDI_CANON,     "FDDI, canonical addresses"},
4919     {0,                       NULL}
4920 };
4921 
4922 static int
dissect_bcp_bpdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4923 dissect_bcp_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4924 {
4925     proto_item *ti;
4926     proto_tree *bcp_bpdu_tree;
4927     int offset = 0;
4928     guint8 flags;
4929     guint8 mac_type;
4930     gint captured_length, reported_length, pad_length;
4931     tvbuff_t *next_tvb;
4932     static int * const bcp_bpdu_flags[] = {
4933         &hf_bcp_bpdu_fcs_present,
4934         &hf_bcp_bpdu_zeropad,
4935         &hf_bcp_bpdu_bcontrol,
4936         &hf_bcp_bpdu_pads,
4937         NULL
4938     };
4939 
4940     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP BCP");
4941     col_clear(pinfo->cinfo, COL_INFO);
4942 
4943     ti = proto_tree_add_item(tree, proto_bcp_bpdu, tvb, 0, -1, ENC_NA);
4944     bcp_bpdu_tree = proto_item_add_subtree(ti, ett_bcp_bpdu);
4945 
4946     flags = tvb_get_guint8(tvb, offset);
4947     if (flags & BCP_IS_BCONTROL) {
4948         col_set_str(pinfo->cinfo, COL_INFO, "Bridge control");
4949     }
4950 
4951     proto_tree_add_bitmask(bcp_bpdu_tree, tvb, offset, hf_bcp_bpdu_flags, ett_bcp_bpdu_flags, bcp_bpdu_flags, ENC_NA);
4952     offset++;
4953 
4954     mac_type = tvb_get_guint8(tvb, offset);
4955     if (!(flags & BCP_IS_BCONTROL)) {
4956         col_add_str(pinfo->cinfo, COL_INFO,
4957                 val_to_str(mac_type, bcp_bpdu_mac_type_vals,
4958                 "Unknown MAC type %u"));
4959     }
4960     proto_tree_add_uint(bcp_bpdu_tree, hf_bcp_bpdu_mac_type, tvb, offset, 1, mac_type);
4961     offset++;
4962 
4963     switch (mac_type) {
4964 
4965     case BCP_MACT_802_4:
4966     case BCP_MACT_802_5_NONCANON:
4967     case BCP_MACT_FDDI_NONCANON:
4968     case BCP_MACT_802_5_CANON:
4969     case BCP_MACT_FDDI_CANON:
4970         proto_tree_add_item(bcp_bpdu_tree, hf_bcp_bpdu_pad, tvb, offset, 1, ENC_NA);
4971         offset++;
4972         break;
4973 
4974     default:
4975         /* TODO? */
4976         break;
4977     }
4978 
4979     proto_item_set_len(ti, offset);
4980 
4981     if (!(flags & BCP_IS_BCONTROL)) {
4982         captured_length = tvb_captured_length_remaining(tvb, offset);
4983         reported_length = tvb_reported_length_remaining(tvb, offset);
4984         pad_length = flags & BCP_PADS_MASK;
4985         if (reported_length >= pad_length) {
4986             reported_length -= pad_length;
4987             if (captured_length > reported_length)
4988                 captured_length = reported_length;
4989             next_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_length,
4990                 reported_length);
4991             switch (mac_type) {
4992 
4993             case BCP_MACT_ETHERNET:
4994                 if (flags & BCP_FCS_PRESENT) {
4995                     call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree);
4996                 } else {
4997                     call_dissector(eth_withoutfcs_handle, next_tvb, pinfo,
4998                         tree);
4999                 }
5000                 break;
5001 
5002             case BCP_MACT_802_4:
5003             case BCP_MACT_802_5_NONCANON:
5004             case BCP_MACT_FDDI_NONCANON:
5005             case BCP_MACT_802_5_CANON:
5006             case BCP_MACT_FDDI_CANON:
5007                 break;
5008 
5009             default:
5010                 call_data_dissector(next_tvb, pinfo, tree);
5011                 break;
5012             }
5013         }
5014     }
5015     return tvb_captured_length(tvb);
5016 }
5017 
5018 /* RFC 3518
5019  * 4.  A PPP Network Control Protocol for Bridging
5020  * :
5021  * The Bridging Control Protocol is exactly the same as the Link Control
5022  * Protocol [6] with the following exceptions...
5023  * :
5024  * ---the PPP Protocol field indicates type hex 8031 (BCP).
5025  */
5026 static int
dissect_bcp_ncp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5027 dissect_bcp_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5028 {
5029     dissect_cp(tvb, proto_bcp_ncp, ett_bcp_ncp, lcp_vals, ett_bcp_ncp_options,
5030         bcp_ncp_option_table, pinfo, tree);
5031     return tvb_captured_length(tvb);
5032 }
5033 
5034 /*
5035  * RFC 1377.
5036  */
5037 static int
dissect_osinlcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5038 dissect_osinlcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5039 {
5040     dissect_cp(tvb, proto_osinlcp, ett_osinlcp, cp_vals, ett_osinlcp_options, osinlcp_option_table,
5041         pinfo, tree);
5042     return tvb_captured_length(tvb);
5043 }
5044 
5045 /*
5046  * RFC 1962.
5047  */
5048 static int
dissect_ccp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5049 dissect_ccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5050 {
5051     dissect_cp(tvb, proto_ccp, ett_ccp, ccp_vals, ett_ccp_options, ccp_option_table, pinfo, tree);
5052     return tvb_captured_length(tvb);
5053 }
5054 
5055 /*
5056  * Callback Control Protocol - see
5057  *
5058  * https://tools.ietf.org/html/draft-gidwani-ppp-callback-cp-00
5059  */
5060 static int
dissect_cbcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5061 dissect_cbcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5062 {
5063     dissect_cp(tvb, proto_cbcp, ett_cbcp, cbcp_vals, ett_cbcp_options,
5064         cbcp_option_table, pinfo, tree);
5065     return tvb_captured_length(tvb);
5066 }
5067 
5068 /*
5069  * RFC 2125 (BACP and BAP).
5070  */
5071 static int
dissect_bacp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5072 dissect_bacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5073 {
5074     dissect_cp(tvb, proto_bacp, ett_bacp, cp_vals, ett_bacp_options, bacp_option_table,
5075                 pinfo, tree);
5076     return tvb_captured_length(tvb);
5077 }
5078 
5079 static int
dissect_bap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5080 dissect_bap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5081 {
5082     proto_item *ti;
5083     proto_tree *fh_tree;
5084     proto_tree *field_tree;
5085     guint8 type;
5086     int length, offset;
5087 
5088     type = tvb_get_guint8(tvb, 0);
5089     length = tvb_get_ntohs(tvb, 2);
5090 
5091     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP BAP");
5092     col_set_str(pinfo->cinfo, COL_INFO,
5093         val_to_str_const(type, bap_vals, "Unknown"));
5094 
5095     ti = proto_tree_add_item(tree, proto_bap, tvb, 0, length, ENC_NA);
5096     fh_tree = proto_item_add_subtree(ti, ett_bap_options);
5097     proto_tree_add_item(fh_tree, hf_bap_type, tvb, 0, 1, ENC_BIG_ENDIAN);
5098     proto_tree_add_item(fh_tree, hf_bap_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
5099     proto_tree_add_item(fh_tree, hf_bap_length, tvb, 2, 2, ENC_BIG_ENDIAN);
5100 
5101     offset = 4;
5102     length -= 4;
5103 
5104     if (type == BAP_CRES || type == BAP_CBRES ||
5105         type == BAP_LDQRES || type == BAP_CSRES) {
5106         proto_tree_add_item(fh_tree, hf_bap_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
5107         offset++;
5108         length--;
5109     }
5110 
5111     if (length > 0) {
5112         field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
5113                                  ett_bap_options, NULL, "Data (%d byte%s)", length, plurality(length, "", "s"));
5114         ppp_dissect_options(tvb, offset, length, bap_option_table, pinfo, field_tree);
5115     }
5116     return tvb_captured_length(tvb);
5117 }
5118 
5119 #if 0 /* TODO? */
5120 static int
5121 dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5122 {
5123     proto_item *ti;
5124     proto_tree *comp_data_tree;
5125 
5126     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP Comp");
5127     col_set_str(pinfo->cinfo, COL_INFO, "Compressed data");
5128 
5129     ti = proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, ENC_NA);
5130     comp_data_tree = proto_item_add_subtree(ti, ett_comp_data);
5131 
5132     return tvb_captured_length(tvb);
5133 }
5134 #else
5135 static int
dissect_comp_data(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5136 dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5137 {
5138     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP Comp");
5139     col_set_str(pinfo->cinfo, COL_INFO, "Compressed data");
5140 
5141     proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, ENC_NA);
5142     return tvb_captured_length(tvb);
5143 }
5144 #endif
5145 
5146 /*
5147  * RFC 3153 (both PPPMuxCP and PPPMux).
5148  */
5149 static int
dissect_pppmuxcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5150 dissect_pppmuxcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5151 {
5152     dissect_cp(tvb, proto_pppmuxcp, ett_pppmuxcp, pppmuxcp_vals,
5153         ett_pppmuxcp_options, pppmuxcp_option_table, pinfo, tree);
5154     return tvb_captured_length(tvb);
5155 }
5156 
5157 #define PPPMUX_FLAGS_MASK          0xc0
5158 #define PPPMUX_PFF_BIT_SET         0x80
5159 #define PPPMUX_LXT_BIT_SET         0x40
5160 
5161 static int
dissect_pppmux(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5162 dissect_pppmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5163 {
5164     proto_tree     *mux_tree, *hdr_tree, *sub_tree;
5165     proto_tree     *info_tree;
5166     proto_item     *ti           = NULL;
5167     guint8          flags, byte;
5168     guint16         length;
5169     static guint16  pid;
5170     tvbuff_t       *next_tvb;
5171     int             offset       = 0, length_remaining;
5172     int             length_field = 0, pid_field = 0, hdr_length = 0;
5173     static int * const subframe_flags[] = {
5174         &hf_pppmux_flags_pid,
5175         &hf_pppmux_flags_field_length,
5176         NULL
5177     };
5178 
5179     col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPP PPPMux");
5180     col_set_str(pinfo->cinfo, COL_INFO, "PPP Multiplexing");
5181 
5182     length_remaining = tvb_reported_length(tvb);
5183 
5184     ti = proto_tree_add_item(tree, proto_pppmux, tvb, 0, -1, ENC_NA);
5185     mux_tree = proto_item_add_subtree(ti, ett_pppmux);
5186 
5187     while (length_remaining > 0) {
5188         flags = tvb_get_guint8(tvb,offset) & PPPMUX_FLAGS_MASK;
5189 
5190         if (flags & PPPMUX_LXT_BIT_SET) {
5191             length = tvb_get_ntohs(tvb,offset) & 0x3fff;
5192             length_field = 2;
5193         } else {
5194             length = tvb_get_guint8(tvb,offset) & 0x3f;
5195             length_field = 1;
5196         }
5197 
5198         if (flags & PPPMUX_PFF_BIT_SET) {
5199             byte = tvb_get_guint8(tvb,offset + length_field);
5200             if (byte & PFC_BIT) {             /* Compressed PID field */
5201                 pid = byte;
5202                 pid_field = 1;
5203             } else {                  /* PID field is 2 bytes */
5204                 pid = tvb_get_ntohs(tvb,offset + length_field);
5205                 pid_field = 2;
5206             }
5207         } else {
5208             pid_field = 0;   /* PID field is 0 bytes */
5209             if (!pid) {       /* No Last PID, hence use the default */
5210                 if (pppmux_def_prot_id)
5211                     pid = pppmux_def_prot_id;
5212             }
5213         }
5214 
5215         hdr_length = length_field + pid_field;
5216 
5217         sub_tree = proto_tree_add_subtree(mux_tree, tvb, offset, length + length_field,
5218             ett_pppmux_subframe, NULL, "PPPMux Sub-frame");
5219         hdr_tree = proto_tree_add_subtree(sub_tree, tvb, offset, hdr_length,
5220             ett_pppmux_subframe_hdr, NULL, "Header field");
5221 
5222         proto_tree_add_bitmask(tree, tvb, offset, hf_pppmux_flags, ett_pppmux_subframe_flags, subframe_flags, ENC_BIG_ENDIAN);
5223         proto_tree_add_uint(hdr_tree, hf_pppmux_sub_frame_length, tvb,offset, length_field, length);
5224 
5225         ti = proto_tree_add_uint(hdr_tree, hf_pppmux_protocol, tvb,
5226             offset + length_field, pid_field, pid);
5227 
5228         /* if protocol is not present in the sub-frame */
5229         if (!(flags & PPPMUX_PFF_BIT_SET)) {
5230             /* mark this item as generated */
5231             proto_item_set_generated(ti);
5232         }
5233 
5234         offset += hdr_length;
5235         length_remaining -= hdr_length;
5236         length -= pid_field;
5237 
5238         tvb_ensure_bytes_exist (tvb, offset, length);
5239         info_tree = proto_tree_add_subtree(sub_tree, tvb,offset, length,
5240             ett_pppmux_subframe_info, NULL, "Information Field");
5241         next_tvb = tvb_new_subset_length(tvb, offset, length);
5242 
5243         if (!dissector_try_uint(ppp_subdissector_table, pid, next_tvb, pinfo,
5244             info_tree)) {
5245             call_data_dissector(next_tvb, pinfo, info_tree);
5246         }
5247         offset += length;
5248         length_remaining -= length;
5249     }
5250     return tvb_captured_length(tvb);
5251 }
5252 
5253 /*
5254  * RFC 2507 / RFC 2508 Internet Protocol Header Compression
5255  */
5256 #define IPHC_CRTP_FH_FLAG_MASK   0xc0
5257 #define IPHC_CRTP_FH_CIDLEN_FLAG 0x80
5258 #define IPHC_CRTP_FH_DATA_FLAG   0x40
5259 
5260 #define IPHC_CRTP_CS_CID8        1
5261 #define IPHC_CRTP_CS_CID16       2
5262 
5263 static int * const iphc_crtp_fh_flags_fields[] = {
5264     &hf_iphc_crtp_fh_cidlenflag,
5265     &hf_iphc_crtp_fh_dataflag,
5266     NULL
5267 };
5268 
5269 static const true_false_string iphc_crtp_fh_cidlenflag = {
5270     "16-bit",
5271     "8-bit"
5272 };
5273 
5274 static const value_string iphc_crtp_cs_flags[] = {
5275     {IPHC_CRTP_CS_CID8,  "8-bit Context Id"},
5276     {IPHC_CRTP_CS_CID16, "16-bit Context Id"},
5277     {0,                  NULL}
5278 };
5279 
5280 static const crumb_spec_t iphc_crtp_cntcp_cid16_crumbs[] = {
5281     {0, 8},
5282     {16, 8},
5283     {0, 0}
5284 };
5285 
5286 /*
5287  * 0x61 Packets: Full IP/UDP Header
5288  */
5289 static int
dissect_iphc_crtp_fh(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5290 dissect_iphc_crtp_fh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5291 {
5292     proto_tree *fh_tree, *info_tree;
5293     proto_item *ti;
5294     guint     ip_hdr_len, flags, seq;
5295     guint     length;
5296     guint     hdr_len;
5297     tvbuff_t *next_tvb;
5298     int       offset_seq;
5299     int       offset_cid;
5300     guint8    ip_version;
5301     guint8    next_protocol;
5302     guchar   *ip_packet;
5303 
5304     length = tvb_reported_length(tvb);
5305 
5306     col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
5307     col_set_str(pinfo->cinfo, COL_INFO, "Full Header");
5308 
5309     /* only dissect IPv4 and UDP */
5310     ip_version = tvb_get_guint8(tvb, 0) >> 4;
5311     flags = (tvb_get_guint8(tvb, 2) & IPHC_CRTP_FH_FLAG_MASK);
5312     next_protocol = tvb_get_guint8(tvb, 9);
5313 
5314     ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
5315             "%s", val_to_str_ext_const(PPP_RTP_FH, &ppp_vals_ext, "Unknown"));
5316     fh_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
5317 
5318     proto_tree_add_bitmask_with_flags(fh_tree, tvb, 2, hf_iphc_crtp_fh_flags,
5319             ett_iphc_crtp_fh_flags, iphc_crtp_fh_flags_fields, ENC_BIG_ENDIAN,
5320             BMT_NO_FLAGS);
5321     proto_tree_add_item(fh_tree, hf_iphc_crtp_gen, tvb, 2, 1,
5322             ENC_BIG_ENDIAN);
5323 
5324     /* calculate length of IP header, assume IPv4 */
5325     ip_hdr_len = (tvb_get_guint8(tvb, 0) & 0x0f) * 4;
5326 
5327     /* calculate total hdr length, assume UDP */
5328     hdr_len = ip_hdr_len + 8;
5329 
5330     if (ip_version != 4) {
5331         proto_tree_add_expert_format(fh_tree, pinfo, &ei_iphc_crtp_ip_version, tvb, 3, -1,
5332                             "IP version is %u: the only supported version is 4",
5333                             ip_version);
5334         return 1;
5335     }
5336 
5337     if (next_protocol != IP_PROTO_UDP) {
5338         proto_tree_add_expert_format(fh_tree, pinfo, &ei_iphc_crtp_next_protocol, tvb, 3, -1,
5339                             "Next protocol is %s (%u): the only supported protocol is UDP",
5340                             ipprotostr(next_protocol), next_protocol);
5341         return 1;
5342     }
5343 
5344     /* context id and sequence fields */
5345     if (flags & IPHC_CRTP_FH_CIDLEN_FLAG) {
5346         offset_seq = 3;
5347         offset_cid = ip_hdr_len + 4;
5348         if (flags & IPHC_CRTP_FH_DATA_FLAG) {
5349             proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq, 1,
5350                     ENC_BIG_ENDIAN);
5351         } else {
5352             seq = tvb_get_guint8(tvb, offset_seq);
5353             if (seq != 0) {
5354                 ti = proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq,
5355                         1, ENC_BIG_ENDIAN);
5356                 expert_add_info(pinfo, ti, &ei_iphc_crtp_seq_nonzero);
5357             }
5358         }
5359         proto_tree_add_item(fh_tree, hf_iphc_crtp_cid16, tvb, offset_cid,
5360                             2, ENC_BIG_ENDIAN);
5361     } else {
5362         offset_cid = 3;
5363         offset_seq = ip_hdr_len + 5;
5364         proto_tree_add_item(fh_tree, hf_iphc_crtp_cid8, tvb, offset_cid, 1,
5365                             ENC_BIG_ENDIAN);
5366         if (flags & IPHC_CRTP_FH_DATA_FLAG) {
5367             proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq, 1,
5368                     ENC_BIG_ENDIAN);
5369         } else {
5370             seq = tvb_get_guint8(tvb, offset_seq);
5371             if (seq != 0) {
5372                 ti = proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq,
5373                         1, ENC_BIG_ENDIAN);
5374                 expert_add_info(pinfo, ti, &ei_iphc_crtp_seq_nonzero);
5375             }
5376         }
5377     }
5378 
5379     /* information field */
5380     info_tree = proto_tree_add_subtree(fh_tree, tvb, 0, length, ett_iphc_crtp_info, NULL, "Information Field");
5381 
5382     /* XXX: 1: May trap above; 2: really only need to check for ip_hdr_len+6 ?? */
5383     tvb_ensure_bytes_exist (tvb, 0, hdr_len);  /* ip_hdr_len + 8 */
5384 
5385     /* allocate a copy of the IP packet */
5386     ip_packet = (guchar *)tvb_memdup(pinfo->pool, tvb, 0, length);
5387 
5388     /* restore the proper values to the IP and UDP length fields */
5389     ip_packet[2] = length >> 8;
5390     ip_packet[3] = length;
5391 
5392     ip_packet[ip_hdr_len + 4] = (length - ip_hdr_len) >> 8;
5393     ip_packet[ip_hdr_len + 5] = (length - ip_hdr_len);
5394 
5395     next_tvb = tvb_new_child_real_data(tvb, ip_packet, length, length);
5396     add_new_data_source(pinfo, next_tvb, "Decompressed Data");
5397 
5398     if (!dissector_try_uint(ppp_subdissector_table, PPP_IP, next_tvb, pinfo,
5399         info_tree)) {
5400         call_data_dissector(next_tvb, pinfo, info_tree);
5401     }
5402     return tvb_captured_length(tvb);
5403 }
5404 
5405 /*
5406  * 0x2067 Packets:  Compressed UDP with 16-bit Context Identifier
5407  */
5408 static int
dissect_iphc_crtp_cudp16(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5409 dissect_iphc_crtp_cudp16(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5410 {
5411     proto_tree *cudp_tree;
5412     proto_item *ti;
5413     guint       length;
5414     guint       hdr_length;
5415     int         offset = 0;
5416 
5417     col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
5418     col_set_str(pinfo->cinfo, COL_INFO, "Compressed UDP 16");
5419 
5420     length = tvb_reported_length(tvb);
5421 
5422     ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
5423             "%s",
5424             val_to_str_ext_const(PPP_RTP_CUDP16, &ppp_vals_ext, "Unknown"));
5425     cudp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
5426 
5427     hdr_length = 3;
5428 
5429     proto_tree_add_item(cudp_tree, hf_iphc_crtp_cid16, tvb, 0, 2,
5430             ENC_BIG_ENDIAN);
5431     proto_tree_add_item(cudp_tree, hf_iphc_crtp_seq, tvb, 2, 1,
5432             ENC_BIG_ENDIAN);
5433 
5434     offset += hdr_length;
5435     length -= hdr_length;
5436 
5437     proto_tree_add_item(cudp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
5438 
5439     return tvb_captured_length(tvb);
5440 }
5441 
5442 /*
5443  * 0x67 Packets:  Compressed UDP with 8-bit Context Identifier
5444  */
5445 static int
dissect_iphc_crtp_cudp8(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5446 dissect_iphc_crtp_cudp8(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5447 {
5448     proto_tree *cudp_tree;
5449     proto_item *ti;
5450     guint       length;
5451     guint       hdr_length;
5452     int         offset = 0;
5453 
5454     col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
5455     col_set_str(pinfo->cinfo, COL_INFO, "Compressed UDP 8");
5456 
5457     length = tvb_reported_length(tvb);
5458 
5459     ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
5460             "%s",
5461             val_to_str_ext_const(PPP_RTP_CUDP8, &ppp_vals_ext, "Unknown"));
5462     cudp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
5463 
5464     hdr_length = 2;
5465 
5466     proto_tree_add_item(cudp_tree, hf_iphc_crtp_cid8, tvb, 0, 1,
5467             ENC_BIG_ENDIAN);
5468     proto_tree_add_item(cudp_tree, hf_iphc_crtp_seq, tvb, 1, 1,
5469             ENC_BIG_ENDIAN);
5470 
5471     offset += hdr_length;
5472     length -= hdr_length;
5473 
5474     proto_tree_add_item(cudp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
5475 
5476     return tvb_captured_length(tvb);
5477 }
5478 
5479 
5480 /*
5481  * 0x2065 Packets:  Context State
5482  */
5483 static int
dissect_iphc_crtp_cs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5484 dissect_iphc_crtp_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5485 {
5486     proto_tree *cs_tree;
5487     proto_item *ti     = NULL;
5488     guint8      flags, cnt;
5489     guint       length, cid_size;
5490     guint       offset = 2, hf;
5491 
5492     col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
5493     col_set_str(pinfo->cinfo, COL_INFO, "Context State");
5494 
5495     ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
5496             "%s", val_to_str_ext_const(PPP_RTP_CS, &ppp_vals_ext, "Unknown"));
5497 
5498     cs_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
5499 
5500     proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_flags, tvb, 0, 1,
5501             ENC_BIG_ENDIAN);
5502     proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_cnt, tvb, 1, 1,
5503             ENC_BIG_ENDIAN);
5504 
5505     /* calculate required length */
5506     flags = tvb_get_guint8(tvb, 0);
5507     cnt = tvb_get_guint8(tvb, 1);
5508 
5509     if (flags == IPHC_CRTP_CS_CID8) {
5510         hf = hf_iphc_crtp_cid8;
5511         cid_size = 1;
5512         length = 3 * cnt;
5513     } else {
5514         hf = hf_iphc_crtp_cid16;
5515         cid_size = 2;
5516         length = 4 * cnt;
5517     }
5518 
5519     while (offset < length) {
5520         proto_tree_add_item(cs_tree, hf, tvb, offset, cid_size,
5521                 ENC_BIG_ENDIAN);
5522         offset += cid_size;
5523         proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_invalid, tvb, offset,
5524                 1, ENC_BIG_ENDIAN);
5525         proto_tree_add_item(cs_tree, hf_iphc_crtp_seq, tvb, offset, 1,
5526                 ENC_BIG_ENDIAN);
5527         ++offset;
5528         proto_tree_add_item(cs_tree, hf_iphc_crtp_gen, tvb, offset, 1,
5529                 ENC_BIG_ENDIAN);
5530         ++offset;
5531     }
5532 
5533     return tvb_captured_length(tvb);
5534 }
5535 
5536 /*
5537  * 0x65 Packets:  Compressed Non TCP
5538  */
5539 static int
dissect_iphc_crtp_cntcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5540 dissect_iphc_crtp_cntcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5541 {
5542     proto_tree *cntcp_tree;
5543     proto_item *ti;
5544     guint       length, flags;
5545     guint       hdr_length;
5546     int         offset = 0;
5547 
5548     col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
5549     col_set_str(pinfo->cinfo, COL_INFO, "Compressed Non TCP");
5550 
5551     length = tvb_reported_length(tvb);
5552 
5553     flags = (tvb_get_guint8(tvb, 1) & IPHC_CRTP_FH_FLAG_MASK);
5554 
5555     ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
5556             "%s",
5557             val_to_str_ext_const(PPP_RTP_CNTCP, &ppp_vals_ext, "Unknown"));
5558     cntcp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
5559 
5560     if (flags & IPHC_CRTP_FH_CIDLEN_FLAG) {
5561         /* RFC 2507 6. Compressed Header Formats
5562          * d) Compressed non-TCP header, 16 bit CID:
5563          *      0             7
5564          *     +-+-+-+-+-+-+-+-+
5565          *     |  msb of CID   |
5566          *     +-+-+-+-+-+-+-+-+
5567          *     |1|D| Generation|
5568          *     +-+-+-+-+-+-+-+-+
5569          *     |  lsb of CID   |
5570          *     +-+-+-+-+-+-+-+-+
5571          *     |      data     |                      (if D=1)
5572          *      - - - - - - - -
5573          *     | RANDOM fields, if any (section 7)    (implied)
5574          */
5575         hdr_length = 3;
5576         proto_tree_add_split_bits_item_ret_val(cntcp_tree, hf_iphc_crtp_cid16, tvb, 0,
5577                 iphc_crtp_cntcp_cid16_crumbs, NULL);
5578     } else {
5579         /* c) Compressed non-TCP header, 8 bit CID:
5580          *      0             7
5581          *     +-+-+-+-+-+-+-+-+
5582          *     |      CID      |
5583          *     +-+-+-+-+-+-+-+-+
5584          *     |0|D| Generation|
5585          *     +-+-+-+-+-+-+-+-+
5586          *     |      data     |                      (if D=1)
5587          *      - - - - - - - -
5588          *     | RANDOM fields, if any (section 7)    (implied)
5589          *      - - - - - - - -
5590          */
5591         hdr_length = 2;
5592         proto_tree_add_item(cntcp_tree, hf_iphc_crtp_cid8, tvb, 0, 1,
5593                 ENC_BIG_ENDIAN);
5594     }
5595     proto_tree_add_bitmask_with_flags(cntcp_tree, tvb, 1, hf_iphc_crtp_fh_flags,
5596             ett_iphc_crtp_fh_flags, iphc_crtp_fh_flags_fields, ENC_BIG_ENDIAN,
5597             BMT_NO_FLAGS);
5598     proto_tree_add_item(cntcp_tree, hf_iphc_crtp_gen, tvb, 1, 1,
5599             ENC_BIG_ENDIAN);
5600 
5601     if (flags & IPHC_CRTP_FH_DATA_FLAG) {
5602         proto_tree_add_item(cntcp_tree, hf_iphc_crtp_seq, tvb, hdr_length++,
5603                 1, ENC_BIG_ENDIAN);
5604     }
5605 
5606     offset += hdr_length;
5607     length -= hdr_length;
5608 
5609     /* The IPv4 Identification Field is RANDOM and thus included in a
5610      * compressed Non TCP packet (RFC 2507 6a, 7.13a). Only IPv4 is
5611      * supported in this dissector, so we don't worry about the IPv6
5612      * case, which is different (RFC 2507 7.1)."
5613      */
5614     proto_tree_add_item(cntcp_tree, hf_iphc_crtp_ip_id, tvb, offset,
5615             2, ENC_BIG_ENDIAN);
5616     offset += 2;
5617     length -= 2;
5618 
5619     proto_tree_add_item(cntcp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
5620 
5621     return tvb_captured_length(tvb);
5622 }
5623 
5624 /*
5625  * RFC 3032.
5626  */
5627 static int
dissect_mplscp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5628 dissect_mplscp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5629 {
5630     dissect_cp(tvb, proto_mplscp, ett_mplscp, cp_vals, ett_mplscp_options,
5631         NULL, pinfo, tree);
5632     return tvb_captured_length(tvb);
5633 }
5634 
5635 /*
5636  * Cisco Discovery Protocol Control Protocol.
5637  * XXX - where is this documented?
5638  */
5639 static int
dissect_cdpcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5640 dissect_cdpcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5641 {
5642     dissect_cp(tvb, proto_cdpcp, ett_cdpcp, cp_vals, ett_cdpcp_options, NULL,
5643         pinfo, tree);
5644     return tvb_captured_length(tvb);
5645 }
5646 
5647 /* PPP Multilink Protcol (RFC 1990) and
5648  * the Multiclass Extension to Multi-Link PPP (RFC 2686)
5649  */
5650 static gboolean mp_short_seqno = FALSE; /* Default to long sequence numbers */
5651 static guint mp_max_fragments = 6;
5652 /* Maximum fragments to try to reassemble. This affects performance and
5653  * memory use significantly. */
5654 static guint mp_fragment_aging = 4000; /* Short sequence numbers only 12 bit */
5655 
5656 #define MP_FRAG_MASK           0xFC
5657 #define MP_FRAG_MASK_SHORT     0xF0
5658 #define MP_FRAG_FIRST          0x80
5659 #define MP_FRAG_LAST           0x40
5660 #define MP_FRAG_CLS            0x3C
5661 #define MP_FRAG_RESERVED       0x03
5662 #define MP_FRAG_CLS_SHORT      0x30
5663 
5664 /* According to RFC 1990, the length the MP header isn't indicated anywhere
5665    in the header itself.  It starts out at four bytes and can be
5666    negotiated down to two using LCP.  We currently have a preference
5667    to select short headers.  - gcc & gh
5668 */
5669 
5670 static int
dissect_mp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5671 dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5672 {
5673     proto_tree  *mp_tree;
5674     proto_item  *ti;
5675     gboolean save_fragmented;
5676     guint8      flags;
5677     guint32     cls; /* 32 bit since we shift it left and XOR with seqnum */
5678     guint32     seqnum;
5679     gint        hdrlen;
5680     fragment_head *frag_mp;
5681     tvbuff_t    *next_tvb;
5682     static int * const mp_flags[] = {
5683         &hf_mp_frag_first,
5684         &hf_mp_frag_last,
5685         &hf_mp_sequence_num_cls,
5686         &hf_mp_sequence_num_reserved,
5687         NULL
5688     };
5689     static int * const mp_short_flags[] = {
5690         &hf_mp_frag_first,
5691         &hf_mp_frag_last,
5692         &hf_mp_short_sequence_num_cls,
5693         NULL
5694     };
5695 
5696     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP MP");
5697     col_set_str(pinfo->cinfo, COL_INFO, "PPP Multilink");
5698 
5699     save_fragmented = pinfo->fragmented;
5700     flags = tvb_get_guint8(tvb, 0);
5701 
5702     ti = proto_tree_add_item(tree, proto_mp, tvb, 0,
5703             mp_short_seqno ? 2 : 4, ENC_NA);
5704     mp_tree = proto_item_add_subtree(ti, ett_mp);
5705 
5706     if (mp_short_seqno) {
5707         proto_tree_add_bitmask(mp_tree, tvb, 0, hf_mp_frag_short, ett_mp_flags, mp_short_flags, ENC_NA);
5708         proto_tree_add_item_ret_uint(mp_tree, hf_mp_short_sequence_num, tvb,  0, 2, ENC_BIG_ENDIAN, &seqnum);
5709     } else {
5710         proto_tree_add_bitmask(mp_tree, tvb, 0, hf_mp_frag, ett_mp_flags, mp_flags, ENC_NA);
5711         proto_tree_add_item_ret_uint(mp_tree, hf_mp_sequence_num, tvb,  1, 3, ENC_BIG_ENDIAN, &seqnum);
5712     }
5713 
5714     hdrlen = mp_short_seqno ? 2 : 4;
5715     if (mp_short_seqno) {
5716         cls = (flags & MP_FRAG_CLS_SHORT) >> 4;
5717     } else {
5718         cls = (flags & MP_FRAG_CLS) >> 2;
5719     }
5720     if (tvb_reported_length_remaining(tvb, hdrlen) > 0) {
5721         pinfo->fragmented = TRUE;
5722         frag_mp = NULL;
5723         if (!pinfo->fd->visited) {
5724             frag_mp = fragment_add_seq_single_aging(&mp_reassembly_table,
5725                 tvb, hdrlen, pinfo, seqnum ^ (cls << 24), NULL,
5726                 tvb_captured_length_remaining(tvb, hdrlen),
5727                 flags & MP_FRAG_FIRST, flags & MP_FRAG_LAST,
5728                 mp_max_fragments, mp_fragment_aging);
5729         } else {
5730             frag_mp = fragment_get_reassembled_id(&mp_reassembly_table, pinfo, seqnum ^ (cls << 24));
5731         }
5732         next_tvb = process_reassembled_data(tvb, hdrlen, pinfo,
5733             "Reassembled PPP MP payload", frag_mp, &mp_frag_items,
5734             NULL, mp_tree);
5735 
5736         if (frag_mp) {
5737             if (pinfo->num == frag_mp->reassembled_in) {
5738                 dissect_ppp(next_tvb, pinfo, tree, NULL);
5739             } else {
5740                 col_append_fstr(pinfo->cinfo, COL_INFO,
5741                     " (PPP MP reassembled in packet %u)",
5742                     frag_mp->reassembled_in);
5743                 proto_tree_add_item(mp_tree, hf_mp_payload, tvb, hdrlen, -1, ENC_NA);
5744             }
5745         } else {
5746             col_append_fstr(pinfo->cinfo, COL_INFO,
5747                 " (PPP MP Unreassembled fragment %u)",
5748                 seqnum);
5749             proto_tree_add_item(mp_tree, hf_mp_payload, tvb, hdrlen, -1, ENC_NA);
5750         }
5751     }
5752 
5753     pinfo->fragmented = save_fragmented;
5754     return tvb_captured_length(tvb);
5755 }
5756 
5757 /*
5758  * Handles PPP without HDLC framing, just a protocol field (RFC 1661).
5759  */
5760 static int
dissect_ppp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5761 dissect_ppp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5762 {
5763     proto_item *ti;
5764     proto_tree *fh_tree;
5765 
5766     ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, ENC_NA);
5767     fh_tree = proto_item_add_subtree(ti, ett_ppp);
5768 
5769     dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti, 0);
5770     return tvb_captured_length(tvb);
5771 }
5772 
5773 static void
dissect_ppp_hdlc_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)5774 dissect_ppp_hdlc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5775 {
5776     proto_item *ti;
5777     proto_tree *fh_tree;
5778     guint8      byte0;
5779     int         proto_offset;
5780     tvbuff_t   *next_tvb;
5781 
5782     byte0 = tvb_get_guint8(tvb, 0);
5783 
5784     /* PPP HDLC encapsulation */
5785     if (byte0 == 0xff)
5786         proto_offset = 2;
5787     else {
5788         /* address and control are compressed (NULL) */
5789         proto_offset = 0;
5790     }
5791 
5792     /* load the top pane info. This should be overwritten by
5793        the next protocol in the stack */
5794     ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, ENC_NA);
5795     fh_tree = proto_item_add_subtree(ti, ett_ppp);
5796     if (byte0 == 0xff) {
5797         proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1,
5798                 ENC_BIG_ENDIAN);
5799         proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1,
5800                 ENC_BIG_ENDIAN);
5801     }
5802 
5803     next_tvb = decode_fcs(tvb, pinfo, fh_tree, ppp_fcs_decode, proto_offset);
5804     dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset);
5805 }
5806 
5807 /*
5808  * Handles link-layer encapsulations where the frame might be
5809  * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
5810  */
5811 static int
dissect_ppp_hdlc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5812 dissect_ppp_hdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5813 {
5814     guint8     byte0;
5815 
5816     byte0 = tvb_get_guint8(tvb, 0);
5817     if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
5818         /* Cisco HDLC encapsulation */
5819         return call_dissector(chdlc_handle, tvb, pinfo, tree);
5820     }
5821 
5822     /*
5823      * XXX - should we have an exported dissector that always dissects
5824      * PPP-in-HDLC-like-framing, without checking for Cisco HDLC, for
5825      * use when we know the packets are PPP, not Cisco HDLC?
5826      */
5827     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
5828     switch (pinfo->p2p_dir) {
5829 
5830     case P2P_DIR_SENT:
5831         col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
5832         col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
5833         break;
5834 
5835     case P2P_DIR_RECV:
5836         col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
5837         col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
5838         break;
5839 
5840     default:
5841         col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
5842         col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
5843         break;
5844     }
5845 
5846     dissect_ppp_hdlc_common(tvb, pinfo, tree);
5847     return tvb_captured_length(tvb);
5848 }
5849 
5850 static tvbuff_t*
remove_escape_chars(tvbuff_t * tvb,packet_info * pinfo,int offset,int length)5851 remove_escape_chars(tvbuff_t *tvb, packet_info *pinfo, int offset, int length)
5852 {
5853     guint8    *buff;
5854     int        i;
5855     int        scanned_len = 0;
5856     guint8     octet;
5857     tvbuff_t  *next_tvb;
5858 
5859     buff = (guint8 *)wmem_alloc(pinfo->pool, length);
5860     i = 0;
5861     while (scanned_len < length) {
5862         octet = tvb_get_guint8(tvb, offset);
5863         if (octet == 0x7d) {
5864             offset++;
5865             scanned_len++;
5866             if (scanned_len >= length)
5867                 break;
5868             octet = tvb_get_guint8(tvb, offset);
5869             buff[i] = octet ^ 0x20;
5870         } else {
5871             buff[i] = octet;
5872         }
5873         offset++;
5874         scanned_len++;
5875         i++;
5876     }
5877     if (i == 0) {
5878         return NULL;
5879     }
5880     next_tvb = tvb_new_child_real_data(tvb, buff, i, i);
5881 
5882     return next_tvb;
5883 }
5884 
5885 /*
5886  * Handles link-layer encapsulations where we have a raw RFC 1662
5887  * HDLC-like asynchronous framing byte stream, and have to
5888  * break the byte stream into frames and remove escapes.
5889  */
5890 static int
dissect_ppp_raw_hdlc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5891 dissect_ppp_raw_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ )
5892 {
5893     proto_item *ti;
5894     proto_tree *bs_tree;
5895     gint        offset, end_offset, data_offset;
5896     int         length, data_length;
5897     tvbuff_t   *ppp_tvb;
5898     gboolean    first   = TRUE;
5899 
5900     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
5901 
5902     ti = proto_tree_add_item(tree, proto_ppp_hdlc, tvb, 0, -1, ENC_NA);
5903     bs_tree = proto_item_add_subtree(ti, ett_ppp_hdlc_data);
5904 
5905     /*
5906      * XXX - this needs to handle a PPP frame split over multiple higher-level
5907      * packets.
5908      */
5909 
5910     /*
5911      * Look for a frame delimiter.
5912      */
5913     offset = tvb_find_guint8(tvb, 0, -1, 0x7e);
5914     if (offset == -1) {
5915         /*
5916          * None found - this is presumably continued from an earlier
5917          * packet and continued in a later packet.
5918          */
5919         col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
5920         proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, offset, -1, ENC_NA);
5921         offset++;
5922         length = tvb_captured_length_remaining(tvb,offset);
5923         ppp_tvb = remove_escape_chars(tvb, pinfo, offset,length);
5924         if (ppp_tvb != NULL) {
5925             add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
5926             call_data_dissector(ppp_tvb, pinfo, tree);
5927         }
5928         return tvb_captured_length(tvb);
5929     }
5930     if (offset != 0) {
5931         /*
5932          * We have some data preceding the first PPP packet;
5933          * mark it as a PPP fragment.
5934          */
5935         col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
5936         length = offset;
5937         proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, 0, length, ENC_NA);
5938         if (length != 0) {
5939             ppp_tvb = remove_escape_chars(tvb, pinfo, 0, length - 1);
5940             if (ppp_tvb != NULL) {
5941                 add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
5942                 call_data_dissector(ppp_tvb, pinfo, tree);
5943             }
5944         }
5945     }
5946     while (tvb_reported_length_remaining(tvb, offset) > 0) {
5947         /*
5948          * Look for the next frame delimiter.
5949          */
5950         end_offset = tvb_find_guint8(tvb, offset + 1, -1, 0x7e);
5951         if (end_offset == -1) {
5952             /*
5953              * We didn't find one.  This is probably continued in a later
5954              * packet.
5955              */
5956             if (first)
5957                 col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
5958             proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, offset, -1, ENC_NA);
5959             offset++;
5960             length = tvb_captured_length_remaining(tvb, offset);
5961             ppp_tvb = remove_escape_chars(tvb, pinfo, offset, length);
5962             if (ppp_tvb != NULL) {
5963                 add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
5964                 call_data_dissector(ppp_tvb, pinfo, tree);
5965             }
5966             return tvb_captured_length(tvb);
5967         }
5968 
5969         data_offset = offset + 1;     /* skip starting frame delimiter */
5970         data_length = end_offset - data_offset;
5971 
5972         /*
5973          * Is that frame delimiter immediately followed by another one?
5974          * Some PPP implementations put a frame delimiter at the
5975          * beginning and the end of each frame, although RFC 1662
5976          * appears only to require that there be one frame delimiter
5977          * between adjacent frames:
5978          *
5979          *  Each frame begins and ends with a Flag Sequence, which is the
5980          *  binary sequence 01111110 (hexadecimal 0x7e).  All implementations
5981          *  continuously check for this flag, which is used for frame
5982          *  synchronization.
5983          *
5984          *  Only one Flag Sequence is required between two frames.  Two
5985          *  consecutive Flag Sequences constitute an empty frame, which is
5986          *  silently discarded, and not counted as a FCS error.
5987          *
5988          * If the delimiter at the end of this frame is followed by
5989          * another delimiter, we consider the first delimiter part
5990          * of this frame.
5991          */
5992         if (tvb_offset_exists(tvb, end_offset + 1) &&
5993             tvb_get_guint8(tvb, end_offset+1) == 0x7e) {
5994             end_offset++;
5995         }
5996         length = end_offset - offset;
5997         proto_tree_add_item(bs_tree, hf_ppp_hdlc_data, tvb, offset, length, ENC_NA);
5998         if (length > 1) {
5999             ppp_tvb = remove_escape_chars(tvb, pinfo, data_offset, data_length);
6000             if (ppp_tvb != NULL) {
6001                 add_new_data_source(pinfo, ppp_tvb, "PPP Message");
6002                 dissect_ppp_hdlc_common(ppp_tvb, pinfo, tree);
6003                 first = FALSE;
6004             }
6005         }
6006         offset = end_offset;
6007     }
6008     return tvb_captured_length(tvb);
6009 }
6010 
6011 /*
6012  * At least for the PPP/USB captures I've seen, the data either starts with
6013  * 0x7eff03 or 0x7eff7d23 or 0xff03, so this function performs that heuristic
6014  * matching first before calling dissect_ppp_raw_hdlc().  Otherwise, if we call
6015  * it directly for USB captures, some captures like the following will not be
6016  * dissected correctly:
6017  * https://gitlab.com/wireshark/wireshark/-/wikis/SampleCaptures#head-886e340c31ca977f321c921f81cbec4c21bb7738
6018  */
6019 static gboolean
dissect_ppp_usb(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6020 dissect_ppp_usb( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
6021 {
6022     /*
6023      * In some cases, the 0x03 normally in byte 3 is escaped so we must look
6024      * for the 2 byte sequence of 0x7d23 instead of 0x03.  The 0x23 is
6025      * generated by 0x20^0x03 per section 4.2 of:
6026      * https://tools.ietf.org/html/rfc1662.html.
6027      */
6028     const guchar buf1[3] = {0x7e, 0xff, 0x03};
6029     const guchar buf2[4] = {0x7e, 0xff, 0x7d, 0x23};
6030     tvbuff_t *next_tvb;
6031 
6032     if ((tvb_memeql(tvb, 0, buf2, sizeof(buf2)) == 0) ||
6033         (tvb_memeql(tvb, 0, buf1, sizeof(buf1)) == 0)) {
6034         dissect_ppp_raw_hdlc(tvb, pinfo, tree, data);
6035     } else if ((tvb_memeql(tvb, 0, &buf1[1], sizeof(buf1) - 1) == 0) ||
6036         (tvb_memeql(tvb, 0, &buf2[1], sizeof(buf2) - 1) == 0)) {
6037         /* It's missing the 0x7e framing character.  What TODO?
6038          * Should we try faking it by sticking 0x7e in front?  Or try telling
6039          * dissect_ppp_raw_hdlc() NOT to look for the 0x7e frame deliminator?
6040          * Or is this a bug in libpcap (used 1.1.0)?
6041          * Or a bug in the Linux kernel (tested with 2.6.24.4)  Or a bug in
6042          * usbmon?  Or is the data we're looking at really just part of the
6043          * payload and not control data?  Well, at least in my case it's
6044          * definitely not, but not sure if this is always the case. Is this
6045          * issue applicable only to PPP/USB or PPP/XYZ, in which case a more
6046          * general solution should be found?
6047          */
6048         /* For now, just try skipping the framing I guess??? */
6049         if (tvb_get_guint8(tvb, 1) == 0x03)
6050             next_tvb = tvb_new_subset_remaining(tvb, 2);
6051         else
6052             next_tvb = tvb_new_subset_remaining(tvb, 3);
6053         dissect_ppp(next_tvb, pinfo, tree, data);
6054     } else if (tvb_get_guint8(tvb, 0) == 0x7e) {
6055         /* Well, let's guess that since the 1st byte is 0x7e that it really is
6056          * a PPP frame, and the address and control bytes are compressed (NULL)
6057          * per https://tools.ietf.org/html/rfc1662, section 3.2, which means
6058          * that they're omitted from the packet. */
6059         next_tvb = tvb_new_subset_remaining(tvb, 1);
6060         dissect_ppp_hdlc_common(next_tvb, pinfo, tree);
6061     } else
6062         return (FALSE);
6063     return (TRUE);
6064 }
6065 
6066 void
proto_register_ppp_raw_hdlc(void)6067 proto_register_ppp_raw_hdlc(void)
6068 {
6069     static hf_register_info hf[] = {
6070       /* Generated from convert_proto_tree_add_text.pl */
6071       { &hf_ppp_hdlc_fragment, { "PPP Fragment", "ppp_hdlc.fragment", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6072       { &hf_ppp_hdlc_data, { "PPP Data", "ppp_hdlc.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6073     };
6074 
6075     static gint *ett[] = {
6076         &ett_ppp_hdlc_data
6077     };
6078 
6079     proto_ppp_hdlc = proto_register_protocol("PPP In HDLC-Like Framing",
6080         "PPP-HDLC", "ppp_hdlc");
6081     proto_register_subtree_array(ett, array_length(ett));
6082     proto_register_field_array(proto_ppp_hdlc, hf, array_length(hf));
6083 
6084     register_capture_dissector_table("ppp_hdlc", "PPP-HDLC");
6085     register_capture_dissector("ppp_hdlc", capture_ppp_hdlc, proto_ppp_hdlc);
6086 }
6087 
6088 void
proto_reg_handoff_ppp_raw_hdlc(void)6089 proto_reg_handoff_ppp_raw_hdlc(void)
6090 {
6091     dissector_handle_t ppp_raw_hdlc_handle;
6092     capture_dissector_handle_t ppp_hdlc_cap_handle;
6093 
6094     ppp_raw_hdlc_handle = create_dissector_handle(dissect_ppp_raw_hdlc, proto_ppp);
6095 
6096     dissector_add_uint("gre.proto", ETHERTYPE_CDMA2000_A10_UBS, ppp_raw_hdlc_handle);
6097     dissector_add_uint("gre.proto", ETHERTYPE_3GPP2, ppp_raw_hdlc_handle);
6098 
6099     /*
6100      * The heuristic checks are rather weak. Each payload starting with
6101      * 0x7e is accepted as a PPP over USB frame, this creates a lot of
6102      * false positives. We disable the heuristic subdissector by
6103      * default.
6104      */
6105     heur_dissector_add("usb.bulk", dissect_ppp_usb,
6106             "PPP USB bulk endpoint", "ppp_usb_bulk", proto_ppp, HEURISTIC_DISABLE);
6107 
6108     ppp_hdlc_cap_handle = find_capture_dissector("ppp_hdlc");
6109     capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_cap_handle);
6110     capture_dissector_add_uint("sll.ltype", LINUX_SLL_P_PPPHDLC, ppp_hdlc_cap_handle);
6111     capture_dissector_add_uint("fr.nlpid", NLPID_PPP, ppp_hdlc_cap_handle);
6112 
6113     chdlc_cap_handle = find_capture_dissector("chdlc");
6114 }
6115 
6116 /*
6117  * Handles PAP just as a protocol field
6118  */
6119 static int
dissect_pap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6120 dissect_pap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6121 {
6122     proto_item *ti, *data_ti;
6123     proto_tree *fh_tree, *data_tree = NULL;
6124     guint8      code;
6125     gchar      *peer_id, *password, *message;
6126     guint8      peer_id_length, password_length, message_length;
6127     int         offset              = 0;
6128 
6129     code = tvb_get_guint8(tvb, 0);
6130 
6131     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP PAP");
6132     col_set_str(pinfo->cinfo, COL_INFO,
6133                 val_to_str_const(code, pap_vals, "Unknown"));
6134 
6135     ti = proto_tree_add_item(tree, proto_pap, tvb, 0, -1, ENC_NA);
6136     fh_tree = proto_item_add_subtree(ti, ett_pap);
6137 
6138     proto_tree_add_item(fh_tree, hf_pap_code, tvb, offset, 1,
6139                         ENC_BIG_ENDIAN);
6140     offset++;
6141 
6142     proto_tree_add_item(fh_tree, hf_pap_identifier, tvb, offset, 1,
6143                         ENC_BIG_ENDIAN);
6144     offset++;
6145 
6146     proto_tree_add_item(fh_tree, hf_pap_length, tvb, offset, 2,
6147                         ENC_BIG_ENDIAN);
6148     offset += 2;
6149 
6150     data_ti = proto_tree_add_item(fh_tree, hf_pap_data, tvb, offset, -1,
6151                                   ENC_NA);
6152     data_tree = proto_item_add_subtree(data_ti, ett_pap_data);
6153 
6154     switch (code) {
6155     case CONFREQ:
6156         proto_tree_add_item(data_tree, hf_pap_peer_id_length, tvb, offset,
6157                             1, ENC_BIG_ENDIAN);
6158         peer_id_length = tvb_get_guint8(tvb, offset);
6159         offset++;
6160 
6161         proto_tree_add_item(data_tree, hf_pap_peer_id, tvb, offset,
6162                             peer_id_length, ENC_ASCII|ENC_NA);
6163         peer_id = tvb_format_text(pinfo->pool, tvb, offset, peer_id_length);
6164         offset += peer_id_length;
6165 
6166         proto_tree_add_item(data_tree, hf_pap_password_length, tvb, offset,
6167                             1, ENC_BIG_ENDIAN);
6168         password_length = tvb_get_guint8(tvb, offset);
6169         offset++;
6170 
6171         proto_tree_add_item(data_tree, hf_pap_password, tvb, offset,
6172                             password_length, ENC_ASCII|ENC_NA);
6173         password = tvb_format_text(pinfo->pool, tvb, offset, password_length);
6174 
6175         col_append_fstr(pinfo->cinfo, COL_INFO,
6176                         " (Peer-ID='%s', Password='%s')", peer_id, password);
6177         break;
6178 
6179     case CONFACK:
6180     case CONFNAK:
6181         proto_tree_add_item(data_tree, hf_pap_message_length, tvb, offset,
6182                             1, ENC_BIG_ENDIAN);
6183         message_length = tvb_get_guint8(tvb, offset);
6184         offset +=1;
6185 
6186         proto_tree_add_item(data_tree, hf_pap_message, tvb, offset,
6187                             message_length, ENC_ASCII|ENC_NA);
6188         message = tvb_format_text(pinfo->pool, tvb, offset, message_length);
6189 
6190         col_append_fstr(pinfo->cinfo, COL_INFO, " (Message='%s')",
6191                         message);
6192         break;
6193 
6194     default:
6195         proto_tree_add_item(data_tree, hf_pap_stuff, tvb, offset, -1,
6196                             ENC_NA);
6197         break;
6198     }
6199     return tvb_captured_length(tvb);
6200 }
6201 
6202 /*
6203  * RFC 1994
6204  * Handles CHAP just as a protocol field
6205  */
6206 static int
dissect_chap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6207 dissect_chap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6208 {
6209     proto_item *ti;
6210     proto_tree *fh_tree;
6211     proto_item *tf;
6212     proto_tree *field_tree;
6213     guint8      code, value_size;
6214     guint32     length;
6215     int         offset;
6216 
6217     code = tvb_get_guint8(tvb, 0);
6218     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP CHAP");
6219     col_set_str(pinfo->cinfo, COL_INFO,
6220         val_to_str_const(code, chap_vals, "Unknown"));
6221 
6222 
6223     /* Create CHAP protocol tree */
6224     ti = proto_tree_add_item(tree, proto_chap, tvb, 0, -1, ENC_NA);
6225     fh_tree = proto_item_add_subtree(ti, ett_chap);
6226 
6227     proto_tree_add_item(fh_tree, hf_chap_code, tvb, 0, 1, ENC_BIG_ENDIAN);
6228     proto_tree_add_item(fh_tree, hf_chap_identifier, tvb, 1, 1,
6229             ENC_BIG_ENDIAN);
6230 
6231     /* Length - make sure it's valid */
6232     length = tvb_get_ntohs(tvb, 2);
6233     if (length < 4) {
6234         proto_tree_add_uint_format_value(fh_tree, hf_chap_length, tvb, 2, 2,
6235                 length, "%u (invalid, must be >= 4)", length);
6236         return 4;
6237     }
6238     proto_item_set_len(ti, length);
6239     proto_tree_add_item(fh_tree, hf_chap_length, tvb, 2, 2,
6240             ENC_BIG_ENDIAN);
6241 
6242     offset = 4;     /* Offset moved to after length field */
6243     length -= 4;    /* Length includes previous 4 bytes, subtract */
6244 
6245     switch (code) {
6246     /* Challenge or Response data */
6247     case CHAP_CHAL:
6248     case CHAP_RESP:
6249         if (length > 0) {
6250             guint value_offset = 0;
6251             guint name_offset  = 0, name_size = 0;
6252 
6253             /* Create data subtree */
6254             tf = proto_tree_add_item(fh_tree, hf_chap_data, tvb, offset,
6255                                      length, ENC_NA);
6256             field_tree = proto_item_add_subtree(tf, ett_chap_data);
6257             length--;
6258 
6259             /* Value size */
6260             value_size = tvb_get_guint8(tvb, offset);
6261             if (value_size > length) {
6262                 proto_tree_add_uint_format_value(field_tree, hf_chap_value_size, tvb, offset, 1,
6263                                     value_size, "%d byte%s (invalid, must be <= %u)",
6264                                     value_size, plurality(value_size, "", "s"), length);
6265                 return offset;
6266             }
6267             proto_tree_add_item(field_tree, hf_chap_value_size, tvb,
6268                                 offset, 1, ENC_BIG_ENDIAN);
6269             offset++;
6270 
6271             /* Value */
6272             if (length > 0) {
6273                 value_offset = offset;
6274                 proto_tree_add_item(field_tree, hf_chap_value, tvb, offset,
6275                                     value_size, ENC_NA);
6276 
6277                 /* Move along value_size bytes */
6278                 offset += value_size;
6279                 length -= value_size;
6280 
6281                 /* Find name in remaining bytes */
6282                 if (length > 0) {
6283                     proto_tree_add_item(field_tree, hf_chap_name, tvb,
6284                                         offset, length, ENC_ASCII|ENC_NA);
6285                     name_offset = offset;
6286                     name_size = length;
6287                 }
6288 
6289                 /* Show name and value in info column */
6290                 col_append_fstr(pinfo->cinfo, COL_INFO,
6291                                 " (NAME='%s%s', VALUE=0x%s)",
6292                                 tvb_format_text(pinfo->pool, tvb, name_offset,
6293                                                 (name_size > 20) ? 20 : name_size),
6294                                 (name_size > 20) ? "..." : "",
6295                                 tvb_bytes_to_str(pinfo->pool, tvb, value_offset, value_size));
6296             }
6297         }
6298         break;
6299 
6300     /* Success or Failure data */
6301     case CHAP_SUCC:
6302     case CHAP_FAIL:
6303         if (length > 0) {
6304             proto_tree_add_item(fh_tree, hf_chap_message, tvb, offset,
6305                     length, ENC_ASCII|ENC_NA);
6306         }
6307 
6308         /* Show message in info column */
6309         col_append_fstr(pinfo->cinfo, COL_INFO, " (MESSAGE='%s')",
6310             tvb_format_text(pinfo->pool, tvb, offset, length));
6311         break;
6312 
6313     /* Code from unknown code type... */
6314     default:
6315         if (length > 0)
6316             proto_tree_add_item(fh_tree, hf_chap_stuff, tvb, offset, length, ENC_NA);
6317         break;
6318     }
6319     return tvb_captured_length(tvb);
6320 }
6321 
6322 /*
6323  * RFC 2472.
6324  */
6325 static int
dissect_ipv6cp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6326 dissect_ipv6cp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6327 {
6328     dissect_cp(tvb, proto_ipv6cp, ett_ipv6cp, cp_vals, ett_ipv6cp_options, ipv6cp_option_table, pinfo, tree);
6329     return tvb_captured_length(tvb);
6330 }
6331 
6332 static void
dissect_ipv6cp_opt_type_len(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)6333 dissect_ipv6cp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
6334     const char *name)
6335 {
6336     guint8 type;
6337 
6338     type = tvb_get_guint8(tvb, offset);
6339     proto_tree_add_uint_format_value(tree, hf_ipv6cp_opt_type, tvb, offset, 1,
6340         type, "%s (%u)", name, type);
6341     proto_tree_add_item(tree, hf_ipv6cp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
6342 }
6343 
6344 static gboolean
dissect_ipv6cp_fixed_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int proto,int ett,int expected_length,proto_tree ** ret_tree,proto_item ** ret_item)6345 dissect_ipv6cp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6346                              int proto, int ett, int expected_length,
6347                              proto_tree** ret_tree, proto_item** ret_item)
6348 {
6349     if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
6350         return FALSE;
6351 
6352     *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
6353     *ret_tree = proto_item_add_subtree(*ret_item, ett);
6354 
6355     dissect_ipv6cp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
6356     return TRUE;
6357 }
6358 
6359 static int
dissect_ipv6cp_if_id_opt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6360 dissect_ipv6cp_if_id_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6361 {
6362     proto_tree* field_tree;
6363     proto_item* tf;
6364     int offset = 0;
6365 
6366     if (!dissect_ipv6cp_fixed_opt(tvb, pinfo, tree, proto_ipv6cp_option_if_id, ett_ipv6cp_if_id_opt, 10,
6367                                   &field_tree, &tf))
6368         return tvb_captured_length(tvb);
6369 
6370     proto_tree_add_item(field_tree, hf_ipv6cp_interface_identifier, tvb, offset+2, 8, ENC_NA);
6371     return tvb_captured_length(tvb);
6372 }
6373 
6374 void
proto_register_ppp(void)6375 proto_register_ppp(void)
6376 {
6377     static hf_register_info hf[] = {
6378         { &hf_ppp_direction,
6379             { "Direction", "ppp.direction", FT_UINT8, BASE_DEC,
6380                 VALS(ppp_direction_vals), 0x0, "PPP direction", HFILL }},
6381         { &hf_ppp_address,
6382             { "Address", "ppp.address", FT_UINT8, BASE_HEX,
6383                 NULL, 0x0, NULL, HFILL }},
6384         { &hf_ppp_control,
6385             { "Control", "ppp.control", FT_UINT8, BASE_HEX,
6386                 NULL, 0x0, NULL, HFILL }},
6387         { &hf_ppp_protocol,
6388             { "Protocol", "ppp.protocol", FT_UINT16, BASE_HEX|BASE_EXT_STRING,
6389                 &ppp_vals_ext, 0x0, NULL, HFILL }},
6390         { &hf_ppp_code,
6391             { "Code", "ppp.code", FT_UINT8, BASE_DEC,
6392                 NULL, 0x0, NULL, HFILL }},
6393         { &hf_ppp_identifier,
6394             { "Identifier", "ppp.identifier", FT_UINT8, BASE_DEC_HEX,
6395                 NULL, 0x0, NULL, HFILL }},
6396         { &hf_ppp_length,
6397             { "Length", "ppp.length", FT_UINT16, BASE_DEC,
6398                 NULL, 0x0, NULL, HFILL }},
6399         { &hf_ppp_magic_number,
6400             { "Magic Number", "ppp.magic_number", FT_UINT32, BASE_HEX,
6401                 NULL, 0x0, NULL, HFILL }},
6402         { &hf_ppp_oui,
6403             { "OUI", "ppp.oui", FT_UINT24, BASE_OUI,
6404                 NULL, 0x0, NULL, HFILL }},
6405         { &hf_ppp_kind,
6406             { "Kind", "ppp.kind", FT_UINT8, BASE_DEC_HEX,
6407                 NULL, 0x0, NULL, HFILL }},
6408         { &hf_ppp_data,
6409             { "Data", "ppp.data", FT_BYTES, BASE_NONE,
6410                 NULL, 0x0, NULL, HFILL }},
6411         { &hf_ppp_fcs_16,
6412             { "FCS 16", "ppp.fcs_16", FT_UINT16, BASE_HEX,
6413                 NULL, 0x0, NULL, HFILL }},
6414         { &hf_ppp_fcs_32,
6415             { "FCS 32", "ppp.fcs_32", FT_UINT32, BASE_HEX,
6416                 NULL, 0x0, NULL, HFILL }},
6417         { &hf_ppp_fcs_status,
6418             { "FCS Status", "ppp.fcs.status", FT_UINT8, BASE_NONE,
6419                 VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
6420     };
6421     static gint *ett[] = {
6422         &ett_ppp,
6423         &ett_ppp_opt_type,
6424         &ett_ppp_unknown_opt
6425     };
6426     static ei_register_info ei[] = {
6427         { &ei_ppp_opt_len_invalid, { "ppp.opt.len.invalid", PI_PROTOCOL, PI_WARN, "Invalid length for option", EXPFILL }},
6428         { &ei_ppp_fcs, { "ppp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
6429     };
6430 
6431     module_t *ppp_module;
6432     expert_module_t* expert_ppp;
6433 
6434     proto_ppp = proto_register_protocol("Point-to-Point Protocol", "PPP", "ppp");
6435     proto_register_field_array(proto_ppp, hf, array_length(hf));
6436     proto_register_subtree_array(ett, array_length(ett));
6437     expert_ppp = expert_register_protocol(proto_ppp);
6438     expert_register_field_array(expert_ppp, ei, array_length(ei));
6439 
6440     /* subdissector code */
6441     ppp_subdissector_table = register_dissector_table("ppp.protocol",
6442         "PPP protocol", proto_ppp, FT_UINT16, BASE_HEX);
6443 
6444     ppp_hdlc_handle = register_dissector("ppp_hdlc", dissect_ppp_hdlc, proto_ppp);
6445     register_dissector("ppp_lcp_options", dissect_lcp_options, proto_ppp);
6446     ppp_handle = register_dissector("ppp", dissect_ppp, proto_ppp);
6447 
6448     /* Register the preferences for the ppp protocol */
6449     ppp_module = prefs_register_protocol(proto_ppp, NULL);
6450 
6451     prefs_register_enum_preference(ppp_module, "fcs_type",
6452         "PPP Frame Checksum Type",
6453         "The type of PPP frame checksum (none, 16-bit, 32-bit)",
6454         &ppp_fcs_decode, fcs_options, FALSE);
6455     prefs_register_obsolete_preference(ppp_module, "decompress_vj");
6456     prefs_register_uint_preference(ppp_module, "default_proto_id",
6457         "PPPMuxCP Default PID (in hex)",
6458         "Default Protocol ID to be used for PPPMuxCP",
6459         16, &pppmux_def_prot_id);
6460 }
6461 
6462 void
proto_reg_handoff_ppp(void)6463 proto_reg_handoff_ppp(void)
6464 {
6465     /*
6466      * Get a handle for the CHDLC dissector.
6467      */
6468     chdlc_handle = find_dissector_add_dependency("chdlc", proto_ppp);
6469 
6470     dissector_add_uint("fr.nlpid", NLPID_PPP, ppp_handle);
6471 
6472     dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_handle);
6473     dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP_WITH_PHDR,
6474         ppp_hdlc_handle);
6475     dissector_add_uint("sll.ltype", LINUX_SLL_P_PPPHDLC, ppp_hdlc_handle);
6476     dissector_add_uint("osinl.excl", NLPID_PPP, ppp_handle);
6477     dissector_add_uint("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle);
6478     dissector_add_uint("juniper.proto", JUNIPER_PROTO_PPP, ppp_handle);
6479     dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_PPP, ppp_hdlc_handle);
6480     dissector_add_uint("l2tp.pw_type", L2TPv3_PROTOCOL_PPP, ppp_hdlc_handle);
6481 }
6482 
6483 void
proto_register_mp(void)6484 proto_register_mp(void)
6485 {
6486     static hf_register_info hf[] = {
6487         { &hf_mp_frag,
6488             { "Fragment", "mp.frag", FT_UINT8, BASE_HEX,
6489                 NULL, MP_FRAG_MASK, NULL, HFILL }},
6490         { &hf_mp_frag_short,
6491             { "Fragment", "mp.frag", FT_UINT8, BASE_HEX,
6492                 NULL, MP_FRAG_MASK_SHORT, NULL, HFILL }},
6493         { &hf_mp_frag_first,
6494             { "First fragment", "mp.first", FT_BOOLEAN, 8,
6495                 TFS(&tfs_yes_no), MP_FRAG_FIRST, NULL, HFILL }},
6496         { &hf_mp_frag_last,
6497             { "Last fragment", "mp.last", FT_BOOLEAN, 8,
6498                 TFS(&tfs_yes_no), MP_FRAG_LAST, NULL, HFILL }},
6499         { &hf_mp_sequence_num,
6500             { "Sequence number", "mp.seq", FT_UINT24, BASE_DEC,
6501                 NULL, 0x0, NULL, HFILL }},
6502         { &hf_mp_sequence_num_cls,
6503             { "Class", "mp.sequence_num_cls", FT_UINT8, BASE_DEC,
6504                 NULL, MP_FRAG_CLS, NULL, HFILL }},
6505         { &hf_mp_sequence_num_reserved,
6506             { "Reserved", "mp.sequence_num_reserved", FT_BOOLEAN, 8,
6507                 NULL, MP_FRAG_RESERVED, NULL, HFILL }},
6508         { &hf_mp_short_sequence_num,
6509             { "Short Sequence number", "mp.sseq", FT_UINT16, BASE_DEC,
6510                 NULL, 0x0FFF, NULL, HFILL }},
6511         { &hf_mp_short_sequence_num_cls,
6512             { "Class", "mp.short_sequence_num_cls", FT_UINT8, BASE_DEC,
6513                 NULL, MP_FRAG_CLS_SHORT, NULL, HFILL }},
6514         { &hf_mp_payload,
6515             {"Payload", "mp.payload", FT_BYTES, BASE_NONE,
6516                 NULL, 0x00, NULL, HFILL }},
6517         { &hf_mp_fragments,
6518             {"Message fragments", "mp.fragments", FT_NONE, BASE_NONE,
6519                 NULL, 0x00, NULL, HFILL }},
6520         { &hf_mp_fragment,
6521           {"Message fragment", "mp.fragment", FT_FRAMENUM, BASE_NONE,
6522                 NULL, 0x00, NULL, HFILL }},
6523         { &hf_mp_fragment_overlap,
6524           {"Message fragment overlap", "mp.fragment.overlap",
6525                 FT_BOOLEAN, BASE_NONE,
6526                 NULL, 0x00, NULL, HFILL }},
6527         { &hf_mp_fragment_overlap_conflicts,
6528           {"Message fragment overlapping with conflicting data", "mp.fragment.overlap.conflicts",
6529                 FT_BOOLEAN, BASE_NONE,
6530                 NULL, 0x00, NULL, HFILL }},
6531         { &hf_mp_fragment_multiple_tails,
6532           {"Message has multiple tail fragments", "mp.fragment.multiple_tails",
6533                 FT_BOOLEAN, BASE_NONE,
6534                 NULL, 0x00, NULL, HFILL }},
6535         { &hf_mp_fragment_too_long_fragment,
6536           {"Message fragment too long", "mp.fragment.too_long_fragment",
6537                 FT_BOOLEAN, BASE_NONE,
6538                 NULL, 0x00, NULL, HFILL }},
6539         { &hf_mp_fragment_error,
6540           {"Message defragmentation error", "mp.fragment.error",
6541                 FT_FRAMENUM, BASE_NONE,
6542                 NULL, 0x00, NULL, HFILL }},
6543         { &hf_mp_fragment_count,
6544           {"Message fragment count", "mp.fragment.count", FT_UINT32, BASE_DEC,
6545                 NULL, 0x00, NULL, HFILL }},
6546         { &hf_mp_reassembled_in,
6547           {"Reassembled in", "mp.reassembled.in", FT_FRAMENUM, BASE_NONE,
6548                 NULL, 0x00, NULL, HFILL }},
6549         { &hf_mp_reassembled_length,
6550           {"Reassembled length", "mp.reassembled.length", FT_UINT32, BASE_DEC,
6551                 NULL, 0x00, NULL, HFILL }}
6552     };
6553     static gint *ett[] = {
6554         &ett_mp,
6555         &ett_mp_flags,
6556         &ett_mp_fragment,
6557         &ett_mp_fragments
6558     };
6559 
6560     module_t *mp_module;
6561 
6562     proto_mp = proto_register_protocol("PPP Multilink Protocol", "PPP MP", "mp");
6563     proto_register_field_array(proto_mp, hf, array_length(hf));
6564     proto_register_subtree_array(ett, array_length(ett));
6565     reassembly_table_register(&mp_reassembly_table,
6566                           &addresses_reassembly_table_functions);
6567 
6568     /* Register the preferences for the PPP multilink protocol */
6569     mp_module = prefs_register_protocol(proto_mp, NULL);
6570 
6571     prefs_register_bool_preference(mp_module, "short_seqno",
6572         "Short sequence numbers",
6573         "Whether PPP Multilink frames use 12-bit sequence numbers",
6574         &mp_short_seqno);
6575     prefs_register_uint_preference(mp_module, "max_fragments",
6576         "Maximum fragments",
6577         "Maximum number of PPP Multilink fragments to try to reassemble into one frame",
6578         10, &mp_max_fragments);
6579     prefs_register_uint_preference(mp_module, "fragment_aging",
6580         "Max unreassembled fragment age",
6581         "Age off unreassembled fragments after this many packets",
6582         10, &mp_fragment_aging);
6583 }
6584 
6585 void
proto_reg_handoff_mp(void)6586 proto_reg_handoff_mp(void)
6587 {
6588     dissector_handle_t mp_handle;
6589 
6590     mp_handle = create_dissector_handle(dissect_mp, proto_mp);
6591     dissector_add_uint("ppp.protocol", PPP_MP, mp_handle);
6592 }
6593 
6594 void
proto_register_lcp(void)6595 proto_register_lcp(void)
6596 {
6597     static hf_register_info hf[] = {
6598         { &hf_lcp_magic_number,
6599             { "Magic Number", "lcp.magic_number", FT_UINT32, BASE_HEX,
6600                 NULL, 0x0, NULL, HFILL }},
6601         { &hf_lcp_data,
6602             { "Data", "lcp.data", FT_BYTES, BASE_NONE,
6603                 NULL, 0x0, NULL, HFILL }},
6604         { &hf_lcp_message,
6605             { "Message", "lcp.message", FT_STRING, BASE_NONE,
6606                 NULL, 0x0, NULL, HFILL }},
6607         { &hf_lcp_secs_remaining,
6608             { "Seconds Remaining", "lcp.secs_remaining", FT_UINT32, BASE_DEC,
6609                 NULL, 0x0, NULL, HFILL }},
6610         { &hf_lcp_rej_proto,
6611             { "Rejected Protocol", "lcp.rej_proto", FT_UINT16,
6612                 BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
6613         { &hf_lcp_opt_type,
6614             { "Type", "lcp.opt.type", FT_UINT8, BASE_DEC,
6615                 NULL, 0x0, NULL, HFILL }},
6616         { &hf_lcp_opt_length,
6617             { "Length", "lcp.opt.length", FT_UINT8, BASE_DEC,
6618                 NULL, 0x0, NULL, HFILL }},
6619         { &hf_lcp_opt_oui,
6620             { "OUI", "lcp.opt.oui", FT_UINT24, BASE_OUI,
6621                 NULL, 0x0, NULL, HFILL }},
6622         { &hf_lcp_opt_kind,
6623             { "Kind", "lcp.opt.kind", FT_UINT8, BASE_DEC_HEX,
6624                 NULL, 0x0, NULL, HFILL }},
6625         { &hf_lcp_opt_data,
6626             { "Data", "lcp.opt.data", FT_BYTES, BASE_NONE,
6627                 NULL, 0x0, NULL, HFILL }},
6628         { &hf_lcp_opt_mru,
6629             { "Maximum Receive Unit", "lcp.opt.mru", FT_UINT16, BASE_DEC,
6630                 NULL, 0x0, NULL, HFILL }},
6631         { &hf_lcp_opt_asyncmap,
6632             { "Async Control Character Map", "lcp.opt.asyncmap", FT_UINT32,
6633                 BASE_HEX, NULL, 0x0, NULL, HFILL }},
6634         { &hf_lcp_opt_asyncmap_nul,
6635             { "NUL", "lcp.opt.asyncmap.nul", FT_BOOLEAN, 32,
6636                 NULL, 0x00000001, NULL, HFILL }},
6637         { &hf_lcp_opt_asyncmap_soh,
6638             { "SOH", "lcp.opt.asyncmap.soh", FT_BOOLEAN, 32,
6639                 NULL, 0x00000002, NULL, HFILL }},
6640         { &hf_lcp_opt_asyncmap_stx,
6641             { "STX", "lcp.opt.asyncmap.stx", FT_BOOLEAN, 32,
6642                 NULL, 0x00000004, NULL, HFILL }},
6643         { &hf_lcp_opt_asyncmap_etx,
6644             { "ETX", "lcp.opt.asyncmap.etx", FT_BOOLEAN, 32,
6645                 NULL, 0x00000008, NULL, HFILL }},
6646         { &hf_lcp_opt_asyncmap_eot,
6647             { "EOT", "lcp.opt.asyncmap.eot", FT_BOOLEAN, 32,
6648                 NULL, 0x00000010, NULL, HFILL }},
6649         { &hf_lcp_opt_asyncmap_enq,
6650             { "ENQ", "lcp.opt.asyncmap.enq", FT_BOOLEAN, 32,
6651                 NULL, 0x00000020, NULL, HFILL }},
6652         { &hf_lcp_opt_asyncmap_ack,
6653             { "ACK", "lcp.opt.asyncmap.ack", FT_BOOLEAN, 32,
6654                 NULL, 0x00000040, NULL, HFILL }},
6655         { &hf_lcp_opt_asyncmap_bel,
6656             { "BEL", "lcp.opt.asyncmap.bel", FT_BOOLEAN, 32,
6657                 NULL, 0x00000080, NULL, HFILL }},
6658         { &hf_lcp_opt_asyncmap_bs,
6659             { "BS", "lcp.opt.asyncmap.bs", FT_BOOLEAN, 32,
6660                 NULL, 0x00000100, NULL, HFILL }},
6661         { &hf_lcp_opt_asyncmap_ht,
6662             { "HT", "lcp.opt.asyncmap.ht", FT_BOOLEAN, 32,
6663                 NULL, 0x00000200, NULL, HFILL }},
6664         { &hf_lcp_opt_asyncmap_lf,
6665             { "LF", "lcp.opt.asyncmap.lf", FT_BOOLEAN, 32,
6666                 NULL, 0x00000400, NULL, HFILL }},
6667         { &hf_lcp_opt_asyncmap_vt,
6668             { "VT", "lcp.opt.asyncmap.vt", FT_BOOLEAN, 32,
6669                 NULL, 0x00000800, NULL, HFILL }},
6670         { &hf_lcp_opt_asyncmap_ff,
6671             { "FF", "lcp.opt.asyncmap.ff", FT_BOOLEAN, 32,
6672                 NULL, 0x00001000, NULL, HFILL }},
6673         { &hf_lcp_opt_asyncmap_cr,
6674             { "CR", "lcp.opt.asyncmap.cr", FT_BOOLEAN, 32,
6675                 NULL, 0x00002000, NULL, HFILL }},
6676         { &hf_lcp_opt_asyncmap_so,
6677             { "SO", "lcp.opt.asyncmap.so", FT_BOOLEAN, 32,
6678                 NULL, 0x00004000, NULL, HFILL }},
6679         { &hf_lcp_opt_asyncmap_si,
6680             { "SI", "lcp.opt.asyncmap.si", FT_BOOLEAN, 32,
6681                 NULL, 0x00008000, NULL, HFILL }},
6682         { &hf_lcp_opt_asyncmap_dle,
6683             { "DLE", "lcp.opt.asyncmap.dle", FT_BOOLEAN, 32,
6684                 NULL, 0x00010000, NULL, HFILL }},
6685         { &hf_lcp_opt_asyncmap_dc1,
6686             { "DC1 (XON)", "lcp.opt.asyncmap.dc1", FT_BOOLEAN, 32,
6687                 NULL, 0x00020000, NULL, HFILL }},
6688         { &hf_lcp_opt_asyncmap_dc2,
6689             { "DC2", "lcp.opt.asyncmap.dc2", FT_BOOLEAN, 32,
6690                 NULL, 0x00040000, NULL, HFILL }},
6691         { &hf_lcp_opt_asyncmap_dc3,
6692             { "DC3 (XOFF)", "lcp.opt.asyncmap.dc3", FT_BOOLEAN, 32,
6693                 NULL, 0x00080000, NULL, HFILL }},
6694         { &hf_lcp_opt_asyncmap_dc4,
6695             { "DC4", "lcp.opt.asyncmap.dc4", FT_BOOLEAN, 32,
6696                 NULL, 0x00100000, NULL, HFILL }},
6697         { &hf_lcp_opt_asyncmap_nak,
6698             { "NAK", "lcp.opt.asyncmap.nak", FT_BOOLEAN, 32,
6699                 NULL, 0x00200000, NULL, HFILL }},
6700         { &hf_lcp_opt_asyncmap_syn,
6701             { "SYN", "lcp.opt.asyncmap.syn", FT_BOOLEAN, 32,
6702                 NULL, 0x00400000, NULL, HFILL }},
6703         { &hf_lcp_opt_asyncmap_etb,
6704             { "ETB", "lcp.opt.asyncmap.etb", FT_BOOLEAN, 32,
6705                 NULL, 0x00800000, NULL, HFILL }},
6706         { &hf_lcp_opt_asyncmap_can,
6707             { "CAN", "lcp.opt.asyncmap.can", FT_BOOLEAN, 32,
6708                 NULL, 0x01000000, NULL, HFILL }},
6709         { &hf_lcp_opt_asyncmap_em,
6710             { "EM", "lcp.opt.asyncmap.em", FT_BOOLEAN, 32,
6711                 NULL, 0x02000000, NULL, HFILL }},
6712         { &hf_lcp_opt_asyncmap_sub,
6713             { "SUB", "lcp.opt.asyncmap.sub", FT_BOOLEAN, 32,
6714                 NULL, 0x04000000, NULL, HFILL }},
6715         { &hf_lcp_opt_asyncmap_esc,
6716             { "ESC", "lcp.opt.asyncmap.esc", FT_BOOLEAN, 32,
6717                 NULL, 0x08000000, NULL, HFILL }},
6718         { &hf_lcp_opt_asyncmap_fs,
6719             { "FS", "lcp.opt.asyncmap.fs", FT_BOOLEAN, 32,
6720                 NULL, 0x10000000, NULL, HFILL }},
6721         { &hf_lcp_opt_asyncmap_gs,
6722             { "GS", "lcp.opt.asyncmap.gs", FT_BOOLEAN, 32,
6723                 NULL, 0x20000000, NULL, HFILL }},
6724         { &hf_lcp_opt_asyncmap_rs,
6725             { "RS", "lcp.opt.asyncmap.rs", FT_BOOLEAN, 32,
6726                 NULL, 0x40000000, NULL, HFILL }},
6727         { &hf_lcp_opt_asyncmap_us,
6728             { "US", "lcp.opt.asyncmap.us", FT_BOOLEAN, 32,
6729                 NULL, 0x80000000, NULL, HFILL }},
6730         { &hf_lcp_opt_auth_protocol,
6731             { "Authentication Protocol", "lcp.opt.auth_protocol", FT_UINT16,
6732                 BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
6733         { &hf_lcp_opt_algorithm,
6734             { "Algorithm", "lcp.opt.algorithm", FT_UINT8,
6735                 BASE_DEC | BASE_RANGE_STRING, &chap_alg_rvals,
6736                 0x0, NULL, HFILL }},
6737         { &hf_lcp_opt_quality_protocol,
6738             { "Quality Protocol", "lcp.opt.quality_protocol", FT_UINT16,
6739                 BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
6740         { &hf_lcp_opt_magic_number,
6741             { "Magic Number", "lcp.opt.magic_number", FT_UINT32, BASE_HEX,
6742                 NULL, 0x0, NULL, HFILL }},
6743         { &hf_lcp_opt_reportingperiod,
6744             { "Reporting Period", "lcp.opt.reporting_period", FT_UINT32,
6745                 BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0,
6746                 "Maximum time in micro-seconds that the remote end should "
6747                 "wait between transmission of LCP Link-Quality-Report packets",
6748                 HFILL }},
6749         { &hf_lcp_opt_fcs_alternatives,
6750             { "FCS Alternatives", "lcp.opt.fcs_alternatives", FT_UINT8,
6751                 BASE_HEX, NULL, 0x0, NULL, HFILL }},
6752         { &hf_lcp_opt_fcs_alternatives_null,
6753             { "NULL FCS", "lcp.opt.fcs_alternatives.null", FT_BOOLEAN, 8,
6754                 NULL, 0x01, NULL, HFILL }},
6755         { &hf_lcp_opt_fcs_alternatives_ccitt16,
6756             { "CCITT 16-bit", "lcp.opt.fcs_alternatives.ccitt16", FT_BOOLEAN,
6757                 8, NULL, 0x02, NULL, HFILL }},
6758         { &hf_lcp_opt_fcs_alternatives_ccitt32,
6759             { "CCITT 32-bit", "lcp.opt.fcs_alternatives.ccitt32", FT_BOOLEAN,
6760                 8, NULL, 0x04, NULL, HFILL }},
6761         { &hf_lcp_opt_maximum,
6762             { "Maximum", "lcp.opt.maximum", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0,
6763                 "The largest number of padding octets which may be added "
6764                 "to the frame.", HFILL }},
6765         { &hf_lcp_opt_window,
6766             { "Window", "lcp.opt.window", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_frame_frames, 0x0,
6767                 "The number of frames the receiver will buffer.", HFILL }},
6768         { &hf_lcp_opt_hdlc_address,
6769             { "Address", "lcp.opt.hdlc_address", FT_BYTES, BASE_NONE, NULL,
6770                 0x0, "An HDLC Address as specified in ISO 3309.", HFILL }},
6771         { &hf_lcp_opt_operation,
6772             { "Operation", "lcp.opt.operation", FT_UINT8, BASE_DEC,
6773                 VALS(callback_op_vals), 0x0, NULL, HFILL }},
6774         { &hf_lcp_opt_message,
6775             { "Message", "lcp.opt.message", FT_BYTES, BASE_NONE,
6776                 NULL, 0x0, NULL, HFILL }},
6777         { &hf_lcp_opt_mrru,
6778             { "MRRU", "lcp.opt.mrru", FT_UINT16, BASE_DEC, NULL, 0x0,
6779                 "Maximum Receive Reconstructed Unit", HFILL }},
6780         { &hf_lcp_opt_ep_disc_class,
6781             { "Class", "lcp.opt.ep_disc_class", FT_UINT8, BASE_DEC,
6782                 VALS(multilink_ep_disc_class_vals), 0x0, NULL, HFILL }},
6783         { &hf_lcp_opt_ip_address,
6784             { "IP Address", "lcp.opt.ip_address", FT_IPv4, BASE_NONE,
6785                 NULL, 0x0, NULL, HFILL }},
6786         { &hf_lcp_opt_802_1_address,
6787             { "IEEE 802.1 Address", "lcp.opt.802_1_address", FT_ETHER,
6788                 BASE_NONE, NULL, 0x0, NULL, HFILL }},
6789         { &hf_lcp_opt_magic_block,
6790             { "PPP Magic-Number Block", "lcp.opt.magic_block", FT_BYTES,
6791                 BASE_NONE, NULL, 0x0, NULL, HFILL }},
6792         { &hf_lcp_opt_psndn,
6793             { "Public Switched Network Directory Number", "lcp.opt.psndn",
6794                 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6795         { &hf_lcp_opt_mode,
6796             { "Mode", "lcp.opt.mode", FT_UINT8, BASE_DEC,
6797                 VALS(dce_id_mode_vals), 0x0, NULL, HFILL }},
6798         { &hf_lcp_opt_unused,
6799             { "Unused", "lcp.opt.unused", FT_BYTES, BASE_NONE,
6800                 NULL, 0x0, NULL, HFILL }},
6801         { &hf_lcp_opt_link_discrim,
6802             { "Link Discriminator", "lcp.opt.link_discrim", FT_UINT16,
6803                 BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }},
6804         { &hf_lcp_opt_id,
6805             { "Identification", "lcp.opt.id", FT_UINT_BYTES, BASE_NONE,
6806                 NULL, 0x0, NULL, HFILL }},
6807         { &hf_lcp_opt_cobs_flags,
6808             { "Flags", "lcp.opt.flags", FT_UINT8, BASE_HEX,
6809                 NULL, 0x0, NULL, HFILL }},
6810         { &hf_lcp_opt_cobs_flags_res,
6811             { "Reserved", "lcp.opt.flags.reserved", FT_UINT8, BASE_HEX,
6812                 NULL, 0xFC, NULL, HFILL }},
6813         { &hf_lcp_opt_cobs_flags_pre,
6814             { "PRE", "lcp.opt.flags.pre", FT_BOOLEAN, 8,
6815                 NULL, 0x02, "Preemption", HFILL }},
6816         { &hf_lcp_opt_cobs_flags_zxe,
6817             { "ZXE", "lcp.opt.flags.zxe", FT_BOOLEAN, 8,
6818                 NULL, 0x01, "Zero pair/run elimination", HFILL }},
6819         { &hf_lcp_opt_class,
6820             { "Class", "lcp.opt.class", FT_UINT8, BASE_DEC,
6821                 NULL, 0x0, NULL, HFILL }},
6822         { &hf_lcp_opt_prefix,
6823             { "Prefix", "lcp.opt.prefix", FT_UINT_BYTES, BASE_NONE,
6824                 NULL, 0x0, NULL, HFILL }},
6825         { &hf_lcp_opt_code,
6826             { "Code", "lcp.opt.code", FT_UINT8, BASE_DEC,
6827                 VALS(ml_hdr_fmt_code_vals), 0x0, NULL, HFILL }},
6828         { &hf_lcp_opt_max_susp_classes,
6829             { "Max suspendable classes", "lcp.opt.max_susp_classes",
6830                 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
6831         { &hf_lcp_opt_MIBenum,
6832             { "MIBenum", "lcp.opt.MIBenum", FT_UINT32,
6833                 BASE_DEC | BASE_EXT_STRING, &charset_vals_ext, 0x0,
6834                 "A unique integer value identifying a charset", HFILL }},
6835         { &hf_lcp_opt_language_tag,
6836             { "Language-Tag", "lcp.opt.language_tag", FT_STRING, BASE_NONE,
6837                 NULL, 0x0, NULL, HFILL }}
6838     };
6839 
6840     static gint *ett[] = {
6841         &ett_lcp,
6842         &ett_lcp_options,
6843         &ett_lcp_vendor_opt,
6844         &ett_lcp_mru_opt,
6845         &ett_lcp_asyncmap_opt,
6846         &ett_lcp_authprot_opt,
6847         &ett_lcp_qualprot_opt,
6848         &ett_lcp_magicnumber_opt,
6849         &ett_lcp_linkqualmon_opt,
6850         &ett_lcp_pcomp_opt,
6851         &ett_lcp_acccomp_opt,
6852         &ett_lcp_fcs_alternatives_opt,
6853         &ett_lcp_self_desc_pad_opt,
6854         &ett_lcp_numbered_mode_opt,
6855         &ett_lcp_callback_opt,
6856         &ett_lcp_compound_frames_opt,
6857         &ett_lcp_nomdataencap_opt,
6858         &ett_lcp_multilink_mrru_opt,
6859         &ett_lcp_multilink_ssnh_opt,
6860         &ett_lcp_multilink_ep_disc_opt,
6861         &ett_lcp_magic_block,
6862         &ett_lcp_dce_identifier_opt,
6863         &ett_lcp_multilink_pp_opt,
6864         &ett_lcp_bacp_link_discrim_opt,
6865         &ett_lcp_auth_opt,
6866         &ett_lcp_cobs_opt,
6867         &ett_lcp_prefix_elision_opt,
6868         &ett_multilink_hdr_fmt_opt,
6869         &ett_lcp_internationalization_opt,
6870         &ett_lcp_sonet_sdh_opt
6871     };
6872 
6873     proto_lcp = proto_register_protocol("PPP Link Control Protocol", "PPP LCP", "lcp");
6874     proto_register_field_array(proto_lcp, hf, array_length(hf));
6875     proto_register_subtree_array(ett, array_length(ett));
6876 
6877     lcp_option_table = register_dissector_table("lcp.option", "PPP LCP Options", proto_lcp, FT_UINT8, BASE_DEC);
6878 
6879     /* Register LCP options as their own protocols so we can get the name of the option */
6880     proto_lcp_option_vendor = proto_register_protocol_in_name_only("Vendor Specific", "Vendor Specific", "lcp.opt.vendor", proto_lcp, FT_BYTES);
6881     proto_lcp_option_mru = proto_register_protocol_in_name_only("Maximum Receive Unit", "Maximum Receive Unit", "lcp.opt.mtu_bytes", proto_lcp, FT_BYTES);
6882     proto_lcp_option_async_map = proto_register_protocol_in_name_only("Async Control Character Map", "Async Control Character Map", "lcp.opt.asyncmap_bytes", proto_lcp, FT_BYTES);
6883     proto_lcp_option_authprot = proto_register_protocol_in_name_only("Authentication Protocol", "Authentication Protocol", "lcp.opt.auth_protocol_bytes", proto_lcp, FT_BYTES);
6884     proto_lcp_option_qualprot = proto_register_protocol_in_name_only("Quality Protocol", "Quality Protocol", "lcp.opt.quality_protocol_bytes", proto_lcp, FT_BYTES);
6885     proto_lcp_option_magicnumber = proto_register_protocol_in_name_only("Magic Number", "Magic Number", "lcp.opt.magic_number_bytes", proto_lcp, FT_BYTES);
6886     proto_lcp_option_linkqualmon = proto_register_protocol_in_name_only("Link Quality Monitoring", "Link Quality Monitoring", "lcp.opt.linkqualmon", proto_lcp, FT_BYTES);
6887     proto_lcp_option_field_compress = proto_register_protocol_in_name_only("Protocol Field Compression", "Protocol Field Compression", "lcp.opt.field_compress", proto_lcp, FT_BYTES);
6888     proto_lcp_option_addr_field_compress = proto_register_protocol_in_name_only("Address and Control Field Compression", "Address and Control Field Compression", "lcp.opt.addr_field_compress", proto_lcp, FT_BYTES);
6889     proto_lcp_option_fcs_alternatives = proto_register_protocol_in_name_only("FCS Alternatives", "FCS Alternatives", "lcp.opt.fcs_alternatives_bytes", proto_lcp, FT_BYTES);
6890     proto_lcp_option_self_desc_pad = proto_register_protocol_in_name_only("Self Describing Pad", "Self Describing Pad", "lcp.opt.self_desc_pad", proto_lcp, FT_BYTES);
6891     proto_lcp_option_numbered_mode = proto_register_protocol_in_name_only("Numbered Mode", "Numbered Mode", "lcp.opt.numbered_mode", proto_lcp, FT_BYTES);
6892     /* TODO? CI_MULTILINK_PROC */
6893     proto_lcp_option_callback = proto_register_protocol_in_name_only("Callback", "Callback", "lcp.opt.callback", proto_lcp, FT_BYTES);
6894     /* TODO? CI_CONNECTTIME */
6895     proto_lcp_option_compound_frames = proto_register_protocol_in_name_only("Compound Frames (Deprecated)", "Compound Frames (Deprecated)", "lcp.opt.compound_frames", proto_lcp, FT_BYTES);
6896     proto_lcp_option_nomdataencap = proto_register_protocol_in_name_only("Nominal Data Encapsulation (Deprecated)", "Nominal Data Encapsulation (Deprecated)", "lcp.opt.nomdataencap", proto_lcp, FT_BYTES);
6897     proto_lcp_option_multilink_mrru = proto_register_protocol_in_name_only("Multilink MRRU", "Multilink MRRU", "lcp.opt.multilink_mrru", proto_lcp, FT_BYTES);
6898     proto_lcp_option_multilink_ssnh = proto_register_protocol_in_name_only("Multilink Short Sequence Number Header", "Multilink Short Sequence Number Header", "lcp.opt.multilink_ssnh", proto_lcp, FT_BYTES);
6899     proto_lcp_option_multilink_ep_disc = proto_register_protocol_in_name_only("Multilink Endpoint Discriminator", "Multilink Endpoint Discriminator", "lcp.opt.multilink_ep_disc", proto_lcp, FT_BYTES);
6900     /* TODO? CI_PROP_KEN: ken@funk.com: www.funk.com => www.juniper.net */
6901     proto_lcp_option_dce_identifier = proto_register_protocol_in_name_only("DCE Identifier", "DCE Identifier", "lcp.opt.dce_identifier", proto_lcp, FT_BYTES);
6902     proto_lcp_option_multilink_pp = proto_register_protocol_in_name_only("Multi Link Plus Procedure", "Multi Link Plus Procedure", "lcp.opt.multilink_pp", proto_lcp, FT_BYTES);
6903     proto_lcp_option_link_discrim = proto_register_protocol_in_name_only("Link Discriminator for BACP", "Link Discriminator for BACP", "lcp.opt.link_discrim_bytes", proto_lcp, FT_BYTES);
6904     proto_lcp_option_auth = proto_register_protocol_in_name_only("Authentication Option", "Authentication Option", "lcp.opt.auth", proto_lcp, FT_BYTES);
6905     proto_lcp_option_cobs = proto_register_protocol_in_name_only("Consistent Overhead Byte Stuffing (COBS)", "Consistent Overhead Byte Stuffing (COBS)", "lcp.opt.cobs", proto_lcp, FT_BYTES);
6906     proto_lcp_option_prefix_elision = proto_register_protocol_in_name_only("Prefix Elision", "Prefix Elision", "lcp.opt.prefix_elision", proto_lcp, FT_BYTES);
6907     proto_lcp_option_multilink_hdr_fmt = proto_register_protocol_in_name_only("Multilink header format", "Multilink header format", "lcp.opt.multilink_hdr_fmt", proto_lcp, FT_BYTES);
6908     proto_lcp_option_internationalization = proto_register_protocol_in_name_only("Internationalization", "Internationalization", "lcp.opt.internationalization", proto_lcp, FT_BYTES);
6909     proto_lcp_option_sonet_sdh = proto_register_protocol_in_name_only("Simple Data Link on SONET/SDH", "Simple Data Link on SONET/SDH", "lcp.opt.sonet_sdh", proto_lcp, FT_BYTES);
6910 }
6911 
6912 void
proto_reg_handoff_lcp(void)6913 proto_reg_handoff_lcp(void)
6914 {
6915     dissector_handle_t lcp_handle;
6916 
6917     lcp_handle = create_dissector_handle(dissect_lcp, proto_lcp);
6918     dissector_add_uint("ppp.protocol", PPP_LCP, lcp_handle);
6919 
6920 
6921     /*
6922      * NDISWAN on Windows translates Ethernet frames from higher-level
6923      * protocols into PPP frames to hand to the PPP driver, and translates
6924      * PPP frames from the PPP driver to hand to the higher-level protocols.
6925      *
6926      * Apparently the PPP driver, on at least some versions of Windows,
6927      * passes frames for internal-to-PPP protocols up through NDISWAN;
6928      * the protocol type field appears to be passed through unchanged
6929      * (unlike what's done with, for example, the protocol type field
6930      * for IP, which is mapped from its PPP value to its Ethernet value).
6931      *
6932      * This means that we may see, on Ethernet captures, frames for
6933      * protocols internal to PPP, so we register PPP_LCP with the
6934      * "ethertype" dissector table as well as the PPP protocol dissector
6935      * table.
6936      */
6937     dissector_add_uint("ethertype", PPP_LCP, lcp_handle);
6938 
6939     /*
6940      * for GSM-A / MobileL3 / GPRS SM / PCO
6941      */
6942     dissector_add_uint("sm_pco.protocol", PPP_LCP, lcp_handle);
6943 
6944     /* Create dissection function handles for all LCP options */
6945     dissector_add_uint("lcp.option", CI_VENDORSPECIFIC, create_dissector_handle( dissect_lcp_vendor_opt, proto_lcp_option_vendor ));
6946     dissector_add_uint("lcp.option", CI_MRU, create_dissector_handle( dissect_lcp_mru_opt, proto_lcp_option_mru ));
6947     dissector_add_uint("lcp.option", CI_ASYNCMAP, create_dissector_handle( dissect_lcp_async_map_opt, proto_lcp_option_async_map ));
6948     dissector_add_uint("lcp.option", CI_AUTHPROT, create_dissector_handle( dissect_lcp_authprot_opt, proto_lcp_option_authprot ));
6949     dissector_add_uint("lcp.option", CI_QUALITY, create_dissector_handle( dissect_lcp_qualprot_opt, proto_lcp_option_qualprot ));
6950     dissector_add_uint("lcp.option", CI_MAGICNUMBER, create_dissector_handle( dissect_lcp_magicnumber_opt, proto_lcp_option_magicnumber ));
6951     dissector_add_uint("lcp.option", CI_LINKQUALMON, create_dissector_handle( dissect_lcp_linkqualmon_opt, proto_lcp_option_linkqualmon ));
6952     dissector_add_uint("lcp.option", CI_PCOMPRESSION, create_dissector_handle( dissect_lcp_field_compress, proto_lcp_option_field_compress ));
6953     dissector_add_uint("lcp.option", CI_ACCOMPRESSION, create_dissector_handle( dissect_lcp_addr_field_compress, proto_lcp_option_addr_field_compress ));
6954     dissector_add_uint("lcp.option", CI_FCS_ALTERNATIVES, create_dissector_handle( dissect_lcp_fcs_alternatives_opt, proto_lcp_option_fcs_alternatives ));
6955     dissector_add_uint("lcp.option", CI_SELF_DESCRIBING_PAD, create_dissector_handle( dissect_lcp_self_describing_pad_opt, proto_lcp_option_self_desc_pad ));
6956     dissector_add_uint("lcp.option", CI_NUMBERED_MODE, create_dissector_handle( dissect_lcp_numbered_mode_opt, proto_lcp_option_numbered_mode ));
6957     /* TODO? CI_MULTILINK_PROC */
6958     dissector_add_uint("lcp.option", CI_CALLBACK, create_dissector_handle( dissect_lcp_callback_opt, proto_lcp_option_callback ));
6959     /* TODO? CI_CONNECTTIME */
6960     dissector_add_uint("lcp.option", CI_COMPOUND_FRAMES, create_dissector_handle( dissect_lcp_compound_frames_opt, proto_lcp_option_compound_frames ));
6961     dissector_add_uint("lcp.option", CI_NOMDATAENCAP, create_dissector_handle( dissect_lcp_nomdataencap_opt, proto_lcp_option_nomdataencap ));
6962     dissector_add_uint("lcp.option", CI_MULTILINK_MRRU, create_dissector_handle( dissect_lcp_multilink_mrru_opt, proto_lcp_option_multilink_mrru ));
6963     dissector_add_uint("lcp.option", CI_MULTILINK_SSNH, create_dissector_handle( dissect_lcp_multilink_ssnh_opt, proto_lcp_option_multilink_ssnh ));
6964     dissector_add_uint("lcp.option", CI_MULTILINK_EP_DISC, create_dissector_handle( dissect_lcp_multilink_ep_disc_opt, proto_lcp_option_multilink_ep_disc ));
6965     /* TODO? CI_PROP_KEN: ken@funk.com: www.funk.com => www.juniper.net */
6966     dissector_add_uint("lcp.option", CI_DCE_IDENTIFIER, create_dissector_handle( dissect_lcp_dce_identifier_opt, proto_lcp_option_dce_identifier ));
6967     dissector_add_uint("lcp.option", CI_MULTILINK_PLUS_PROC, create_dissector_handle( dissect_lcp_multilink_pp_opt, proto_lcp_option_multilink_pp ));
6968     dissector_add_uint("lcp.option", CI_LINK_DISC_FOR_BACP, create_dissector_handle( dissect_lcp_bacp_link_discriminator_opt, proto_lcp_option_link_discrim ));
6969     dissector_add_uint("lcp.option", CI_LCP_AUTHENTICATION, create_dissector_handle( dissect_lcp_auth_opt, proto_lcp_option_auth ));
6970     dissector_add_uint("lcp.option", CI_COBS, create_dissector_handle( dissect_lcp_cobs_opt, proto_lcp_option_cobs ));
6971     dissector_add_uint("lcp.option", CI_PREFIX_ELISION, create_dissector_handle( dissect_lcp_prefix_elision_opt, proto_lcp_option_prefix_elision ));
6972     dissector_add_uint("lcp.option", CI_MULTILINK_HDR_FMT, create_dissector_handle( dissect_lcp_multilink_hdr_fmt_opt, proto_lcp_option_multilink_hdr_fmt ));
6973     dissector_add_uint("lcp.option", CI_INTERNATIONALIZATION, create_dissector_handle( dissect_lcp_internationalization_opt, proto_lcp_option_internationalization ));
6974     dissector_add_uint("lcp.option", CI_SDL_ON_SONET_SDH, create_dissector_handle( dissect_lcp_sonet_sdh_opt, proto_lcp_option_sonet_sdh ));
6975 }
6976 
6977 void
proto_register_vsncp(void)6978 proto_register_vsncp(void)
6979 {
6980     static hf_register_info hf[] = {
6981       { &hf_vsncp_opt_type, { "Type", "vsncp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
6982       { &hf_vsncp_opt_length, { "Length", "vsncp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
6983       /* Generated from convert_proto_tree_add_text.pl */
6984       { &hf_vsncp_pdn_identifier, { "PDN Identifier", "vsncp.pdn_identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
6985       { &hf_vsncp_attach_type, { "Attach Type", "vsncp.attach_type", FT_UINT8, BASE_HEX, VALS(vsncp_attach_vals), 0x0, NULL, HFILL }},
6986       { &hf_vsncp_pdn_type, { "PDN Type", "vsncp.pdn_type", FT_UINT8, BASE_HEX, VALS(vsncp_pdntype_vals), 0x0, NULL, HFILL }},
6987       { &hf_vsncp_error_code, { "Error Code", "vsncp.error_code", FT_UINT8, BASE_HEX, VALS(vsncp_errorcode_vals), 0x0, NULL, HFILL }},
6988       { &hf_vsncp_pdn_ipv4, { "PDN IPv4", "vsncp.pdn_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6989       { &hf_vsncp_pdn_ipv6, { "PDN IPv6", "vsncp.pdn_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6990       { &hf_vsncp_default_router_address, { "IPv4 Default Router Address", "vsncp.default_router_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6991       { &hf_vsncp_access_point_name, { "Access Point Name Label", "vsncp.access_point_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6992       { &hf_vsncp_address_allocation_cause, { "Address Allocation Cause", "vsncp.address_allocation_cause", FT_UINT8, BASE_HEX, VALS(vsncp_alloc_vals), 0x0, NULL, HFILL }},
6993       { &hf_vsncp_ambr_data, { "AMBR Data", "vsncp.ambr_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6994       { &hf_vsncp_ipv6_interface_identifier, { "IPv6 interface identifier", "vsncp.ipv6_interface_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6995       { &hf_vsncp_protocol, { "Protocol", "vsncp.protocol", FT_UINT16, BASE_HEX, VALS(vsncp_pco_vals), 0x0, NULL, HFILL }},
6996       { &hf_vsncp_protocol_configuration_length, { "Length", "vsncp.protocol_configuration_length", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
6997       { &hf_vsncp_protocol_configuration_data, { "Data", "vsncp.protocol_configuration_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6998       { &hf_vsncp_code, { "Code", "vsncp.code", FT_UINT8, BASE_HEX, VALS(cp_vals), 0x0, NULL, HFILL }},
6999       { &hf_vsncp_identifier, { "Identifier", "vsncp.identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
7000       { &hf_vsncp_length, { "Length", "vsncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7001     };
7002 
7003     static gint *ett[] = {
7004         &ett_vsncp,
7005         &ett_vsncp_options,
7006         &ett_vsncp_pdnid_opt,
7007         &ett_vsncp_apname_opt,
7008         &ett_vsncp_pdntype_opt,
7009         &ett_vsncp_pdnaddress_opt,
7010         &ett_vsncp_pco_opt,
7011         &ett_vsncp_errorcode_opt,
7012         &ett_vsncp_attachtype_opt,
7013         &ett_vsncp_ipv4address_opt,
7014         &ett_vsncp_addressalloc_opt,
7015         &ett_vsncp_apn_ambr_opt,
7016         &ett_vsncp_ipv6_hsgw_lla_iid_opt,
7017     };
7018 
7019     proto_vsncp = proto_register_protocol("Vendor Specific Control Protocol", "VSNCP", "vsncp");
7020     proto_register_subtree_array(ett, array_length(ett));
7021     proto_register_field_array(proto_vsncp, hf, array_length(hf));
7022 
7023     vsncp_option_table = register_dissector_table("vsncp.option", "PPP VSNCP Options", proto_vsncp, FT_UINT8, BASE_DEC);
7024 
7025     /* Register VSNCP options as their own protocols so we can get the name of the option */
7026     proto_vsncp_option_pdnid = proto_register_protocol_in_name_only("PDN Identifier", "PDN Identifier", "vsncp.opt.pdnid", proto_vsncp, FT_BYTES);
7027     proto_vsncp_option_apname = proto_register_protocol_in_name_only("Access Point Name", "Access Point Name", "vsncp.opt.apname", proto_vsncp, FT_BYTES);
7028     proto_vsncp_option_pdntype = proto_register_protocol_in_name_only("PDN Type", "PDN Type", "vsncp.opt.pdntype", proto_vsncp, FT_BYTES);
7029     proto_vsncp_option_pdnaddress = proto_register_protocol_in_name_only("PDN Address", "PDN Address", "vsncp.opt.pdnaddress", proto_vsncp, FT_BYTES);
7030     proto_vsncp_option_pco = proto_register_protocol_in_name_only("Protocol Configuration Options", "Protocol Configuration Options", "vsncp.opt.pco", proto_vsncp, FT_BYTES);
7031     proto_vsncp_option_errorcode = proto_register_protocol_in_name_only("Error Code", "Error Code", "vsncp.opt.errorcode", proto_vsncp, FT_BYTES);
7032     proto_vsncp_option_attachtype = proto_register_protocol_in_name_only("Attach Type", "Attach Type", "vsncp.opt.attachtype", proto_vsncp, FT_BYTES);
7033     proto_vsncp_option_ipv4address = proto_register_protocol_in_name_only("IPv4 Default Router Address", "IPv4 Default Router Address", "vsncp.opt.ipv4address", proto_vsncp, FT_BYTES);
7034     proto_vsncp_option_addressalloc = proto_register_protocol_in_name_only("Address Allocation Cause", "Address Allocation Cause", "vsncp.opt.addressalloc", proto_vsncp, FT_BYTES);
7035     proto_vsncp_option_apn_ambr = proto_register_protocol_in_name_only("APN Aggregate Maximum Bit Rate(APN-AMBR)", "APN Aggregate Maximum Bit Rate(APN-AMBR)", "vsncp.opt.apn_ambr", proto_vsncp, FT_BYTES);
7036     proto_vsncp_option_ipv6_hsgw_lla_iid = proto_register_protocol_in_name_only("IPv6 HSGW Link Local Address IID", "IPv6 HSGW Link Local Address IID", "vsncp.opt.ipv6_hsgw_lla_iid", proto_vsncp, FT_BYTES);
7037 }
7038 
7039 void
proto_reg_handoff_vsncp(void)7040 proto_reg_handoff_vsncp(void)
7041 {
7042     dissector_handle_t vsncp_handle;
7043 
7044     vsncp_handle = create_dissector_handle(dissect_vsncp, proto_vsncp);
7045     dissector_add_uint("ppp.protocol", PPP_VSNCP, vsncp_handle);
7046 
7047     dissector_add_uint("vsncp.option", CI_PDN_IDENTIFIER, create_dissector_handle( dissect_vsncp_pdnid_opt, proto_vsncp_option_pdnid ));
7048     dissector_add_uint("vsncp.option", CI_ACCESS_POINT_NM, create_dissector_handle( dissect_vsncp_apname_opt, proto_vsncp_option_apname ));
7049     dissector_add_uint("vsncp.option", CI_PDN_TYPE, create_dissector_handle( dissect_vsncp_pdntype_opt, proto_vsncp_option_pdntype ));
7050     dissector_add_uint("vsncp.option", CI_PDN_ADDRESS, create_dissector_handle( dissect_vsncp_pdnaddress_opt, proto_vsncp_option_pdnaddress ));
7051     dissector_add_uint("vsncp.option", CI_PROTOCOL_CONFIG, create_dissector_handle( dissect_vsncp_pco_opt, proto_vsncp_option_pco ));
7052     dissector_add_uint("vsncp.option", CI_ERROR_CODE, create_dissector_handle( dissect_vsncp_errorcode_opt, proto_vsncp_option_errorcode ));
7053     dissector_add_uint("vsncp.option", CI_ATTACH_TYPE, create_dissector_handle( dissect_vsncp_attachtype_opt, proto_vsncp_option_attachtype ));
7054     dissector_add_uint("vsncp.option", CI_IPv4DEFAULT_ROUTER, create_dissector_handle( dissect_vsncp_ipv4address_opt, proto_vsncp_option_ipv4address ));
7055     dissector_add_uint("vsncp.option", CI_ADDRESS_ALLOC, create_dissector_handle( dissect_vsncp_addressalloc_opt, proto_vsncp_option_addressalloc ));
7056     dissector_add_uint("vsncp.option", CI_APN_AMBR, create_dissector_handle( dissect_vsncp_apn_ambr_opt, proto_vsncp_option_apn_ambr ));
7057     dissector_add_uint("vsncp.option", CI_IPv6_HSGW_LLA_IID, create_dissector_handle( dissect_vsncp_ipv6_hsgw_lla_iid_opt, proto_vsncp_option_ipv6_hsgw_lla_iid ));
7058 }
7059 
7060 void
proto_register_vsnp(void)7061 proto_register_vsnp(void)
7062 {
7063     static gint *ett[] = {
7064         &ett_vsnp
7065     };
7066 
7067     static hf_register_info hf[] = {
7068         { &hf_vsnp_pdnid,
7069             { "PDN ID", "vsnp.pdnid", FT_UINT8, BASE_HEX,
7070                 NULL, 0x0, NULL, HFILL }}
7071     };
7072 
7073     proto_vsnp = proto_register_protocol("Vendor Specific Network Protocol",
7074         "PPP VSNP", "vsnp");
7075     proto_register_subtree_array(ett, array_length(ett));
7076     proto_register_field_array(proto_vsnp, hf, array_length(hf));
7077 }
7078 
7079 void
proto_reg_handoff_vsnp(void)7080 proto_reg_handoff_vsnp(void)
7081 {
7082     dissector_handle_t vsnp_handle;
7083 
7084     vsnp_handle = create_dissector_handle(dissect_vsnp, proto_vsnp);
7085     dissector_add_uint("ppp.protocol", PPP_VSNP, vsnp_handle);
7086 }
7087 
7088 void
proto_register_ipcp(void)7089 proto_register_ipcp(void)
7090 {
7091     static hf_register_info hf[] = {
7092         { &hf_ipcp_opt_type,
7093             { "Type", "ipcp.opt.type", FT_UINT8, BASE_DEC,
7094                 NULL, 0x0, NULL, HFILL }},
7095         { &hf_ipcp_opt_length,
7096             { "Length", "ipcp.opt.length", FT_UINT8, BASE_DEC,
7097                 NULL, 0x0, NULL, HFILL }},
7098         { &hf_ipcp_opt_src_address,
7099             { "Source IP Address", "ipcp.opt.src_address", FT_IPv4, BASE_NONE,
7100                 NULL, 0x0, NULL, HFILL }},
7101         { &hf_ipcp_opt_dst_address,
7102             { "Destination IP Address", "ipcp.opt.dst_address", FT_IPv4,
7103                 BASE_NONE, NULL, 0x0, NULL, HFILL }},
7104         { &hf_ipcp_opt_compress_proto,
7105             { "IP Compression Protocol", "ipcp.opt.compress_proto", FT_UINT16,
7106                 BASE_HEX, VALS(ipcp_compress_proto_vals), 0x0, NULL, HFILL }},
7107         { &hf_ipcp_opt_max_cid,
7108             { "Max CID", "ipcp.opt.max_cid", FT_UINT16, BASE_DEC,
7109                 NULL, 0x0, "Maximum value of a context identifier", HFILL }},
7110         { &hf_ipcp_opt_mrru,
7111             { "MRRU", "ipcp.opt.mrru", FT_UINT16, BASE_DEC,
7112                 NULL, 0x0, "Maximum Reconstructed Reception Unit", HFILL }},
7113         { &hf_ipcp_opt_max_slot_id,
7114             { "Max Slot ID", "ipcp.opt.max_slot_id", FT_UINT8, BASE_DEC,
7115                 NULL, 0x0, NULL, HFILL }},
7116         { &hf_ipcp_opt_comp_slot_id,
7117             { "Comp Slot ID", "ipcp.opt.comp_slot_id", FT_BOOLEAN, 8,
7118                 TFS(&tfs_comp_slot_id), 0x01, NULL, HFILL }},
7119         { &hf_ipcp_opt_tcp_space,
7120             { "TCP Space", "ipcp.opt.tcp_space", FT_UINT16, BASE_DEC,
7121                 NULL, 0x0, NULL, HFILL }},
7122         { &hf_ipcp_opt_non_tcp_space,
7123             { "Non TCP Space", "ipcp.opt.non_tcp_space", FT_UINT16, BASE_DEC,
7124                 NULL, 0x0, NULL, HFILL }},
7125         { &hf_ipcp_opt_f_max_period,
7126             { "F Max Period", "ipcp.opt.f_max_period", FT_UINT16, BASE_DEC,
7127                 NULL, 0x0, "Maximum interval between full headers", HFILL }},
7128         { &hf_ipcp_opt_f_max_time,
7129             { "F Max Time", "ipcp.opt.f_max_time", FT_UINT16, BASE_DEC, NULL,
7130                 0x0, "Maximum time interval between full headers", HFILL }},
7131         { &hf_ipcp_opt_max_header,
7132             { "Max Header", "ipcp.opt.max_header", FT_UINT16, BASE_DEC, NULL,
7133                 0x0,
7134                 "The largest header size in octets that may be compressed",
7135                 HFILL }},
7136         { &hf_ipcp_data,
7137             { "Data", "ipcp.data", FT_BYTES, BASE_NONE,
7138                 NULL, 0x0, NULL, HFILL }},
7139         { &hf_ipcp_opt_ip_address,
7140             { "IP Address", "ipcp.opt.ip_address", FT_IPv4, BASE_NONE,
7141                 NULL, 0x0, NULL, HFILL }},
7142         { &hf_ipcp_opt_mobilenodehomeaddr,
7143             { "Mobile Node's Home Address", "ipcp.opt.mobilenodehomeaddress",
7144                 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7145         { &hf_ipcp_opt_pri_dns_address,
7146             { "Primary DNS Address", "ipcp.opt.pri_dns_address",
7147                 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7148         { &hf_ipcp_opt_pri_nbns_address,
7149             { "Primary NBNS Address", "ipcp.opt.pri_nbns_address",
7150                 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7151         { &hf_ipcp_opt_sec_dns_address,
7152             { "Secondary DNS Address", "ipcp.opt.sec_dns_address",
7153                 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7154         { &hf_ipcp_opt_sec_nbns_address,
7155             { "Secondary NBNS Address", "ipcp.opt.sec_nbns_address",
7156                 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7157         { &hf_ipcp_opt_rohc_type,
7158             { "Type", "ipcp.opt.rohc.type", FT_UINT8, BASE_DEC,
7159                 NULL, 0x0, NULL, HFILL }},
7160         { &hf_ipcp_opt_rohc_length,
7161             { "Length", "ipcp.opt.rohc.length", FT_UINT8, BASE_DEC,
7162                 NULL, 0x0, NULL, HFILL }},
7163         { &hf_ipcp_opt_rohc_profile,
7164             { "Profile", "ipcp.opt.rohc.profile", FT_UINT16, BASE_HEX,
7165                 VALS(ipcp_rohc_profile_vals), 0x0, NULL, HFILL }},
7166         { &hf_ipcp_opt_iphc_type,
7167             { "Type", "ipcp.opt.iphc.type", FT_UINT8, BASE_DEC,
7168                 NULL, 0x0, NULL, HFILL }},
7169         { &hf_ipcp_opt_iphc_length,
7170             { "Length", "ipcp.opt.iphc.length", FT_UINT8, BASE_DEC,
7171                 NULL, 0x0, NULL, HFILL }},
7172         { &hf_ipcp_opt_iphc_param,
7173             { "Parameter", "ipcp.opt.iphc.param", FT_UINT8, BASE_DEC,
7174                 VALS(ipcp_iphc_parameter_vals), 0x0, NULL, HFILL }}
7175     };
7176 
7177     static gint *ett[] = {
7178         &ett_ipcp,
7179         &ett_ipcp_options,
7180         &ett_ipcp_ipaddrs_opt,
7181         &ett_ipcp_compress_opt,
7182         &ett_ipcp_ipaddr_opt,
7183         &ett_ipcp_mobileipv4_opt,
7184         &ett_ipcp_pridns_opt,
7185         &ett_ipcp_secdns_opt,
7186         &ett_ipcp_prinbns_opt,
7187         &ett_ipcp_secnbns_opt,
7188         &ett_ipcp_iphc_rtp_compress_opt,
7189         &ett_ipcp_iphc_enhanced_rtp_compress_opt,
7190         &ett_ipcp_iphc_neghdrcomp_opt,
7191         &ett_ipcp_rohc_profiles_opt
7192     };
7193 
7194     proto_ipcp = proto_register_protocol("PPP IP Control Protocol", "PPP IPCP", "ipcp");
7195     proto_register_field_array(proto_ipcp, hf, array_length(hf));
7196     proto_register_subtree_array(ett, array_length(ett));
7197 
7198     ipcp_option_table = register_dissector_table("ipcp.option", "PPP IPCP Options", proto_ipcp, FT_UINT8, BASE_DEC);
7199     ipcp_rohc_suboption_table = register_dissector_table("ipcp.rohc.option", "PPP IPCP ROHC Options", proto_ipcp, FT_UINT8, BASE_DEC);
7200     ipcp_iphc_suboption_table = register_dissector_table("ipcp.iphc.option", "PPP IPCP IPHC Options", proto_ipcp, FT_UINT8, BASE_DEC);
7201 
7202     /* Register IPCP options as their own protocols so we can get the name of the option */
7203     proto_ipcp_option_addrs = proto_register_protocol_in_name_only("IP Addresses (deprecated)", "IP Addresses (deprecated)", "ipcp.opt.addrs", proto_ipcp, FT_BYTES);
7204     proto_ipcp_option_compress = proto_register_protocol_in_name_only("IP Compression Protocol", "IP Compression Protocol", "ipcp.opt.compress", proto_ipcp, FT_BYTES);
7205     proto_ipcp_option_addr = proto_register_protocol_in_name_only("IP Address", "IP Address", "ipcp.opt.addr", proto_ipcp, FT_BYTES);
7206     proto_ipcp_option_mobileipv4 = proto_register_protocol_in_name_only("Mobile Node's Home IP Address", "Mobile Node's Home IP Address", "ipcp.opt.mobileipv4", proto_ipcp, FT_BYTES);
7207     proto_ipcp_option_pri_dns = proto_register_protocol_in_name_only("Primary DNS Server IP Address", "Primary DNS Server IP Address", "ipcp.opt.pri_dns", proto_ipcp, FT_BYTES);
7208     proto_ipcp_option_pri_nbns = proto_register_protocol_in_name_only("Primary NBNS Server IP Address", "Primary NBNS Server IP Address", "ipcp.opt.pri_nbns", proto_ipcp, FT_BYTES);
7209     proto_ipcp_option_sec_dns = proto_register_protocol_in_name_only("Secondary DNS Server IP Address", "Secondary DNS Server IP Address", "ipcp.opt.sec_dns", proto_ipcp, FT_BYTES);
7210     proto_ipcp_option_sec_nbns = proto_register_protocol_in_name_only("Secondary NBNS Server IP Address", "Secondary NBNS Server IP Address", "ipcp.opt.sec_nbns", proto_ipcp, FT_BYTES);
7211 
7212     proto_ipcp_rohc_option_profiles = proto_register_protocol_in_name_only("Profiles (RFC3241)", "Profiles (RFC3241)", "ipcp.opt.rohc.profile_bytes", proto_ipcp, FT_BYTES);
7213 
7214     proto_ipcp_iphc_option_rtp_compress = proto_register_protocol_in_name_only("RTP compression (RFC2508)", "RTP compression (RFC2508)", "ipcp.opt.iphc.rtp_compress", proto_ipcp, FT_BYTES);
7215     proto_ipcp_iphc_option_enhanced_rtp_compress = proto_register_protocol_in_name_only("Enhanced RTP compression (RFC3545)", "Enhanced RTP compression (RFC3545)", "ipcp.opt.iphc.enhanced_rtp_compress", proto_ipcp, FT_BYTES);
7216     proto_ipcp_iphc_option_neghdrcomp = proto_register_protocol_in_name_only("Negotiating header compression (RFC3545)", "Negotiating header compression (RFC3545)", "ipcp.opt.iphc.neghdrcomp", proto_ipcp, FT_BYTES);
7217 }
7218 
7219 void
proto_reg_handoff_ipcp(void)7220 proto_reg_handoff_ipcp(void)
7221 {
7222     dissector_handle_t ipcp_handle;
7223 
7224     ipcp_handle = create_dissector_handle(dissect_ipcp, proto_ipcp);
7225     dissector_add_uint("ppp.protocol", PPP_IPCP, ipcp_handle);
7226 
7227     /*
7228      * See above comment about NDISWAN for an explanation of why we're
7229      * registering with the "ethertype" dissector table.
7230      */
7231     dissector_add_uint("ethertype", PPP_IPCP, ipcp_handle);
7232 
7233     /*
7234      * for GSM-A / MobileL3 / GPRS SM / PCO
7235      */
7236     dissector_add_uint("sm_pco.protocol", PPP_IPCP, ipcp_handle);
7237 
7238     dissector_add_uint("ipcp.option", CI_ADDRS, create_dissector_handle( dissect_ipcp_addrs_opt, proto_ipcp_option_addrs ));
7239     dissector_add_uint("ipcp.option", CI_COMPRESS_PROTO, create_dissector_handle( dissect_ipcp_compress_opt, proto_ipcp_option_compress ));
7240     dissector_add_uint("ipcp.option", CI_ADDR, create_dissector_handle( dissect_ipcp_addr_opt, proto_ipcp_option_addr ));
7241     dissector_add_uint("ipcp.option", CI_MOBILE_IPv4, create_dissector_handle( dissect_ipcp_mobileipv4_opt, proto_ipcp_option_mobileipv4 ));
7242     dissector_add_uint("ipcp.option", CI_PRI_DNS, create_dissector_handle( dissect_ipcp_pri_dns_opt, proto_ipcp_option_pri_dns ));
7243     dissector_add_uint("ipcp.option", CI_PRI_NBNS, create_dissector_handle( dissect_ipcp_pri_nbns_opt, proto_ipcp_option_pri_nbns ));
7244     dissector_add_uint("ipcp.option", CI_SEC_DNS, create_dissector_handle( dissect_ipcp_sec_dns_opt, proto_ipcp_option_sec_dns ));
7245     dissector_add_uint("ipcp.option", CI_SEC_NBNS, create_dissector_handle( dissect_ipcp_sec_nbns_opt, proto_ipcp_option_sec_nbns ));
7246 
7247     dissector_add_uint("ipcp.rohc.option", IPCP_ROHC_PROFILES, create_dissector_handle( dissect_ipcp_rohc_profiles_opt, proto_ipcp_rohc_option_profiles ));
7248 
7249     dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_CRTP, create_dissector_handle( dissect_ipcp_iphc_rtp_compress, proto_ipcp_iphc_option_rtp_compress ));
7250     dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_ECRTP, create_dissector_handle( dissect_ipcp_iphc_enhanced_rtp_compress, proto_ipcp_iphc_option_enhanced_rtp_compress ));
7251     dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_NEGHC, create_dissector_handle( dissect_ipcp_iphc_neghdrcomp_opt, proto_ipcp_iphc_option_neghdrcomp ));
7252 }
7253 
7254 void
proto_register_bcp_bpdu(void)7255 proto_register_bcp_bpdu(void)
7256 {
7257     static hf_register_info hf[] = {
7258         { &hf_bcp_bpdu_flags,
7259             { "Flags", "bcp_bpdu.flags", FT_UINT8, BASE_HEX,
7260                 NULL, 0x0, NULL, HFILL }},
7261         { &hf_bcp_bpdu_fcs_present,
7262             { "LAN FCS present", "bcp_bpdu.flags.fcs_present", FT_BOOLEAN, 8,
7263                 TFS(&tfs_yes_no), BCP_FCS_PRESENT, NULL, HFILL }},
7264         { &hf_bcp_bpdu_zeropad,
7265             { "802.3 pad zero-filled", "bcp_bpdu.flags.zeropad", FT_BOOLEAN, 8,
7266                 TFS(&tfs_yes_no), BCP_ZEROPAD, NULL, HFILL }},
7267         { &hf_bcp_bpdu_bcontrol,
7268             { "Bridge control", "bcp_bpdu.flags.bcontrol", FT_BOOLEAN, 8,
7269                 TFS(&tfs_yes_no), BCP_IS_BCONTROL, NULL, HFILL }},
7270         { &hf_bcp_bpdu_pads,
7271             { "Pads", "bcp_bpdu.pads", FT_UINT8, BASE_DEC,
7272                 NULL, BCP_PADS_MASK, NULL, HFILL }},
7273         { &hf_bcp_bpdu_mac_type,
7274             { "MAC Type", "bcp_bpdu.mac_type", FT_UINT8, BASE_DEC,
7275                 VALS(bcp_bpdu_mac_type_vals), 0x0, NULL, HFILL }},
7276         { &hf_bcp_bpdu_pad,
7277             { "Pad", "bcp_bpdu.pad", FT_BYTES, BASE_NONE,
7278                 NULL, 0x0, NULL, HFILL }},
7279     };
7280 
7281     static gint *ett[] = {
7282         &ett_bcp_bpdu,
7283         &ett_bcp_bpdu_flags,
7284     };
7285 
7286     proto_bcp_bpdu = proto_register_protocol("PPP Bridging Control Protocol Bridged PDU",
7287         "PPP BCP BPDU", "bcp_bpdu");
7288     proto_register_field_array(proto_bcp_bpdu, hf, array_length(hf));
7289     proto_register_subtree_array(ett, array_length(ett));
7290 }
7291 
7292 void
proto_reg_handoff_bcp_bpdu(void)7293 proto_reg_handoff_bcp_bpdu(void)
7294 {
7295     dissector_handle_t bcp_bpdu_handle;
7296 
7297     eth_withfcs_handle    = find_dissector_add_dependency("eth_withfcs", proto_bcp_bpdu);
7298     eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_bcp_bpdu);
7299 
7300     bcp_bpdu_handle = create_dissector_handle(dissect_bcp_bpdu, proto_bcp_bpdu);
7301 
7302     dissector_add_uint("ppp.protocol", PPP_BCP_BPDU, bcp_bpdu_handle);
7303 }
7304 
7305 void
proto_register_bcp_ncp(void)7306 proto_register_bcp_ncp(void)
7307 {
7308     static hf_register_info hf[] = {
7309         { &hf_bcp_ncp_opt_type,
7310             { "Type", "bcp_ncp.lcp.opt.type", FT_UINT8, BASE_DEC,
7311                 NULL, 0x0, NULL, HFILL } },
7312         { &hf_bcp_ncp_opt_length,
7313             { "Length", "bcp_ncp.lcp.opt.length", FT_UINT8, BASE_DEC,
7314                 NULL, 0x0, NULL, HFILL } },
7315         { &hf_bcp_ncp_lan_seg_no,
7316             { "LAN Segment Number", "bcp_ncp.lcp.lan_seg_no", FT_UINT16, BASE_DEC,
7317                 NULL, 0xfff0, NULL, HFILL } },
7318         { &hf_bcp_ncp_bridge_no,
7319             { "Bridge Number", "bcp_ncp.lcp.bridge_no", FT_UINT16, BASE_DEC,
7320                 NULL, 0x000f, NULL, HFILL } },
7321        { &hf_bcp_ncp_tinygram_comp,
7322             { "Tinygram-Compression", "bcp_ncp.lcp.tinygram_comp", FT_BOOLEAN, 8,
7323                 TFS(&tfs_enabled_disabled), 0x0, NULL, HFILL } },
7324        { &hf_bcp_ncp_mac,
7325             { "MAC Address", "bcp_ncp.lcp.mac_addres", FT_ETHER, BASE_NONE,
7326                 NULL, 0x0, NULL, HFILL } },
7327        { &hf_bcp_ncp_mac_l,
7328             { "L bit", "bcp_ncp.lcp.mac_l", FT_UINT48, BASE_HEX,
7329                 NULL, G_GUINT64_CONSTANT(0x0200000000), NULL, HFILL } },
7330        { &hf_bcp_ncp_mac_m,
7331            { "M bit", "bcp_ncp.lcp.mac_addre", FT_UINT48, BASE_HEX,
7332                 NULL, G_GUINT64_CONSTANT(0x0100000000), NULL, HFILL } },
7333        { &hf_bcp_ncp_stp_prot,
7334            { "Protocol", "bcp_ncp.lcp.stp_protocol", FT_UINT8, BASE_DEC,
7335                 VALS(bcp_ncp_stp_prot_vals), 0x0, NULL, HFILL } },
7336        { &hf_bcp_ncp_ieee_802_tagged_frame,
7337            { "IEEE-802-Tagged-Frame", "bcp_ncp.ieee_802_tagged_frame", FT_BOOLEAN, 8,
7338                 TFS(&tfs_enabled_disabled), 0x0, NULL, HFILL } },
7339 
7340     };
7341 
7342     static gint *ett[] = {
7343         &ett_bcp_ncp,
7344         &ett_bcp_ncp_options,
7345         &ett_bcp_ncp_ieee_802_tagged_frame_opt,
7346         &ett_bcp_ncp_management_inline_opt,
7347         &ett_bcp_ncp_bcp_ind_opt,
7348         &ett_bcp_ncp_bridge_id_opt,
7349         &ett_bcp_ncp_line_id_opt,
7350         &ett_bcp_ncp_mac_sup_opt,
7351         &ett_bcp_ncp_tinygram_comp_opt,
7352         &ett_bcp_ncp_lan_id_opt,
7353         &ett_bcp_ncp_mac_addr_opt,
7354         &ett_bcp_ncp_stp_opt
7355     };
7356 
7357     proto_bcp_ncp = proto_register_protocol("PPP Bridging Control Protocol Network Control Protocol", "PPP BCP NCP", "bcp_ncp");
7358     proto_register_field_array(proto_bcp_ncp, hf, array_length(hf));
7359     proto_register_subtree_array(ett, array_length(ett));
7360 
7361     bcp_ncp_option_table = register_dissector_table("bcp_ncp.option", "PPP BCP NCP Options", proto_bcp_ncp, FT_UINT8, BASE_DEC);
7362 
7363     /* Register BCP NCP options as their own protocols so we can get the name of the option */
7364     proto_bcp_ncp_option_bridge_id = proto_register_protocol_in_name_only("Bridge-Identification", "Bridge-Identification", "bcp_ncp.opt.bridge_id", proto_bcp_ncp, FT_BYTES);
7365     proto_bcp_ncp_option_line_id = proto_register_protocol_in_name_only("Line-Identification", "Line-Identification", "bcp_ncp.opt.line_id", proto_bcp_ncp, FT_BYTES);
7366     proto_bcp_ncp_option_mac_sup = proto_register_protocol_in_name_only("MAC-Support", "MAC-Support", "bcp_ncp.opt.mac_sup", proto_bcp_ncp, FT_BYTES);
7367     proto_bcp_ncp_option_tinygram_comp = proto_register_protocol_in_name_only("Tinygram-Compression", "Tinygram-Compression", "bcp_ncp.opt.tinygram_comp", proto_bcp_ncp, FT_BYTES);
7368     proto_bcp_ncp_option_lan_id = proto_register_protocol_in_name_only("LAN-Identification (obsoleted)", "LAN-Identification (obsoleted)", "bcp_ncp.opt.lan_id", proto_bcp_ncp, FT_BYTES);
7369     proto_bcp_ncp_option_mac_addr = proto_register_protocol_in_name_only("MAC-Address", "MAC-Address", "bcp_ncp.opt.mac_addr", proto_bcp_ncp, FT_BYTES);
7370     proto_bcp_ncp_option_stp = proto_register_protocol_in_name_only("Spanning-Tree-Protocol (old formatted)", "Spanning-Tree-Protocol (old formatted)", "bcp_ncp.opt.stp", proto_bcp_ncp, FT_BYTES);
7371     proto_bcp_ncp_option_ieee_802_tagged_frame = proto_register_protocol_in_name_only("IEEE 802 Tagged Frame", "IEEE 802 Tagged Frame", "bcp_ncp.opt.ieee_802_tagged_frame", proto_bcp_ncp, FT_BYTES);
7372     proto_bcp_ncp_option_management_inline = proto_register_protocol_in_name_only("Management Inline", "Management Inline", "bcp_ncp.opt.management_inline", proto_bcp_ncp, FT_BYTES);
7373     proto_bcp_ncp_option_bcp_ind = proto_register_protocol_in_name_only("Bridge Control Packet Indicator", "Bridge Control Packet Indicator", "bcp_ncp.opt.bcp_ind", proto_bcp_ncp, FT_BYTES);
7374 }
7375 
7376 void
proto_reg_handoff_bcp_ncp(void)7377 proto_reg_handoff_bcp_ncp(void)
7378 {
7379     dissector_handle_t bcp_ncp_handle;
7380 
7381     bcp_ncp_handle = create_dissector_handle(dissect_bcp_ncp, proto_bcp_ncp);
7382 
7383     dissector_add_uint("ppp.protocol", PPP_BCP_NCP, bcp_ncp_handle);
7384 
7385     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_BRIDGE_ID, create_dissector_handle( dissect_bcp_ncp_bridge_id, proto_bcp_ncp_option_bridge_id ));
7386     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_LINE_ID, create_dissector_handle( dissect_bcp_ncp_line_id, proto_bcp_ncp_option_line_id ));
7387     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MAC_SUPPORT, create_dissector_handle( dissect_bcp_ncp_mac_sup, proto_bcp_ncp_option_mac_sup ));
7388     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_TINYGRAM_COMP, create_dissector_handle( dissect_bcp_ncp_tinygram_comp, proto_bcp_ncp_option_tinygram_comp ));
7389     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_LAN_ID, create_dissector_handle( dissect_bcp_ncp_lan_id, proto_bcp_ncp_option_lan_id ));
7390     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MAC_ADDRESS, create_dissector_handle( dissect_bcp_ncp_mac_addr, proto_bcp_ncp_option_mac_addr ));
7391     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_STP, create_dissector_handle( dissect_bcp_ncp_stp, proto_bcp_ncp_option_stp ));
7392     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_IEEE_802_TAGGED_FRAME, create_dissector_handle( dissect_bcp_ncp_ieee_802_tagged_frame, proto_bcp_ncp_option_ieee_802_tagged_frame ));
7393     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MANAGEMENT_INLINE, create_dissector_handle( dissect_bcp_ncp_management_inline, proto_bcp_ncp_option_management_inline ));
7394     dissector_add_uint("bcp_ncp.option", CI_BCPNCP_BCP_IND, create_dissector_handle( dissect_bcp_ncp_bcp_ncp_bcp_ind, proto_bcp_ncp_option_bcp_ind ));
7395 }
7396 
7397 void
proto_register_osinlcp(void)7398 proto_register_osinlcp(void)
7399 {
7400     static hf_register_info hf[] = {
7401         { &hf_osinlcp_opt_type,
7402         { "Type", "osinlcp.opt.type", FT_UINT8, BASE_DEC,
7403         NULL, 0x0, NULL, HFILL } },
7404         { &hf_osinlcp_opt_length,
7405         { "Length", "osinlcp.opt.length", FT_UINT8, BASE_DEC,
7406         NULL, 0x0, NULL, HFILL } },
7407         { &hf_osinlcp_opt_alignment,
7408         { "Alignment", "osinlcp.opt.alignment", FT_UINT8, BASE_DEC,
7409         NULL, 0x0, NULL, HFILL } }
7410     };
7411 
7412     static gint *ett[] = {
7413         &ett_osinlcp,
7414         &ett_osinlcp_options,
7415         &ett_osinlcp_align_npdu_opt
7416     };
7417 
7418     proto_osinlcp = proto_register_protocol("PPP OSI Network Layer Control Protocol", "PPP OSINLCP", "osinlcp");
7419     proto_register_field_array(proto_osinlcp, hf, array_length(hf));
7420     proto_register_subtree_array(ett, array_length(ett));
7421 
7422     osinlcp_option_table = register_dissector_table("osinlcp.option", "PPP OSINLCP Options", proto_osinlcp, FT_UINT8, BASE_DEC);
7423 
7424     /* Register OSINLCP options as their own protocols so we can get the name of the option */
7425     proto_osinlcp_option_align_npdu = proto_register_protocol_in_name_only("Align-NPDU", "Align-NPDU", "osinlcp.opt.def_pid", proto_osinlcp, FT_BYTES);
7426 }
7427 
7428 
7429 void
proto_reg_handoff_osinlcp(void)7430 proto_reg_handoff_osinlcp(void)
7431 {
7432     dissector_handle_t osinlcp_handle;
7433 
7434     osinlcp_handle = create_dissector_handle(dissect_osinlcp, proto_osinlcp);
7435     dissector_add_uint("ppp.protocol", PPP_OSINLCP, osinlcp_handle);
7436 
7437     /*
7438      * See above comment about NDISWAN for an explanation of why we're
7439      * registering with the "ethertype" dissector table.
7440      */
7441     dissector_add_uint("ethertype", PPP_OSINLCP, osinlcp_handle);
7442 
7443     dissector_add_uint("osinlcp.option", CI_OSINLCP_ALIGN_NPDU, create_dissector_handle( dissect_osinlcp_align_npdu_opt, proto_osinlcp_option_align_npdu ));
7444 }
7445 
7446 void
proto_register_ccp(void)7447 proto_register_ccp(void)
7448 {
7449     static hf_register_info hf[] = {
7450         { &hf_ccp_opt_type,
7451             { "Type", "ccp.opt.type", FT_UINT8, BASE_DEC,
7452                 NULL, 0x0, NULL, HFILL }},
7453         { &hf_ccp_opt_length,
7454             { "Length", "ccp.opt.length", FT_UINT8, BASE_DEC,
7455                 NULL, 0x0, NULL, HFILL }},
7456         { &hf_ccp_opt_oui,
7457             { "OUI", "ccp.opt.oui", FT_UINT24, BASE_OUI,
7458                 NULL, 0x0, NULL, HFILL }},
7459         { &hf_ccp_opt_subtype,
7460             { "Subtype", "ccp.opt.subtype", FT_UINT8, BASE_DEC_HEX,
7461                 NULL, 0x0, NULL, HFILL }},
7462         { &hf_ccp_opt_history_count,
7463             { "History Count", "ccp.opt.history_count", FT_UINT16, BASE_DEC,
7464                 NULL, 0x0, "The maximum number of compression histories",
7465                 HFILL }},
7466         { &hf_ccp_opt_cm,
7467             { "Check Mode Field", "ccp.opt.cm", FT_UINT8, BASE_DEC,
7468                 NULL, 0x0, NULL, HFILL }},
7469         { &hf_ccp_opt_cm_reserved,
7470             { "Reserved", "ccp.opt.cm.reserved", FT_UINT8, BASE_DEC,
7471                 NULL, 0xF8, NULL, HFILL }},
7472         { &hf_ccp_opt_cm_check_mode,
7473             { "Check Mode", "ccp.opt.cm.check_mode", FT_UINT8, BASE_DEC,
7474                 VALS(stac_checkmode_vals), 0x07, NULL, HFILL }},
7475         { &hf_ccp_opt_supported_bits,
7476             { "Supported Bits", "ccp.opt.supported_bits", FT_UINT32, BASE_HEX,
7477                 NULL, 0x0, NULL, HFILL }},
7478         { &hf_ccp_opt_supported_bits_h,
7479             { "H", "ccp.opt.supported_bits.h", FT_BOOLEAN, 32,
7480                 TFS(&ccp_mppe_h_tfs), MPPE_SUPPORTED_BITS_H, NULL, HFILL }},
7481         { &hf_ccp_opt_supported_bits_m,
7482             { "M", "ccp.opt.supported_bits.m", FT_BOOLEAN, 32,
7483                 TFS(&ccp_mppe_m_tfs), MPPE_SUPPORTED_BITS_M, NULL, HFILL }},
7484         { &hf_ccp_opt_supported_bits_s,
7485             { "S", "ccp.opt.supported_bits.s", FT_BOOLEAN, 32,
7486                 TFS(&ccp_mppe_s_tfs), MPPE_SUPPORTED_BITS_S, NULL, HFILL }},
7487         { &hf_ccp_opt_supported_bits_l,
7488             { "L", "ccp.opt.supported_bits.l", FT_BOOLEAN, 32,
7489                 TFS(&ccp_mppe_l_tfs), MPPE_SUPPORTED_BITS_L, NULL, HFILL }},
7490         { &hf_ccp_opt_supported_bits_d,
7491             { "D", "ccp.opt.supported_bits.d", FT_BOOLEAN, 32,
7492                 TFS(&ccp_mppe_d_tfs), MPPE_SUPPORTED_BITS_D, NULL, HFILL }},
7493         { &hf_ccp_opt_supported_bits_c,
7494             { "C", "ccp.opt.supported_bits.c", FT_BOOLEAN, 32,
7495                 TFS(&ccp_mppe_c_tfs), MPPC_SUPPORTED_BITS_C, NULL, HFILL }},
7496         { &hf_ccp_opt_history,
7497             { "History", "ccp.opt.history", FT_UINT8, BASE_DEC, NULL, 0x0,
7498                 "Maximum size of the compression history in powers of 2",
7499                 HFILL }},
7500         { &hf_ccp_opt_version,
7501             { "Version", "ccp.opt.version", FT_BYTES, BASE_NONE,
7502                 NULL, 0x0, NULL, HFILL }},
7503         { &hf_ccp_opt_vd,
7504             { "Vers/Dict", "ccp.opt.vd", FT_UINT8, BASE_HEX,
7505                 NULL, 0x0, NULL, HFILL }},
7506         { &hf_ccp_opt_vd_vers,
7507             { "Vers", "ccp.opt.vd.vers", FT_UINT8, BASE_DEC,
7508                 NULL, 0xE0, NULL, HFILL }},
7509         { &hf_ccp_opt_vd_dict,
7510             { "Dict", "ccp.opt.vd.dict", FT_UINT8, BASE_DEC, NULL,
7511                 0x1F, "The size in bits of the largest code used", HFILL }},
7512         { &hf_ccp_opt_check_mode,
7513             { "Check Mode", "ccp.opt.check_mode", FT_UINT8, BASE_DEC,
7514                 VALS(lzsdcp_checkmode_vals), 0x0, NULL, HFILL }},
7515         { &hf_ccp_opt_process_mode,
7516             { "Process Mode", "ccp.opt.process_mode", FT_UINT8, BASE_DEC,
7517                 VALS(lzsdcp_processmode_vals), 0x0, NULL, HFILL }},
7518         { &hf_ccp_opt_fe,
7519             { "Features", "ccp.opt.fe", FT_UINT8, BASE_DEC,
7520                 NULL, 0xC0, NULL, HFILL }},
7521         { &hf_ccp_opt_p,
7522             { "Packet by Packet flag", "ccp.opt.p", FT_BOOLEAN, 8,
7523                 TFS(&tfs_enabled_disabled), 0x20, NULL, HFILL }},
7524         { &hf_ccp_opt_History,
7525             { "History", "ccp.opt.History", FT_UINT8, BASE_DEC,
7526                 NULL, 0x1F, NULL, HFILL }},
7527         { &hf_ccp_opt_contexts,
7528             { "# Contexts", "ccp.opt.contexts", FT_UINT8, BASE_DEC,
7529                 NULL, 0x0, NULL, HFILL }},
7530         { &hf_ccp_opt_mode,
7531             { "Mode", "ccp.opt.mode", FT_UINT8, BASE_DEC,
7532                 VALS(dce_mode_vals), 0x0, NULL, HFILL }},
7533         { &hf_ccp_opt_window,
7534             { "Window", "ccp.opt.window", FT_UINT8, BASE_DEC,
7535                 NULL, 0xF0, NULL, HFILL }},
7536         { &hf_ccp_opt_method,
7537             { "Method", "ccp.opt.method", FT_UINT8, BASE_DEC,
7538                 VALS(deflate_method_vals), 0x0F, NULL, HFILL }},
7539         { &hf_ccp_opt_mbz,
7540             { "MBZ", "ccp.opt.mbz", FT_UINT8, BASE_DEC,
7541                 NULL, 0xFC, NULL, HFILL }},
7542         { &hf_ccp_opt_chk,
7543             { "Chk", "ccp.opt.chk", FT_UINT8, BASE_DEC,
7544                 VALS(deflate_chk_vals), 0x03, NULL, HFILL }},
7545         { &hf_ccp_opt_mode_dictcount,
7546             { "Mode/Dictionary Count", "ccp.opt.mode_dictcount", FT_UINT16,
7547                 BASE_DEC | BASE_RANGE_STRING, RVALS(v44lzjh_mode_dict_rvals),
7548                 0x0, NULL, HFILL }},
7549         { &hf_ccp_opt_dict_size,
7550             { "Dictionary Size", "ccp.opt.dict_size", FT_UINT16, BASE_DEC,
7551                 NULL, 0x0, NULL, HFILL }},
7552         { &hf_ccp_opt_history_length,
7553             { "History Length", "ccp.opt.history_length", FT_UINT16, BASE_DEC,
7554                 NULL, 0x0, NULL, HFILL }},
7555         { &hf_ccp_opt_data,
7556             { "Data", "ccp.opt.data", FT_BYTES, BASE_NONE,
7557                 NULL, 0x0, NULL, HFILL }},
7558     };
7559     static gint *ett[] = {
7560         &ett_ccp,
7561         &ett_ccp_options,
7562         &ett_ccp_oui_opt,
7563         &ett_ccp_predict1_opt,
7564         &ett_ccp_predict2_opt,
7565         &ett_ccp_puddle_opt,
7566         &ett_ccp_hpppc_opt,
7567         &ett_ccp_stac_opt,
7568         &ett_ccp_stac_opt_check_mode,
7569         &ett_ccp_mppe_opt,
7570         &ett_ccp_mppe_opt_supp_bits,
7571         &ett_ccp_gfza_opt,
7572         &ett_ccp_v42bis_opt,
7573         &ett_ccp_bsdcomp_opt,
7574         &ett_ccp_lzsdcp_opt,
7575         &ett_ccp_mvrca_opt,
7576         &ett_ccp_dce_opt,
7577         &ett_ccp_deflate_opt,
7578         &ett_ccp_v44lzjh_opt
7579     };
7580 
7581     proto_ccp = proto_register_protocol("PPP Compression Control Protocol", "PPP CCP", "ccp");
7582     proto_register_field_array(proto_ccp, hf, array_length(hf));
7583     proto_register_subtree_array(ett, array_length(ett));
7584 
7585     ccp_option_table = register_dissector_table("ccp.option", "PPP CCP Options", proto_ccp, FT_UINT8, BASE_DEC);
7586 
7587     /* Register CCP options as their own protocols so we can get the name of the option */
7588     proto_ccp_option_oui = proto_register_protocol_in_name_only("OUI", "OUI", "ccp.opt_oui", proto_ccp, FT_BYTES);
7589     proto_ccp_option_predict1 = proto_register_protocol_in_name_only("Predictor type 1", "Predictor type 1", "ccp.opt.predict1", proto_ccp, FT_BYTES);
7590     proto_ccp_option_predict2 = proto_register_protocol_in_name_only("Predictor type 2", "Predictor type 2", "ccp.opt.predict2", proto_ccp, FT_BYTES);
7591     proto_ccp_option_puddle = proto_register_protocol_in_name_only("Puddle Jumper", "Puddle Jumper", "ccp.opt.puddle", proto_ccp, FT_BYTES);
7592     proto_ccp_option_hpppc = proto_register_protocol_in_name_only("Hewlett-Packard PPC", "Hewlett-Packard PPC", "ccp.opt.hpppc", proto_ccp, FT_BYTES);
7593     proto_ccp_option_stac = proto_register_protocol_in_name_only("Stac Electronics LZS", "Stac Electronics LZS", "ccp.opt.stac", proto_ccp, FT_BYTES);
7594     proto_ccp_option_stac_ascend = proto_register_protocol_in_name_only("Stac Electronics LZS (Ascend Proprietary version)", "Stac Electronics LZS (Ascend Proprietary version)", "ccp.opt.stac_ascend", proto_ccp, FT_BYTES);
7595     proto_ccp_option_mppe = proto_register_protocol_in_name_only("Microsoft PPE/PPC", "Microsoft PPE/PPC", "ccp.opt.mppe", proto_ccp, FT_BYTES);
7596     proto_ccp_option_gfza = proto_register_protocol_in_name_only("Gandalf FZA", "Gandalf FZA", "ccp.opt.gfza", proto_ccp, FT_BYTES);
7597     proto_ccp_option_v42bis = proto_register_protocol_in_name_only("V.42bis compression", "V.42bis compression", "ccp.opt.v42bis", proto_ccp, FT_BYTES);
7598     proto_ccp_option_bsdcomp = proto_register_protocol_in_name_only("BSD LZW Compress", "BSD LZW Compress", "ccp.opt.bsdcomp", proto_ccp, FT_BYTES);
7599     proto_ccp_option_lzsdcp = proto_register_protocol_in_name_only("LZS-DCP", "LZS-DCP", "ccp.opt.lzsdcp", proto_ccp, FT_BYTES);
7600     proto_ccp_option_mvrca = proto_register_protocol_in_name_only("MVRCA (Magnalink)", "MVRCA (Magnalink)", "ccp.opt.mvrca", proto_ccp, FT_BYTES);
7601     proto_ccp_option_dce = proto_register_protocol_in_name_only("PPP for Data Compression in Data Circuit-Terminating Equipment (DCE)", "PPP for Data Compression in Data Circuit-Terminating Equipment (DCE)", "ccp.opt.dce", proto_ccp, FT_BYTES);
7602     proto_ccp_option_deflate = proto_register_protocol_in_name_only("Deflate", "Deflate", "ccp.opt.deflate", proto_ccp, FT_BYTES);
7603     proto_ccp_option_v44lzjh = proto_register_protocol_in_name_only("V.44/LZJH compression", "V.44/LZJH compression", "ccp.opt.v44lzjh", proto_ccp, FT_BYTES);
7604 }
7605 
7606 void
proto_reg_handoff_ccp(void)7607 proto_reg_handoff_ccp(void)
7608 {
7609     dissector_handle_t ccp_handle;
7610 
7611     ccp_handle = create_dissector_handle(dissect_ccp, proto_ccp);
7612     dissector_add_uint("ppp.protocol", PPP_CCP, ccp_handle);
7613 
7614     /*
7615      * See above comment about NDISWAN for an explanation of why we're
7616      * registering with the "ethertype" dissector table.
7617      */
7618     dissector_add_uint("ethertype", PPP_CCP, ccp_handle);
7619 
7620     dissector_add_uint("ccp.option", CI_CCP_OUI, create_dissector_handle( dissect_ccp_oui_opt, proto_ccp_option_oui ));
7621     dissector_add_uint("ccp.option", CI_CCP_PREDICT1, create_dissector_handle( dissect_ccp_predict1_opt, proto_ccp_option_predict1 ));
7622     dissector_add_uint("ccp.option", CI_CCP_PREDICT2, create_dissector_handle( dissect_ccp_predict2_opt, proto_ccp_option_predict2 ));
7623     dissector_add_uint("ccp.option", CI_CCP_PUDDLE, create_dissector_handle( dissect_ccp_puddle_opt, proto_ccp_option_puddle ));
7624     dissector_add_uint("ccp.option", CI_CCP_HPPPC, create_dissector_handle( dissect_ccp_hpppc_opt, proto_ccp_option_hpppc ));
7625     dissector_add_uint("ccp.option", CI_CCP_STAC, create_dissector_handle( dissect_ccp_stac_opt, proto_ccp_option_stac ));
7626     dissector_add_uint("ccp.option", CI_CCP_MPPE, create_dissector_handle( dissect_ccp_mppe_opt, proto_ccp_option_mppe ));
7627     dissector_add_uint("ccp.option", CI_CCP_GFZA, create_dissector_handle( dissect_ccp_gfza_opt, proto_ccp_option_gfza ));
7628     dissector_add_uint("ccp.option", CI_CCP_V42BIS, create_dissector_handle( dissect_ccp_v42bis_opt, proto_ccp_option_v42bis ));
7629     dissector_add_uint("ccp.option", CI_CCP_BSDLZW, create_dissector_handle( dissect_ccp_bsdcomp_opt, proto_ccp_option_bsdcomp ));
7630     dissector_add_uint("ccp.option", CI_CCP_LZSDCP, create_dissector_handle( dissect_ccp_lzsdcp_opt, proto_ccp_option_lzsdcp ));
7631     dissector_add_uint("ccp.option", CI_CCP_MVRCA, create_dissector_handle( dissect_ccp_mvrca_opt, proto_ccp_option_mvrca ));
7632     dissector_add_uint("ccp.option", CI_CCP_DCE, create_dissector_handle( dissect_ccp_dce_opt, proto_ccp_option_dce ));
7633     dissector_add_uint("ccp.option", CI_CCP_DEFLATE, create_dissector_handle( dissect_ccp_deflate_opt, proto_ccp_option_deflate ));
7634     dissector_add_uint("ccp.option", CI_CCP_V44LZJH, create_dissector_handle( dissect_ccp_v44lzjh_opt, proto_ccp_option_v44lzjh ));
7635 }
7636 
7637 void
proto_register_cbcp(void)7638 proto_register_cbcp(void)
7639 {
7640     static hf_register_info hf[] = {
7641       { &hf_cbcp_opt_type, { "Type", "cbcp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7642       { &hf_cbcp_opt_length, { "Length", "cbcp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7643       /* Generated from convert_proto_tree_add_text.pl */
7644       { &hf_cbcp_callback_delay, { "Callback delay", "cbcp.callback_delay", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7645       { &hf_cbcp_address_type, { "Address Type", "cbcp.address_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7646       { &hf_cbcp_address, { "Address", "cbcp.address", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7647       { &hf_cbcp_no_callback, { "No callback", "cbcp.no_callback", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7648     };
7649 
7650     static gint *ett[] = {
7651         &ett_cbcp,
7652         &ett_cbcp_options,
7653         &ett_cbcp_callback_opt,
7654         &ett_cbcp_callback_opt_addr,
7655         &ett_cbcp_no_callback,
7656         &ett_cbcp_callback_user,
7657         &ett_cbcp_callback_admin,
7658         &ett_cbcp_callback_list,
7659     };
7660 
7661     static ei_register_info ei[] = {
7662         { &ei_cbcp_address, { "cbcp.address.malformed", PI_MALFORMED, PI_ERROR, "Address runs past end of option", EXPFILL }},
7663     };
7664 
7665     expert_module_t* expert_cbcp;
7666 
7667     proto_cbcp = proto_register_protocol("PPP Callback Control Protocol", "PPP CBCP", "cbcp");
7668     proto_register_field_array(proto_cbcp, hf, array_length(hf));
7669     proto_register_subtree_array(ett, array_length(ett));
7670     expert_cbcp = expert_register_protocol(proto_cbcp);
7671     expert_register_field_array(expert_cbcp, ei, array_length(ei));
7672 
7673     cbcp_option_table = register_dissector_table("cbcp.option", "PPP CBCP Options", proto_cbcp, FT_UINT8, BASE_DEC);
7674 
7675     /* Register CBCP options as their own protocols so we can get the name of the option */
7676     proto_cbcp_option_no_callback = proto_register_protocol_in_name_only("No callback", "No callback", "cbcp.opt.no_callback", proto_cbcp, FT_BYTES);
7677     proto_cbcp_option_callback_user = proto_register_protocol_in_name_only("Callback to a user-specified number", "Callback to a user-specified number", "cbcp.opt.callback_user", proto_cbcp, FT_BYTES);
7678     proto_cbcp_option_callback_admin = proto_register_protocol_in_name_only("Callback to a pre-specified or admin-specified number", "Callback to a pre-specified or admin-specified number", "cbcp.opt.callback_admin", proto_cbcp, FT_BYTES);
7679     proto_cbcp_option_callback_list = proto_register_protocol_in_name_only("Callback to any of a list of numbers", "Callback to any of a list of numbers", "cbcp.opt.callback_list", proto_cbcp, FT_BYTES);
7680 }
7681 
7682 void
proto_reg_handoff_cbcp(void)7683 proto_reg_handoff_cbcp(void)
7684 {
7685     dissector_handle_t cbcp_handle;
7686 
7687     cbcp_handle = create_dissector_handle(dissect_cbcp, proto_cbcp);
7688     dissector_add_uint("ppp.protocol", PPP_CBCP, cbcp_handle);
7689 
7690     /*
7691      * See above comment about NDISWAN for an explanation of why we're
7692      * registering with the "ethertype" dissector table.
7693      */
7694     dissector_add_uint("ethertype", PPP_CBCP, cbcp_handle);
7695 
7696     dissector_add_uint("cbcp.option", CI_CBCP_NO_CALLBACK, create_dissector_handle( dissect_cbcp_no_callback_opt, proto_cbcp_option_no_callback ));
7697     dissector_add_uint("cbcp.option", CI_CBCP_CB_USER, create_dissector_handle( dissect_cbcp_callback_user_opt, proto_cbcp_option_callback_user ));
7698     dissector_add_uint("cbcp.option", CI_CBCP_CB_PRE, create_dissector_handle( dissect_cbcp_callback_admin_opt, proto_cbcp_option_callback_admin ));
7699     dissector_add_uint("cbcp.option", CI_CBCP_CB_ANY, create_dissector_handle( dissect_cbcp_callback_list_opt, proto_cbcp_option_callback_list ));
7700 }
7701 
7702 void
proto_register_bacp(void)7703 proto_register_bacp(void)
7704 {
7705     static hf_register_info hf[] = {
7706       { &hf_bacp_opt_type, { "Type", "bacp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7707       { &hf_bacp_opt_length, { "Length", "bacp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7708       /* Generated from convert_proto_tree_add_text.pl */
7709       { &hf_bacp_magic_number, { "Magic number", "bacp.magic_number", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
7710       { &hf_bacp_link_speed, { "Link Speed", "bacp.link_speed", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_kbps, 0x0, NULL, HFILL }},
7711       { &hf_bacp_link_type, { "Link Type", "bacp.link_type", FT_UINT8, BASE_DEC, VALS(bap_link_type_vals), 0x0, NULL, HFILL }},
7712     };
7713 
7714     static gint *ett[] = {
7715         &ett_bacp,
7716         &ett_bacp_options,
7717         &ett_bacp_favored_peer_opt
7718     };
7719 
7720     proto_bacp = proto_register_protocol("PPP Bandwidth Allocation Control Protocol", "PPP BACP", "bacp");
7721     proto_register_field_array(proto_bacp, hf, array_length(hf));
7722     proto_register_subtree_array(ett, array_length(ett));
7723 
7724     bacp_option_table = register_dissector_table("bacp.option", "PPP BACP Options", proto_bacp, FT_UINT8, BASE_DEC);
7725 
7726     /* Register BACP options as their own protocols so we can get the name of the option */
7727     proto_bacp_option_favored_peer = proto_register_protocol_in_name_only("Favored-Peer", "Favored-Peer", "bacp.opt.favored_peer", proto_bacp, FT_BYTES);
7728 }
7729 
7730 void
proto_reg_handoff_bacp(void)7731 proto_reg_handoff_bacp(void)
7732 {
7733     dissector_handle_t bacp_handle;
7734 
7735     bacp_handle = create_dissector_handle(dissect_bacp, proto_bacp);
7736     dissector_add_uint("ppp.protocol", PPP_BACP, bacp_handle);
7737 
7738     /*
7739      * See above comment about NDISWAN for an explanation of why we're
7740      * registering with the "ethertype" dissector table.
7741      */
7742     dissector_add_uint("ethertype", PPP_BACP, bacp_handle);
7743 
7744     dissector_add_uint("bacp.option", CI_BACP_FAVORED_PEER, create_dissector_handle( dissect_bacp_favored_peer_opt, proto_bacp_option_favored_peer ));
7745 }
7746 
7747 void
proto_register_bap(void)7748 proto_register_bap(void)
7749 {
7750     static hf_register_info hf[] = {
7751       { &hf_bap_opt_type, { "Type", "bap.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7752       { &hf_bap_opt_length, { "Length", "bap.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7753       /* Generated from convert_proto_tree_add_text.pl */
7754       { &hf_bap_sub_option_type, { "Sub-Option Type", "bap.sub_option_type", FT_UINT8, BASE_DEC, VALS(bap_phone_delta_subopt_vals), 0x0, NULL, HFILL }},
7755       { &hf_bap_sub_option_length, { "Sub-Option Length", "bap.sub_option_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7756       { &hf_bap_unique_digit, { "Unique Digit", "bap.unique_digit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7757       { &hf_bap_subscriber_number, { "Subscriber Number", "bap.subscriber_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7758       { &hf_bap_phone_number_sub_address, { "Phone Number Sub Address", "bap.phone_number_sub_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7759       { &hf_bap_unknown_option_data, { "Unknown", "bap.unknown_option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7760       { &hf_bap_reason, { "Reason", "bap.reason", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
7761       { &hf_bap_link_discriminator, { "Link Discriminator", "bap.link_discriminator", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
7762       { &hf_bap_call_status, { "Status", "bap.call_status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &q931_cause_code_vals_ext, 0x0, NULL, HFILL }},
7763       { &hf_bap_call_action, { "Action", "bap.call_action", FT_UINT8, BASE_HEX, VALS(bap_call_status_opt_action_vals), 0x0, NULL, HFILL }},
7764       { &hf_bap_type, { "Type", "bap.type", FT_UINT8, BASE_HEX, VALS(bap_vals), 0x0, NULL, HFILL }},
7765       { &hf_bap_identifier, { "Identifier", "bap.identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
7766       { &hf_bap_length, { "Length", "bap.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
7767       { &hf_bap_response_code, { "Response Code", "bap.response_code", FT_UINT8, BASE_HEX, VALS(bap_resp_code_vals), 0x0, NULL, HFILL }},
7768     };
7769 
7770     static gint *ett[] = {
7771         &ett_bap,
7772         &ett_bap_options,
7773         &ett_bap_link_type_opt,
7774         &ett_bap_phone_delta_opt,
7775         &ett_bap_phone_delta_subopt,
7776         &ett_bap_call_status_opt,
7777         &ett_bap_no_phone_opt,
7778         &ett_bap_reason_opt,
7779         &ett_bap_link_disc_opt,
7780     };
7781 
7782     static ei_register_info ei[] = {
7783         { &ei_bap_sub_option_length, { "bap.sub_option_length.invalid", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
7784     };
7785 
7786     expert_module_t* expert_bap;
7787 
7788     proto_bap = proto_register_protocol("PPP Bandwidth Allocation Protocol", "PPP BAP", "bap");
7789     proto_register_field_array(proto_bap, hf, array_length(hf));
7790     proto_register_subtree_array(ett, array_length(ett));
7791     expert_bap = expert_register_protocol(proto_bap);
7792     expert_register_field_array(expert_bap, ei, array_length(ei));
7793 
7794     bap_option_table = register_dissector_table("bap.option", "PPP BAP Options", proto_bap, FT_UINT8, BASE_DEC);
7795 
7796     /* Register BAP options as their own protocols so we can get the name of the option */
7797     proto_bap_option_link_type = proto_register_protocol_in_name_only("Link Type", "Link Type", "bap.opt.link_type", proto_bap, FT_BYTES);
7798     proto_bap_option_phone_delta = proto_register_protocol_in_name_only("Phone Delta", "Phone Delta", "bap.opt.phone_delta", proto_bap, FT_BYTES);
7799     proto_bap_option_no_phone = proto_register_protocol_in_name_only("No Phone Number Needed", "No Phone Number Needed", "bap.opt.no_phone", proto_bap, FT_BYTES);
7800     proto_bap_option_reason = proto_register_protocol_in_name_only("Reason", "Reason", "bap.opt.reason", proto_bap, FT_BYTES);
7801     proto_bap_option_link_disc = proto_register_protocol_in_name_only("Link Discriminator", "Link Discriminator", "bap.opt.link_disc", proto_bap, FT_BYTES);
7802     proto_bap_option_call_status = proto_register_protocol_in_name_only("Call Status", "Call Status", "bap.opt.call_status", proto_bap, FT_BYTES);
7803 }
7804 
7805 void
proto_reg_handoff_bap(void)7806 proto_reg_handoff_bap(void)
7807 {
7808     dissector_handle_t bap_handle;
7809 
7810     bap_handle = create_dissector_handle(dissect_bap, proto_bap);
7811     dissector_add_uint("ppp.protocol", PPP_BAP, bap_handle);
7812 
7813     /*
7814      * See above comment about NDISWAN for an explanation of why we're
7815      * registering with the "ethertype" dissector table.
7816      */
7817     dissector_add_uint("ethertype", PPP_BAP, bap_handle);
7818 
7819     dissector_add_uint("bap.option", CI_BAP_LINK_TYPE, create_dissector_handle( dissect_bap_link_type_opt, proto_bap_option_link_type ));
7820     dissector_add_uint("bap.option", CI_BAP_PHONE_DELTA, create_dissector_handle( dissect_bap_phone_delta_opt, proto_bap_option_phone_delta ));
7821     dissector_add_uint("bap.option", CI_BAP_NO_PHONE_NUM_NEEDED, create_dissector_handle( dissect_bap_no_phone_opt, proto_bap_option_no_phone ));
7822     dissector_add_uint("bap.option", CI_BAP_REASON, create_dissector_handle( dissect_bap_reason_opt, proto_bap_option_reason ));
7823     dissector_add_uint("bap.option", CI_BAP_LINK_DISC, create_dissector_handle( dissect_bap_link_disc_opt, proto_bap_option_link_disc ));
7824     dissector_add_uint("bap.option", CI_BAP_CALL_STATUS, create_dissector_handle( dissect_bap_call_status_opt, proto_bap_option_call_status ));
7825 }
7826 
7827 void
proto_register_comp_data(void)7828 proto_register_comp_data(void)
7829 {
7830 #if 0 /* See dissect_comp_data() */
7831     static gint *ett[] = {
7832         &ett_comp_data
7833     };
7834 #endif
7835 
7836     proto_comp_data = proto_register_protocol("PPP Compressed Datagram",
7837         "PPP Comp", "comp_data");
7838 #if 0
7839     proto_register_subtree_array(ett, array_length(ett));
7840 #endif
7841 }
7842 
7843 void
proto_reg_handoff_comp_data(void)7844 proto_reg_handoff_comp_data(void)
7845 {
7846     dissector_handle_t comp_data_handle;
7847 
7848     comp_data_handle = create_dissector_handle(dissect_comp_data,
7849         proto_comp_data);
7850     dissector_add_uint("ppp.protocol", PPP_COMP, comp_data_handle);
7851 
7852     /*
7853      * See above comment about NDISWAN for an explanation of why we're
7854      * registering with the "ethertype" dissector table.
7855      */
7856     dissector_add_uint("ethertype", PPP_COMP, comp_data_handle);
7857 }
7858 
7859 void
proto_register_pap(void)7860 proto_register_pap(void)
7861 {
7862     static gint *ett[] = {
7863         &ett_pap,
7864         &ett_pap_data
7865     };
7866 
7867     static hf_register_info hf[] = {
7868         { &hf_pap_code,
7869             { "Code", "pap.code", FT_UINT8, BASE_DEC, VALS(pap_vals), 0x0,
7870                 "The Code field is one octet and identifies the type of PAP "
7871                 "packet", HFILL }},
7872         { &hf_pap_identifier,
7873             { "Identifier", "pap.identifier", FT_UINT8, BASE_DEC, NULL, 0x0,
7874                 "The Identifier field is one octet and aids in matching "
7875                 "requests and replies.", HFILL }},
7876         { &hf_pap_length,
7877             { "Length", "pap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7878                 "The Length field is two octets and indicates the length of "
7879                 "the PAP packet", HFILL }},
7880         { &hf_pap_data,
7881             { "Data", "pap.data", FT_NONE, BASE_NONE, NULL, 0x0,
7882                 "The format of the Data field is determined by the Code field",
7883                 HFILL }},
7884         { &hf_pap_peer_id_length,
7885             { "Peer-ID-Length", "pap.peer_id.length",
7886                 FT_UINT8, BASE_DEC, NULL, 0x0,
7887                 "The Peer-ID-Length field is one octet and indicates the "
7888                 "length of the Peer-ID field", HFILL }},
7889         { &hf_pap_peer_id,
7890             { "Peer-ID", "pap.peer_id", FT_STRING, BASE_NONE, NULL, 0x0,
7891                 "The Peer-ID field is zero or more octets and indicates the "
7892                 "name of the peer to be authenticated", HFILL }},
7893         { &hf_pap_password_length,
7894             { "Password-Length", "pap.password.length",
7895                 FT_UINT8, BASE_DEC, NULL, 0x0,
7896                 "The Password-Length field is one octet and indicates the "
7897                 "length of the Password field", HFILL }},
7898         { &hf_pap_password,
7899             { "Password", "pap.password", FT_STRING, BASE_NONE, NULL, 0x0,
7900                 "The Password field is zero or more octets and indicates the "
7901                 "password to be used for authentication", HFILL }},
7902         { &hf_pap_message_length,
7903             { "Message-Length", "pap.message.length",
7904                 FT_UINT8, BASE_DEC, NULL, 0x0,
7905                 "The Message-Length field is one octet and indicates the "
7906                 "length of the Message field", HFILL }},
7907         { &hf_pap_message,
7908             { "Message", "pap.message", FT_STRING, BASE_NONE, NULL, 0x0,
7909                 "The Message field is zero or more octets, and its contents "
7910                 "are implementation dependent.", HFILL }},
7911         { &hf_pap_stuff,
7912             { "stuff", "pap.stuff", FT_BYTES, BASE_NONE,
7913                 NULL, 0x0, NULL, HFILL }}
7914     };
7915 
7916     proto_pap = proto_register_protocol("PPP Password Authentication Protocol",
7917         "PPP PAP", "pap");
7918     proto_register_field_array(proto_pap, hf, array_length(hf));
7919     proto_register_subtree_array(ett, array_length(ett));
7920 }
7921 
7922 void
proto_reg_handoff_pap(void)7923 proto_reg_handoff_pap(void)
7924 {
7925     dissector_handle_t pap_handle;
7926 
7927     pap_handle = create_dissector_handle(dissect_pap, proto_pap);
7928     dissector_add_uint("ppp.protocol", PPP_PAP, pap_handle);
7929 
7930     /*
7931      * See above comment about NDISWAN for an explanation of why we're
7932      * registering with the "ethertype" dissector table.
7933      */
7934     dissector_add_uint("ethertype", PPP_PAP, pap_handle);
7935 
7936     /*
7937      * for GSM-A / MobileL3 / GPRS SM / PCO
7938      */
7939     dissector_add_uint("sm_pco.protocol", PPP_PAP, pap_handle);
7940 }
7941 
7942 void
proto_register_chap(void)7943 proto_register_chap(void)
7944 {
7945     static gint *ett[] = {
7946         &ett_chap,
7947         &ett_chap_data
7948     };
7949 
7950     static hf_register_info hf[] = {
7951         { &hf_chap_code,
7952             { "Code", "chap.code", FT_UINT8, BASE_DEC, VALS(chap_vals), 0x0,
7953                 "CHAP code", HFILL }},
7954         { &hf_chap_identifier,
7955             { "Identifier", "chap.identifier", FT_UINT8, BASE_DEC, NULL, 0x0,
7956                 "CHAP identifier", HFILL }},
7957         { &hf_chap_length,
7958             { "Length", "chap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7959                 "CHAP length", HFILL  }},
7960         { &hf_chap_data,
7961             { "Data", "chap.data", FT_NONE, BASE_NONE, NULL, 0x0,
7962                 "CHAP Data", HFILL }},
7963          { &hf_chap_value_size,
7964             { "Value Size", "chap.value_size", FT_UINT8, BASE_DEC, NULL, 0x0,
7965                 "CHAP value size", HFILL }},
7966         { &hf_chap_value,
7967             { "Value", "chap.value", FT_BYTES, BASE_NONE, NULL, 0x0,
7968                 "CHAP value data", HFILL }},
7969         { &hf_chap_name,
7970             { "Name", "chap.name", FT_STRING, BASE_NONE, NULL, 0x0,
7971                 "CHAP name", HFILL }},
7972         { &hf_chap_message,
7973             { "Message", "chap.message", FT_STRING, BASE_NONE, NULL, 0x0,
7974                 "CHAP message", HFILL }},
7975         { &hf_chap_stuff,
7976             { "Stuff", "chap.stuff", FT_BYTES, BASE_NONE, NULL, 0x0,
7977                 NULL, HFILL }},
7978         };
7979 
7980     proto_chap = proto_register_protocol(
7981         "PPP Challenge Handshake Authentication Protocol", "PPP CHAP", "chap");
7982     proto_register_field_array(proto_chap, hf, array_length(hf));
7983     proto_register_subtree_array(ett, array_length(ett));
7984 }
7985 
7986 void
proto_reg_handoff_chap(void)7987 proto_reg_handoff_chap(void)
7988 {
7989     dissector_handle_t chap_handle = create_dissector_handle(dissect_chap,
7990         proto_chap);
7991     dissector_add_uint("ppp.protocol", PPP_CHAP, chap_handle);
7992 
7993     /*
7994      * See above comment about NDISWAN for an explanation of why we're
7995      * registering with the "ethertype" dissector table.
7996      */
7997     dissector_add_uint("ethertype", PPP_CHAP, chap_handle);
7998 
7999     /*
8000      * for GSM-A / MobileL3 / GPRS SM / PCO
8001      */
8002     dissector_add_uint("sm_pco.protocol", PPP_CHAP, chap_handle);
8003 }
8004 
8005 void
proto_register_pppmuxcp(void)8006 proto_register_pppmuxcp(void)
8007 {
8008     static hf_register_info hf[] = {
8009         { &hf_pppmux_flags_pid,
8010             { "PID", "pppmuxcp.flags.pid", FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x80,
8011                 NULL, HFILL }},
8012         { &hf_pppmux_flags_field_length,
8013             { "Length field", "pppmuxcp.flags.field_length", FT_BOOLEAN, 8, TFS(&tfs_pppmux_length_field), 0x40,
8014                 NULL, HFILL }},
8015         { &hf_pppmuxcp_opt_type,
8016             { "Type", "pppmuxcp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0,
8017                 NULL, HFILL }},
8018         { &hf_pppmuxcp_opt_length,
8019             { "Length", "pppmuxcp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0,
8020                 NULL, HFILL }},
8021 
8022         /* Generated from convert_proto_tree_add_text.pl */
8023         { &hf_pppmux_flags, { "PFF/LXT", "pppmuxcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
8024         { &hf_pppmux_sub_frame_length, { "Sub-frame Length", "pppmuxcp.sub_frame_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
8025         { &hf_pppmux_def_prot_id, { "Default Protocol ID", "pppmuxcp.def_prot_id", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
8026         };
8027 
8028     static gint *ett[] = {
8029         &ett_pppmuxcp,
8030         &ett_pppmuxcp_options,
8031         &ett_pppmuxcp_def_pid_opt
8032     };
8033 
8034     proto_pppmuxcp = proto_register_protocol("PPPMux Control Protocol", "PPP PPPMuxCP", "pppmuxcp");
8035     proto_register_field_array(proto_pppmuxcp, hf, array_length(hf));
8036     proto_register_subtree_array(ett, array_length(ett));
8037 
8038     pppmuxcp_option_table = register_dissector_table("pppmuxcp.option", "PPP PPPMuxCP Options", proto_pppmuxcp, FT_UINT8, BASE_DEC);
8039 
8040     /* Register PPPMuxCP options as their own protocols so we can get the name of the option */
8041     proto_pppmuxcp_option_def_pid = proto_register_protocol_in_name_only("Default Protocol ID", "Default Protocol ID", "pppmuxcp.opt.def_pid", proto_pppmuxcp, FT_BYTES);
8042 }
8043 
8044 
8045 void
proto_reg_handoff_pppmuxcp(void)8046 proto_reg_handoff_pppmuxcp(void)
8047 {
8048     dissector_handle_t muxcp_handle;
8049 
8050     muxcp_handle = create_dissector_handle(dissect_pppmuxcp, proto_pppmuxcp);
8051     dissector_add_uint("ppp.protocol", PPP_MUXCP, muxcp_handle);
8052 
8053     /*
8054      * See above comment about NDISWAN for an explanation of why we're
8055      * registering with the "ethertype" dissector table.
8056      */
8057     dissector_add_uint("ethertype", PPP_MUXCP, muxcp_handle);
8058 
8059     dissector_add_uint("pppmuxcp.option", CI_DEFAULT_PID, create_dissector_handle( dissect_pppmuxcp_def_pid_opt, proto_pppmuxcp_option_def_pid ));
8060 }
8061 
8062 
8063 void
proto_register_pppmux(void)8064 proto_register_pppmux(void)
8065 {
8066     static hf_register_info hf[] = {
8067         { &hf_pppmux_protocol,
8068             { "Protocol", "pppmux.protocol", FT_UINT16,
8069                 BASE_HEX|BASE_EXT_STRING, &ppp_vals_ext, 0x0,
8070                 "The protocol of the sub-frame.", HFILL }}
8071     };
8072 
8073     static gint *ett[] = {
8074         &ett_pppmux,
8075         &ett_pppmux_subframe,
8076         &ett_pppmux_subframe_hdr,
8077         &ett_pppmux_subframe_flags,
8078         &ett_pppmux_subframe_info
8079     };
8080 
8081     proto_pppmux = proto_register_protocol("PPP Multiplexing", "PPP PPPMux",
8082         "pppmux");
8083     proto_register_field_array(proto_pppmux, hf, array_length(hf));
8084     proto_register_subtree_array(ett, array_length(ett));
8085 }
8086 
8087 void
proto_reg_handoff_pppmux(void)8088 proto_reg_handoff_pppmux(void)
8089 {
8090     dissector_handle_t pppmux_handle;
8091 
8092     pppmux_handle = create_dissector_handle(dissect_pppmux, proto_pppmux);
8093     dissector_add_uint("ppp.protocol", PPP_MUX, pppmux_handle);
8094 
8095     /*
8096      * See above comment about NDISWAN for an explanation of why we're
8097      * registering with the "ethertype" dissector table.
8098      */
8099     dissector_add_uint("ethertype", PPP_MUX, pppmux_handle);
8100 }
8101 
8102 void
proto_register_mplscp(void)8103 proto_register_mplscp(void)
8104 {
8105     static gint *ett[] = {
8106         &ett_mplscp,
8107         &ett_mplscp_options
8108     };
8109 
8110     proto_mplscp = proto_register_protocol("PPP MPLS Control Protocol",
8111         "PPP MPLSCP", "mplscp");
8112     proto_register_subtree_array(ett, array_length(ett));
8113 }
8114 
8115 void
proto_reg_handoff_mplscp(void)8116 proto_reg_handoff_mplscp(void)
8117 {
8118     dissector_handle_t mplscp_handle;
8119 
8120     mplscp_handle = create_dissector_handle(dissect_mplscp, proto_mplscp);
8121     dissector_add_uint("ppp.protocol", PPP_MPLSCP, mplscp_handle);
8122 
8123     /*
8124      * See above comment about NDISWAN for an explanation of why we're
8125      * registering with the "ethertype" dissector table.
8126      */
8127     dissector_add_uint("ethertype", PPP_MPLSCP, mplscp_handle);
8128 }
8129 
8130 void
proto_register_cdpcp(void)8131 proto_register_cdpcp(void)
8132 {
8133     static gint *ett[] = {
8134         &ett_cdpcp,
8135         &ett_cdpcp_options
8136     };
8137 
8138     proto_cdpcp = proto_register_protocol("PPP CDP Control Protocol",
8139         "PPP CDPCP", "cdpcp");
8140     proto_register_subtree_array(ett, array_length(ett));
8141 }
8142 
8143 void
proto_reg_handoff_cdpcp(void)8144 proto_reg_handoff_cdpcp(void)
8145 {
8146     dissector_handle_t cdpcp_handle;
8147 
8148     cdpcp_handle = create_dissector_handle(dissect_cdpcp, proto_cdpcp);
8149     dissector_add_uint("ppp.protocol", PPP_CDPCP, cdpcp_handle);
8150 
8151     /*
8152      * See above comment about NDISWAN for an explanation of why we're
8153      * registering with the "ethertype" dissector table.
8154      */
8155     dissector_add_uint("ethertype", PPP_CDPCP, cdpcp_handle);
8156 }
8157 
8158 void
proto_register_ipv6cp(void)8159 proto_register_ipv6cp(void)
8160 {
8161     static hf_register_info hf[] = {
8162       { &hf_ipv6cp_opt_type, { "Type", "ipv6cp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
8163       { &hf_ipv6cp_opt_length, { "Length", "ipv6cp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
8164       /* Generated from convert_proto_tree_add_text.pl */
8165       { &hf_ipv6cp_interface_identifier, { "Interface Identifier", "ipv6cp.interface_identifier", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL }},
8166     };
8167     static gint *ett[] = {
8168         &ett_ipv6cp,
8169         &ett_ipv6cp_options,
8170         &ett_ipv6cp_if_id_opt,
8171         &ett_ipv6cp_compress_opt
8172     };
8173 
8174     proto_ipv6cp = proto_register_protocol("PPP IPv6 Control Protocol", "PPP IPV6CP", "ipv6cp");
8175     proto_register_field_array(proto_ipv6cp, hf, array_length(hf));
8176     proto_register_subtree_array(ett, array_length(ett));
8177 
8178     ipv6cp_option_table = register_dissector_table("ipv6cp.option", "PPP IPV6CP Options", proto_ipv6cp, FT_UINT8, BASE_DEC);
8179 
8180     /* Register IPV6CP options as their own protocols so we can get the name of the option */
8181     proto_ipv6cp_option_if_id = proto_register_protocol_in_name_only("Interface Identifier", "Interface Identifier", "ipv6cp.opt.interface_identifier", proto_ipv6cp, FT_BYTES);
8182     proto_ipv6cp_option_compress = proto_register_protocol_in_name_only("IPv6 compression", "IPv6 compression", "ipv6cp.opt.compress", proto_ipv6cp, FT_BYTES);
8183 }
8184 
8185 void
proto_reg_handoff_ipv6cp(void)8186 proto_reg_handoff_ipv6cp(void)
8187 {
8188     dissector_handle_t ipv6cp_handle;
8189 
8190     ipv6cp_handle = create_dissector_handle(dissect_ipv6cp, proto_ipv6cp);
8191     dissector_add_uint("ppp.protocol", PPP_IPV6CP, ipv6cp_handle);
8192 
8193     /*
8194      * See above comment about NDISWAN for an explanation of why we're
8195      * registering with the "ethertype" dissector table.
8196      */
8197     dissector_add_uint("ethertype", PPP_IPV6CP, ipv6cp_handle);
8198 
8199     /*
8200      * for GSM-A / MobileL3 / GPRS SM / PCO
8201      */
8202     dissector_add_uint("sm_pco.protocol", PPP_IPV6CP, ipv6cp_handle);
8203 
8204     dissector_add_uint("ipv6cp.option", CI_IPV6CP_IF_ID, create_dissector_handle( dissect_ipv6cp_if_id_opt, proto_ipv6cp_option_if_id ));
8205     dissector_add_uint("ipv6cp.option", CI_COMPRESS_PROTO, create_dissector_handle( dissect_ipcp_compress_opt, proto_ipv6cp_option_compress ));
8206 }
8207 
8208 void
proto_register_iphc_crtp(void)8209 proto_register_iphc_crtp(void)
8210 {
8211     static hf_register_info hf[] = {
8212         { &hf_iphc_crtp_cid16,
8213             { "Context Id", "crtp.cid", FT_UINT16, BASE_DEC, NULL, 0x0,
8214                 "The context identifier of the compressed packet.", HFILL }},
8215         { &hf_iphc_crtp_cid8,
8216             { "Context Id", "crtp.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
8217                 "The context identifier of the compressed packet.", HFILL }},
8218         { &hf_iphc_crtp_gen,
8219             { "Generation", "crtp.gen", FT_UINT8, BASE_DEC, NULL, 0x3f,
8220                 "The generation of the compressed packet.", HFILL }},
8221         { &hf_iphc_crtp_seq,
8222             { "Sequence (Data)", "crtp.seq", FT_UINT8, BASE_DEC, NULL, 0x0f,
8223                 "The sequence of the compressed packet.", HFILL }},
8224         { &hf_iphc_crtp_fh_flags,
8225             { "Flags", "crtp.fh_flags", FT_UINT8, BASE_HEX, NULL,
8226                 IPHC_CRTP_FH_FLAG_MASK,
8227                 "The flags of the full header packet.", HFILL }},
8228         { &hf_iphc_crtp_fh_cidlenflag,
8229             { "CID Length", "crtp.fh_flags.cidlen", FT_BOOLEAN, 8, TFS(&iphc_crtp_fh_cidlenflag),
8230                 IPHC_CRTP_FH_CIDLEN_FLAG, "A flag which is not set for 8-bit Context Ids and set for 16-bit Context Ids.", HFILL }},
8231         { &hf_iphc_crtp_fh_dataflag,
8232             { "Sequence (Data)", "crtp.fh_flags.data", FT_BOOLEAN, 8,
8233                 TFS(&tfs_present_absent), IPHC_CRTP_FH_DATA_FLAG,
8234                 "This indicates the presence of a nonzero data field, usually meaning the low nibble is a sequence number.", HFILL }},
8235         { &hf_iphc_crtp_cs_flags,
8236             { "Flags", "crtp.cs_flags", FT_UINT8, BASE_DEC, VALS(iphc_crtp_cs_flags),
8237                 0x0, "The flags of the context state packet.", HFILL }},
8238         { &hf_iphc_crtp_cs_cnt,
8239             { "Count", "crtp.cnt", FT_UINT8, BASE_DEC, NULL, 0x0,
8240                 "The count of the context state packet.", HFILL }},
8241         { &hf_iphc_crtp_cs_invalid,
8242             { "Invalid", "crtp.invalid", FT_BOOLEAN, 8, NULL, 0x80,
8243                 "The invalid bit of the context state packet.", HFILL }},
8244         { &hf_iphc_crtp_ip_id,
8245             { "IP-ID", "crtp.ip-id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
8246                 "The IPv4 Identification Field is RANDOM and thus included in a compressed Non TCP packet (RFC 2507 6a), 7.13a). Only IPv4 is supported in this dissector.", HFILL }},
8247         { &hf_iphc_crtp_data,
8248             { "Data", "crtp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
8249                 NULL, HFILL }},
8250         };
8251 
8252     static gint *ett[] = {
8253         &ett_iphc_crtp,
8254         &ett_iphc_crtp_hdr,
8255         &ett_iphc_crtp_info,
8256         &ett_iphc_crtp_fh_flags
8257     };
8258 
8259     static ei_register_info ei[] = {
8260         { &ei_iphc_crtp_ip_version, { "crtp.ip_version_unsupported", PI_PROTOCOL, PI_WARN, "IP version is unsupported", EXPFILL }},
8261         { &ei_iphc_crtp_next_protocol, { "crtp.next_protocol_unsupported", PI_PROTOCOL, PI_WARN, "Next protocol is unsupported", EXPFILL }},
8262         { &ei_iphc_crtp_seq_nonzero, { "crtp.seq_nonzero", PI_PROTOCOL, PI_WARN, "Sequence (Data) field is nonzero despite D bit not set", EXPFILL }}
8263     };
8264 
8265     expert_module_t* expert_iphc_crtp;
8266 
8267     proto_iphc_crtp = proto_register_protocol("CRTP", "CRTP", "crtp");
8268     /* Created to remove Decode As confusion */
8269     proto_iphc_crtp_cudp16 = proto_register_protocol_in_name_only("CRTP (CUDP 16)", "CRTP (CUDP 16)", "crtp_cudp16", proto_iphc_crtp, FT_PROTOCOL);
8270     proto_iphc_crtp_cudp8 = proto_register_protocol_in_name_only("CRTP (CUDP 8)", "CRTP (CUDP 8)", "crtp_cudp8", proto_iphc_crtp, FT_PROTOCOL);
8271     proto_iphc_crtp_cs = proto_register_protocol_in_name_only("CRTP (CS)", "CRTP (CS)", "crtp_cs", proto_iphc_crtp, FT_PROTOCOL);
8272     proto_iphc_crtp_cntcp = proto_register_protocol_in_name_only("CRTP (CNTCP)", "CRTP (CNTCP)", "crtp_cntcp", proto_iphc_crtp, FT_PROTOCOL);
8273 
8274     proto_register_field_array(proto_iphc_crtp, hf, array_length(hf));
8275     proto_register_subtree_array(ett, array_length(ett));
8276     expert_iphc_crtp = expert_register_protocol(proto_iphc_crtp);
8277     expert_register_field_array(expert_iphc_crtp, ei, array_length(ei));
8278 }
8279 
8280 void
proto_reg_handoff_iphc_crtp(void)8281 proto_reg_handoff_iphc_crtp(void)
8282 {
8283     dissector_handle_t fh_handle;
8284     dissector_handle_t cudp16_handle;
8285     dissector_handle_t cudp8_handle;
8286     dissector_handle_t cs_handle;
8287     dissector_handle_t cntcp_handle;
8288 
8289     fh_handle = create_dissector_handle(dissect_iphc_crtp_fh, proto_iphc_crtp);
8290     dissector_add_uint("ppp.protocol", PPP_RTP_FH, fh_handle);
8291 
8292     cudp16_handle = create_dissector_handle(dissect_iphc_crtp_cudp16, proto_iphc_crtp_cudp16);
8293     dissector_add_uint("ppp.protocol", PPP_RTP_CUDP16, cudp16_handle);
8294 
8295     cudp8_handle = create_dissector_handle(dissect_iphc_crtp_cudp8, proto_iphc_crtp_cudp8);
8296     dissector_add_uint("ppp.protocol", PPP_RTP_CUDP8, cudp8_handle);
8297 
8298     cs_handle = create_dissector_handle(dissect_iphc_crtp_cs, proto_iphc_crtp_cs);
8299     dissector_add_uint("ppp.protocol", PPP_RTP_CS, cs_handle);
8300 
8301     cntcp_handle = create_dissector_handle(dissect_iphc_crtp_cntcp, proto_iphc_crtp_cntcp);
8302     dissector_add_uint("ppp.protocol", PPP_RTP_CNTCP, cntcp_handle);
8303 
8304     /*
8305      * See above comment about NDISWAN for an explanation of why we're
8306      * registering with the "ethertype" dissector table.
8307      */
8308     dissector_add_uint("ethertype", PPP_RTP_FH, fh_handle);
8309     dissector_add_uint("ethertype", PPP_RTP_CUDP16, cudp16_handle);
8310     dissector_add_uint("ethertype", PPP_RTP_CUDP8, cudp8_handle);
8311     dissector_add_uint("ethertype", PPP_RTP_CS, cs_handle);
8312     dissector_add_uint("ethertype", PPP_RTP_CNTCP, cntcp_handle);
8313 }
8314 
8315 /*
8316  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
8317  *
8318  * Local variables:
8319  * c-basic-offset: 4
8320  * tab-width: 8
8321  * indent-tabs-mode: nil
8322  * End:
8323  *
8324  * vi: set shiftwidth=4 tabstop=8 expandtab:
8325  * :indentSize=4:tabSize=8:noTabs=true:
8326  */
8327