Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lapd.c
blob04003251710514c75d9000a7dc540b217039a59f
1 /* packet-lapd.c
2 * Routines for LAPD frame disassembly
3 * Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 * LAPD bitstream over RTP handling
13 * Copyright 2008, Ericsson AB
14 * Written by Balint Reczey <balint.reczey@ericsson.com>
16 * ISDN/LAPD references:
18 * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/isdn.htm
19 * http://www.ece.wpi.edu/courses/ee535/hwk11cd95/agrebe/agrebe.html
20 * http://www.acacia-net.com/Clarinet/Protocol/q9213o84.htm
21 * http://www.itu.int/rec/T-REC-Q.921/en
22 * Base Station Controller - Base Transceiver Station (BSC - BTS) interface; Layer 2 specification
23 * http://www.3gpp.org/ftp/Specs/html-info/48056.htm
26 #include "config.h"
28 #include <epan/packet.h>
29 #include <epan/conversation.h>
30 #include <epan/xdlc.h>
31 #include <epan/crc16-tvb.h>
32 #include <epan/prefs.h>
33 #include <wiretap/wtap.h>
34 #include <epan/lapd_sapi.h>
35 #include <epan/expert.h>
36 #include <epan/proto_data.h>
37 #include <epan/tfs.h>
38 #include <wsutil/array.h>
40 void proto_register_lapd(void);
41 void proto_reg_handoff_lapd(void);
43 static int proto_lapd;
44 static int hf_lapd_direction;
45 static int hf_lapd_address;
46 static int hf_lapd_sapi;
47 static int hf_lapd_gsm_sapi;
48 static int hf_lapd_cr;
49 static int hf_lapd_ea1;
50 static int hf_lapd_tei;
51 static int hf_lapd_ea2;
52 static int hf_lapd_control;
53 static int hf_lapd_n_r;
54 static int hf_lapd_n_s;
55 static int hf_lapd_p;
56 static int hf_lapd_p_ext;
57 static int hf_lapd_f;
58 static int hf_lapd_f_ext;
59 static int hf_lapd_s_ftype;
60 static int hf_lapd_u_modifier_cmd;
61 static int hf_lapd_u_modifier_resp;
62 static int hf_lapd_ftype_i;
63 static int hf_lapd_ftype_s_u;
64 static int hf_lapd_ftype_s_u_ext;
65 static int hf_lapd_checksum;
66 static int hf_lapd_checksum_status;
68 static int ett_lapd;
69 static int ett_lapd_address;
70 static int ett_lapd_control;
71 static int ett_lapd_checksum;
73 static expert_field ei_lapd_abort;
74 static expert_field ei_lapd_checksum_bad;
76 static dissector_handle_t lapd_handle;
77 static dissector_handle_t lapd_phdr_handle;
78 static dissector_handle_t linux_lapd_handle;
79 static dissector_handle_t lapd_bitstream_handle;
81 static dissector_table_t lapd_sapi_dissector_table;
82 static dissector_table_t lapd_gsm_sapi_dissector_table;
84 /* Whether to use GSM SAPI vals or not */
85 static bool global_lapd_gsm_sapis;
88 * Bits in the address field.
90 #define LAPD_SAPI 0xfc00 /* Service Access Point Identifier */
91 #define LAPD_SAPI_SHIFT 10
92 #define LAPD_CR 0x0200 /* Command/Response bit */
93 #define LAPD_EA1 0x0100 /* First Address Extension bit */
94 #define LAPD_TEI 0x00fe /* Terminal Endpoint Identifier */
95 #define LAPD_TEI_SHIFT 1
96 #define LAPD_EA2 0x0001 /* Second Address Extension bit */
98 #define LAPD_DIR_USER_TO_NETWORK 0
99 #define LAPD_DIR_NETWORK_TO_USER 1
101 static const value_string lapd_direction_vals[] = {
102 { LAPD_DIR_USER_TO_NETWORK, "User->Network"},
103 { LAPD_DIR_NETWORK_TO_USER, "Network->User"},
104 { 0, NULL }
107 static const value_string lapd_sapi_vals[] = {
108 { LAPD_SAPI_Q931, "Q.931 Call control procedure" },
109 { LAPD_SAPI_PM_Q931, "Packet mode Q.931 Call control procedure" },
110 { LAPD_SAPI_X25, "X.25 Level 3 procedures" },
111 { LAPD_SAPI_L2, "Layer 2 management procedures" },
112 { 0, NULL }
115 static const value_string lapd_gsm_sapi_vals[] = {
116 { LAPD_GSM_SAPI_RA_SIG_PROC, "Radio signalling procedures" },
117 { LAPD_GSM_SAPI_NOT_USED_1, "(Not used in GSM PLMN)" },
118 { LAPD_GSM_SAPI_NOT_USED_16, "(Not used in GSM PLMN)" },
119 { LAPD_GSM_SAPI_OM_PROC, "Operation and maintenance procedure" },
120 { LAPD_SAPI_L2, "Layer 2 management procedures" },
121 { 0, NULL }
124 /* Used only for U frames */
125 static const xdlc_cf_items lapd_cf_items = {
126 NULL,
127 NULL,
128 &hf_lapd_p,
129 &hf_lapd_f,
130 NULL,
131 &hf_lapd_u_modifier_cmd,
132 &hf_lapd_u_modifier_resp,
133 NULL,
134 &hf_lapd_ftype_s_u
137 /* Used only for I and S frames */
138 static const xdlc_cf_items lapd_cf_items_ext = {
139 &hf_lapd_n_r,
140 &hf_lapd_n_s,
141 &hf_lapd_p_ext,
142 &hf_lapd_f_ext,
143 &hf_lapd_s_ftype,
144 NULL,
145 NULL,
146 &hf_lapd_ftype_i,
147 &hf_lapd_ftype_s_u_ext
150 #define MAX_LAPD_PACKET_LEN 1024
152 /* LAPD frame detection state */
153 enum lapd_bitstream_states {OUT_OF_SYNC, FLAGS, DATA};
155 typedef struct lapd_byte_state {
156 enum lapd_bitstream_states state; /* frame detection state */
157 char full_byte; /* part of a full byte */
158 char bit_offset; /* number of bits already got in the full byte */
159 int ones; /* number of consecutive ones since the last zero */
160 char data[MAX_LAPD_PACKET_LEN];
161 int data_len;
162 } lapd_byte_state_t;
164 typedef struct lapd_ppi {
165 bool has_crc; /* CRC is captured with LAPD the frames */
166 lapd_byte_state_t start_byte_state; /* LAPD bitstream byte state at the beginning of processing the packet */
167 } lapd_ppi_t;
169 /* Fill values in lapd_byte_state struct */
170 static void
171 fill_lapd_byte_state(lapd_byte_state_t *ptr, enum lapd_bitstream_states state, char full_byte, char bit_offset, int ones, char *data, int data_len)
173 ptr->state = state;
174 ptr->full_byte = full_byte;
175 ptr->bit_offset = bit_offset;
176 ptr->ones = ones;
178 ptr->data_len = MIN((int)sizeof(ptr->data), data_len);
179 memcpy(ptr->data, data, ptr->data_len);
182 typedef struct lapd_convo_data {
183 address addr_a;
184 address addr_b;
185 uint32_t port_a;
186 uint32_t port_b;
187 lapd_byte_state_t *byte_state_a;
188 lapd_byte_state_t *byte_state_b;
189 } lapd_convo_data_t;
192 static void
193 dissect_lapd_full(tvbuff_t*, packet_info*, proto_tree*, uint32_t);
195 /* got new LAPD frame byte */
196 static void new_byte(char full_byte, char data[], int *data_len) {
197 if (*data_len < MAX_LAPD_PACKET_LEN) {
198 data[*data_len] = full_byte;
199 (*data_len)++;
200 } else {
201 /* XXX : we are not prepared for that big messages, drop the last byte */
205 static void
206 lapd_log_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *msg)
208 proto_item *ti;
210 ti = proto_tree_add_item(tree, proto_lapd, tvb, offset, 1, ENC_NA);
211 expert_add_info_format(pinfo, ti, &ei_lapd_abort, "%s", msg);
215 * Flags to pass to dissect_lapd_full.
217 #define LAPD_HAS_CRC 0x00000001
218 #define LAPD_HAS_DIRECTION 0x00000002
219 #define LAPD_HAS_LINUX_SLL 0x00000004
220 #define LAPD_USER_TO_NETWORK 0x00000008
221 #define LAPD_NETWORK_IS_REMOTE 0x00000010
222 #define LAPD_USER_IS_REMOTE 0x00000020
224 static int
225 dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissector_data _U_)
227 uint8_t byte, full_byte = 0x00, bit_offset = 0;
228 bool bit;
229 uint8_t i, ones = 0, data[MAX_LAPD_PACKET_LEN];
230 int data_len = 0;
231 int offset = 0, available;
232 uint8_t *buff;
233 tvbuff_t *new_tvb;
235 enum lapd_bitstream_states state = OUT_OF_SYNC;
236 lapd_ppi_t *lapd_ppi;
237 conversation_t *conversation = NULL;
238 lapd_convo_data_t *convo_data = NULL;
239 lapd_byte_state_t *lapd_byte_state, *prev_byte_state = NULL;
240 bool forward_stream = true;
242 /* get remaining data from previous packets */
243 conversation = find_or_create_conversation(pinfo);
244 lapd_ppi = (lapd_ppi_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0);
245 if (lapd_ppi) {
246 prev_byte_state = &lapd_ppi->start_byte_state;
247 if (prev_byte_state) {
248 state = prev_byte_state->state;
249 full_byte = prev_byte_state->full_byte;
250 bit_offset = prev_byte_state->bit_offset;
251 ones = prev_byte_state->ones;
252 memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
253 data_len = prev_byte_state->data_len;
256 } else if (conversation) {
257 convo_data = (lapd_convo_data_t*)conversation_get_proto_data(conversation, proto_lapd);
258 if (NULL != convo_data) {
259 if (addresses_equal(&convo_data->addr_a, &pinfo->src)
260 && addresses_equal(&convo_data->addr_b, &pinfo->dst)
261 && convo_data-> port_a == pinfo->srcport
262 && convo_data-> port_b == pinfo->destport) {
263 /* "forward" direction */
264 forward_stream = true;
265 prev_byte_state = convo_data->byte_state_a;
266 } else if (addresses_equal(&convo_data-> addr_b, &pinfo->src)
267 && addresses_equal(&convo_data->addr_a, &pinfo->dst)
268 && convo_data-> port_b == pinfo->srcport
269 && convo_data-> port_a == pinfo->destport) {
270 /* "backward" direction */
271 forward_stream = false;
272 prev_byte_state = convo_data->byte_state_b;
275 if (prev_byte_state) {
276 state = prev_byte_state->state;
277 full_byte = prev_byte_state->full_byte;
278 bit_offset = prev_byte_state->bit_offset;
279 ones = prev_byte_state->ones;
281 memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
282 data_len = prev_byte_state->data_len;
286 /* Consume tvb bytes */
287 available = tvb_reported_length_remaining(tvb, offset);
288 while (offset < available) {
289 byte = tvb_get_uint8(tvb,offset);
290 offset++;
291 for (i=0; i < 8; i++) { /* cycle through bits */
292 bit = byte & (0x80 >> i) ? true : false;
294 /* consume a bit */
295 if (bit) {
296 ones++;
297 full_byte |= (1 << bit_offset++);
298 } else {
299 if (ones == 5 && state == DATA) {
300 /* we don't increase bit_offset, it is an inserted zero */
301 } else if (ones == 6 && state == DATA) { /* probably starting flag sequence */
302 buff = (uint8_t *)wmem_memdup(pinfo->pool, data, data_len);
303 /* Allocate new tvb for the LAPD frame */
304 new_tvb = tvb_new_child_real_data(tvb, buff, data_len, data_len);
305 add_new_data_source(pinfo, new_tvb, "Decoded LAPD bitstream");
306 data_len = 0;
307 state = FLAGS;
308 bit_offset++;
310 if (full_byte != 0x7E) {
311 data_len = 0;
312 state = OUT_OF_SYNC;
313 lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 6 ones that don't match 0x7e!");
316 dissect_lapd_full(new_tvb, pinfo, tree, LAPD_HAS_CRC);
317 } else if (ones >= 7) { /* frame reset or 11111111 flag byte */
318 data_len = 0;
319 state = OUT_OF_SYNC;
320 bit_offset++;
322 lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 7 ones!");
323 } else {
324 bit_offset++;
326 ones = 0;
329 if (bit_offset == 8) { /* we have a new complete byte */
330 switch (state) {
331 case OUT_OF_SYNC:
332 if (full_byte == 0x7E) { /* we have a flag byte */
333 state = FLAGS;
334 full_byte = 0x00;
335 bit_offset = 0;
336 } else { /* no sync yet, wait for a new byte */
337 full_byte = (full_byte >> 1) & 0x7F;
338 bit_offset--;
340 break;
342 case FLAGS:
343 if (full_byte == 0x7E) { /* we have a flag byte */
344 full_byte = 0x00;
345 bit_offset = 0;
346 } else { /* we got the first data byte */
347 state = DATA;
348 new_byte(full_byte, data, &data_len);
349 full_byte = 0x00;
350 bit_offset = 0;
352 break;
354 case DATA:
355 /* we got a new data byte */
356 new_byte(full_byte, data, &data_len);
357 full_byte = 0x00;
358 bit_offset = 0;
359 break;
366 if (NULL == p_get_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0)) {
367 /* Per packet information */
368 lapd_ppi = wmem_new(wmem_file_scope(), lapd_ppi_t);
369 lapd_ppi->has_crc = true;
370 if (prev_byte_state)
371 fill_lapd_byte_state(&lapd_ppi->start_byte_state, prev_byte_state->state,
372 prev_byte_state->full_byte, prev_byte_state->bit_offset,
373 prev_byte_state->ones, prev_byte_state->data, prev_byte_state->data_len);
374 else
375 fill_lapd_byte_state(&lapd_ppi->start_byte_state, OUT_OF_SYNC, 0x00, 0, 0, data, 0);
377 p_add_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0, lapd_ppi);
380 /* Conversation info*/
382 if (conversation) {
383 if (convo_data) { /* already have lapd convo data */
384 if (forward_stream) {
385 if (!convo_data->byte_state_a)
386 convo_data->byte_state_a = wmem_new(wmem_file_scope(), lapd_byte_state_t);
387 fill_lapd_byte_state(convo_data->byte_state_a, state, full_byte, bit_offset, ones, data, data_len);
388 } else {
389 if (!convo_data->byte_state_b)
390 convo_data->byte_state_b = wmem_new(wmem_file_scope(), lapd_byte_state_t);
391 fill_lapd_byte_state(convo_data->byte_state_b, state, full_byte, bit_offset, ones, data, data_len);
393 } else { /* lapd convo data has to be created */
394 lapd_byte_state = wmem_new(wmem_file_scope(), lapd_byte_state_t);
395 fill_lapd_byte_state(lapd_byte_state, state, full_byte, bit_offset, ones, data, data_len);
396 convo_data = wmem_new(wmem_file_scope(), lapd_convo_data_t);
397 copy_address_wmem(wmem_file_scope(), &convo_data->addr_a, &pinfo->src);
398 copy_address_wmem(wmem_file_scope(), &convo_data->addr_b, &pinfo->dst);
399 convo_data->port_a = pinfo->srcport;
400 convo_data->port_b = pinfo->destport;
401 convo_data->byte_state_a = lapd_byte_state;
402 convo_data->byte_state_b = NULL;
403 conversation_add_proto_data(conversation, proto_lapd, convo_data);
408 return tvb_captured_length(tvb);
411 static int
412 dissect_linux_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
414 uint32_t flags = LAPD_HAS_LINUX_SLL | LAPD_HAS_DIRECTION;
416 /* frame is captured via libpcap */
417 if (pinfo->pseudo_header->lapd.pkttype == 4 /*PACKET_OUTGOING*/) {
418 if (pinfo->pseudo_header->lapd.we_network) {
420 * We're the network side, so the user is remote,
421 * and we're sending it, so this is Network->User.
423 flags |= LAPD_USER_IS_REMOTE;
424 } else {
426 * We're the user side, so the network is remote,
427 * and we're sending it, so this is User->Network.
429 flags |= LAPD_NETWORK_IS_REMOTE | LAPD_USER_TO_NETWORK;
432 else if (pinfo->pseudo_header->lapd.pkttype == 3 /*PACKET_OTHERHOST*/) {
434 * We must be a TE, sniffing what other TE transmit, so
435 * both sides are remote.
437 * XXX - do we know whether it's User->Network or
438 * Network->User?
440 flags |= LAPD_USER_IS_REMOTE | LAPD_NETWORK_IS_REMOTE | LAPD_USER_TO_NETWORK;
442 else {
443 /* The frame is incoming */
444 if (pinfo->pseudo_header->lapd.we_network) {
446 * We're the network side, so the user is remote,
447 * and we received it, so this is User->Network.
449 flags |= LAPD_USER_IS_REMOTE | LAPD_USER_TO_NETWORK;
450 } else {
452 * We're the user side, so the network is remote,
453 * and we received it, so this is Network->User.
455 flags |= LAPD_NETWORK_IS_REMOTE;
458 dissect_lapd_full(tvb, pinfo, tree, flags);
459 return tvb_captured_length(tvb);
463 * Called from dissectors, such as the ISDN dissector, that supply a
464 * struct isdn_pndr giving the packet direction.
466 static int
467 dissect_lapd_phdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
469 struct isdn_phdr *isdn = (struct isdn_phdr *)data;
470 uint32_t flags = LAPD_HAS_DIRECTION;
472 if (isdn->uton)
473 flags |= LAPD_USER_TO_NETWORK;
474 dissect_lapd_full(tvb, pinfo, tree, flags);
475 return tvb_captured_length(tvb);
479 * Called for link-layer encapsulation.
481 static int
482 dissect_lapd_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
484 uint32_t flags;
485 uint32_t lapd_flags = 0;
488 * If we have direction flags, we have a direction;
489 * "outbound" packets are presumed to be User->Network and
490 * "inbound" packets are presumed to be Network->User.
491 * Other packets, we have no idea.
493 if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_uint32_option_value(pinfo->rec->block, OPT_PKT_FLAGS, &flags)) {
494 switch (PACK_FLAGS_DIRECTION(flags)) {
496 case PACK_FLAGS_DIRECTION_OUTBOUND:
497 lapd_flags |= LAPD_HAS_DIRECTION | LAPD_USER_TO_NETWORK;
498 break;
500 case PACK_FLAGS_DIRECTION_INBOUND:
501 lapd_flags |= LAPD_HAS_DIRECTION;
502 break;
504 default:
505 break;
508 dissect_lapd_full(tvb, pinfo, tree, lapd_flags);
509 return tvb_captured_length(tvb);
512 static int
513 dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
515 /* XXX - direction is unknown */
516 dissect_lapd_full(tvb, pinfo, tree, 0);
517 return tvb_captured_length(tvb);
520 static void
521 dissect_lapd_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t flags)
523 proto_tree *lapd_tree, *addr_tree;
524 proto_item *lapd_ti, *addr_ti;
525 uint16_t control;
526 int lapd_header_len, checksum_offset;
527 uint16_t addr, cr, sapi, tei;
528 bool is_response = 0;
529 tvbuff_t *next_tvb;
530 const char *srcname = "?";
531 const char *dstname = "?";
533 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPD");
534 col_clear(pinfo->cinfo, COL_INFO);
536 addr = tvb_get_ntohs(tvb, 0);
537 cr = addr & LAPD_CR;
538 tei = (addr & LAPD_TEI) >> LAPD_TEI_SHIFT;
539 sapi = (addr & LAPD_SAPI) >> LAPD_SAPI_SHIFT;
540 lapd_header_len = 2; /* addr */
542 /* Append TEI to info field */
543 col_append_fstr(pinfo->cinfo, COL_INFO, "TEI:%02u ", tei);
544 col_set_fence(pinfo->cinfo, COL_INFO);
546 if (flags & LAPD_HAS_DIRECTION) {
547 if (flags & LAPD_USER_TO_NETWORK) {
548 is_response = cr ? true : false;
549 if (flags & LAPD_HAS_LINUX_SLL) {
550 srcname = (flags & LAPD_USER_IS_REMOTE) ?
551 "Remote User" : "Local User";
552 dstname = (flags & LAPD_NETWORK_IS_REMOTE) ?
553 "Remote Network" : "Local Network";
554 } else {
555 srcname = "User";
556 dstname = "Network";
558 } else {
559 is_response = cr ? false : true;
560 if (flags & LAPD_HAS_LINUX_SLL) {
561 srcname = (flags & LAPD_NETWORK_IS_REMOTE) ?
562 "Remote Network" : "Local Network";
563 dstname = (flags & LAPD_USER_IS_REMOTE) ?
564 "Remote User" : "Local User";
565 } else {
566 srcname = "Network";
567 dstname = "User";
571 set_address(&pinfo->dl_dst, AT_STRINGZ, (int)strlen(dstname) + 1, dstname);
572 set_address(&pinfo->dl_src, AT_STRINGZ, (int)strlen(srcname) + 1, srcname);
573 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
574 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
576 if (tree) {
577 proto_item *direction_ti;
579 lapd_ti = proto_tree_add_item(tree, proto_lapd, tvb, 0, -1,
580 ENC_NA);
581 lapd_tree = proto_item_add_subtree(lapd_ti, ett_lapd);
584 * Don't show the direction if we don't know it.
586 if (flags & LAPD_HAS_DIRECTION) {
587 direction_ti = proto_tree_add_uint(lapd_tree, hf_lapd_direction,
588 tvb, 0, 0,
589 (flags & LAPD_USER_TO_NETWORK) ? LAPD_DIR_USER_TO_NETWORK : LAPD_DIR_NETWORK_TO_USER);
590 proto_item_set_generated(direction_ti);
593 addr_ti = proto_tree_add_uint(lapd_tree, hf_lapd_address, tvb,
594 0, 2, addr);
595 addr_tree = proto_item_add_subtree(addr_ti, ett_lapd_address);
597 if(global_lapd_gsm_sapis){
598 proto_tree_add_uint(addr_tree, hf_lapd_gsm_sapi,tvb, 0, 1, addr);
599 }else{
600 proto_tree_add_uint(addr_tree, hf_lapd_sapi,tvb, 0, 1, addr);
602 proto_tree_add_uint(addr_tree, hf_lapd_cr, tvb, 0, 1, addr);
603 proto_tree_add_uint(addr_tree, hf_lapd_ea1, tvb, 0, 1, addr);
604 proto_tree_add_uint(addr_tree, hf_lapd_tei, tvb, 1, 1, addr);
605 proto_tree_add_uint(addr_tree, hf_lapd_ea2, tvb, 1, 1, addr);
607 else {
608 lapd_ti = NULL;
609 lapd_tree = NULL;
612 control = dissect_xdlc_control(tvb, 2, pinfo, lapd_tree, hf_lapd_control,
613 ett_lapd_control, &lapd_cf_items, &lapd_cf_items_ext, NULL, NULL,
614 is_response, true, false);
615 lapd_header_len += XDLC_CONTROL_LEN(control, true);
617 if (tree)
618 proto_item_set_len(lapd_ti, lapd_header_len);
620 if (flags & LAPD_HAS_CRC) {
622 /* check checksum */
623 checksum_offset = tvb_reported_length(tvb) - 2;
625 proto_tree_add_checksum(lapd_tree, tvb, checksum_offset, hf_lapd_checksum, hf_lapd_checksum_status, &ei_lapd_checksum_bad, pinfo,
626 crc16_ccitt_tvb(tvb, tvb_reported_length(tvb) - 2), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
628 next_tvb = tvb_new_subset_length(tvb, lapd_header_len, tvb_reported_length_remaining(tvb,lapd_header_len) - 2);
630 } else
631 next_tvb = tvb_new_subset_remaining(tvb, lapd_header_len);
633 /* Dissection done, append " | " to COL_INFO */
634 col_append_str(pinfo->cinfo, COL_INFO, " | ");
635 col_set_fence(pinfo->cinfo, COL_INFO);
637 if (XDLC_IS_INFORMATION(control)) {
638 /* call next protocol */
639 if(global_lapd_gsm_sapis){
640 if (!dissector_try_uint(lapd_gsm_sapi_dissector_table, sapi,
641 next_tvb, pinfo, tree))
642 call_data_dissector(next_tvb, pinfo, tree);
643 }else{
644 if (!dissector_try_uint(lapd_sapi_dissector_table, sapi,
645 next_tvb, pinfo, tree))
646 call_data_dissector(next_tvb, pinfo, tree);
648 } else
649 call_data_dissector(next_tvb, pinfo, tree);
652 void
653 proto_register_lapd(void)
655 static hf_register_info hf[] = {
657 { &hf_lapd_direction,
658 { "Direction", "lapd.direction", FT_UINT32, BASE_DEC, VALS(lapd_direction_vals), 0x0,
659 NULL, HFILL }},
661 { &hf_lapd_address,
662 { "Address Field", "lapd.address", FT_UINT16, BASE_HEX, NULL, 0x0,
663 NULL, HFILL }},
665 { &hf_lapd_sapi,
666 { "SAPI", "lapd.sapi", FT_UINT16, BASE_DEC, VALS(lapd_sapi_vals), LAPD_SAPI,
667 "Service Access Point Identifier", HFILL }},
669 { &hf_lapd_gsm_sapi,
670 { "SAPI", "lapd.sapi", FT_UINT16, BASE_DEC, VALS(lapd_gsm_sapi_vals), LAPD_SAPI,
671 "Service Access Point Identifier", HFILL }},
673 { &hf_lapd_cr,
674 { "C/R", "lapd.cr", FT_UINT16, BASE_DEC, NULL, LAPD_CR,
675 "Command/Response bit", HFILL }},
677 { &hf_lapd_ea1,
678 { "EA1", "lapd.ea1", FT_UINT16, BASE_DEC, NULL, LAPD_EA1,
679 "First Address Extension bit", HFILL }},
681 { &hf_lapd_tei,
682 { "TEI", "lapd.tei", FT_UINT16, BASE_DEC, NULL, LAPD_TEI,
683 "Terminal Endpoint Identifier", HFILL }},
685 { &hf_lapd_ea2,
686 { "EA2", "lapd.ea2", FT_UINT16, BASE_DEC, NULL, LAPD_EA2,
687 "Second Address Extension bit", HFILL }},
689 { &hf_lapd_control,
690 { "Control Field", "lapd.control", FT_UINT16, BASE_HEX, NULL, 0x0,
691 NULL, HFILL }},
693 { &hf_lapd_n_r,
694 { "N(R)", "lapd.control.n_r", FT_UINT16, BASE_DEC,
695 NULL, XDLC_N_R_EXT_MASK, NULL, HFILL }},
697 { &hf_lapd_n_s,
698 { "N(S)", "lapd.control.n_s", FT_UINT16, BASE_DEC,
699 NULL, XDLC_N_S_EXT_MASK, NULL, HFILL }},
701 { &hf_lapd_p,
702 { "Poll", "lapd.control.p", FT_BOOLEAN, 8,
703 TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }},
705 { &hf_lapd_p_ext,
706 { "Poll", "lapd.control.p", FT_BOOLEAN, 16,
707 TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }},
709 { &hf_lapd_f,
710 { "Final", "lapd.control.f", FT_BOOLEAN, 8,
711 TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }},
713 { &hf_lapd_f_ext,
714 { "Final", "lapd.control.f", FT_BOOLEAN, 16,
715 TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }},
717 { &hf_lapd_s_ftype,
718 { "Supervisory frame type", "lapd.control.s_ftype", FT_UINT16, BASE_HEX,
719 VALS(stype_vals), XDLC_S_FTYPE_MASK, NULL, HFILL }},
721 { &hf_lapd_u_modifier_cmd,
722 { "Command", "lapd.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
723 VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, NULL, HFILL }},
725 { &hf_lapd_u_modifier_resp,
726 { "Response", "lapd.control.u_modifier_resp", FT_UINT8, BASE_HEX,
727 VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, NULL, HFILL }},
729 { &hf_lapd_ftype_i,
730 { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
731 VALS(ftype_vals), XDLC_I_MASK, NULL, HFILL }},
733 { &hf_lapd_ftype_s_u,
734 { "Frame type", "lapd.control.ftype", FT_UINT8, BASE_HEX,
735 VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }},
737 { &hf_lapd_ftype_s_u_ext,
738 { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
739 VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }},
741 { &hf_lapd_checksum,
742 { "Checksum", "lapd.checksum", FT_UINT16, BASE_HEX,
743 NULL, 0x0, "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
745 { &hf_lapd_checksum_status,
746 { "Checksum Status", "lapd.checksum.status", FT_UINT8, BASE_NONE,
747 VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
749 static int *ett[] = {
750 &ett_lapd,
751 &ett_lapd_address,
752 &ett_lapd_control,
753 &ett_lapd_checksum
756 static ei_register_info ei[] = {
757 { &ei_lapd_abort, { "lapd.abort.expert", PI_PROTOCOL, PI_ERROR, "Formatted message", EXPFILL }},
758 { &ei_lapd_checksum_bad, { "lapd.checksum_bad.expert", PI_CHECKSUM, PI_WARN, "Bad FCS", EXPFILL }},
761 module_t *lapd_module;
762 expert_module_t* expert_lapd;
764 proto_lapd = proto_register_protocol("Link Access Procedure, Channel D (LAPD)",
765 "LAPD", "lapd");
766 proto_register_field_array (proto_lapd, hf, array_length(hf));
767 proto_register_subtree_array(ett, array_length(ett));
768 expert_lapd = expert_register_protocol(proto_lapd);
769 expert_register_field_array(expert_lapd, ei, array_length(ei));
771 lapd_handle = register_dissector("lapd", dissect_lapd, proto_lapd);
772 lapd_phdr_handle = register_dissector("lapd-phdr", dissect_lapd_phdr, proto_lapd);
773 linux_lapd_handle = register_dissector("linux-lapd", dissect_linux_lapd, proto_lapd);
774 lapd_bitstream_handle = register_dissector("lapd-bitstream", dissect_lapd_bitstream, proto_lapd);
776 lapd_sapi_dissector_table = register_dissector_table("lapd.sapi",
777 "LAPD SAPI", proto_lapd, FT_UINT16, BASE_DEC);
779 lapd_gsm_sapi_dissector_table = register_dissector_table("lapd.gsm.sapi",
780 "LAPD GSM SAPI", proto_lapd, FT_UINT16, BASE_DEC);
782 lapd_module = prefs_register_protocol(proto_lapd, NULL);
784 prefs_register_bool_preference(lapd_module, "use_gsm_sapi_values",
785 "Use GSM SAPI values",
786 "Use SAPI values as specified in TS 48 056",
787 &global_lapd_gsm_sapis);
788 prefs_register_obsolete_preference(lapd_module, "rtp_payload_type");
791 void
792 proto_reg_handoff_lapd(void)
794 dissector_handle_t lapd_frame_handle;
796 dissector_add_uint("wtap_encap", WTAP_ENCAP_LINUX_LAPD, linux_lapd_handle);
798 lapd_frame_handle = create_dissector_handle(dissect_lapd_frame, proto_lapd);
799 dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPD, lapd_frame_handle);
801 dissector_add_for_decode_as("l2tp.pw_type", lapd_handle);
802 dissector_add_for_decode_as_with_preference("sctp.ppi", lapd_handle);
803 dissector_add_for_decode_as("sctp.port", lapd_handle);
804 dissector_add_uint_range_with_preference("udp.port", "", lapd_handle);
805 dissector_add_uint_range_with_preference("rtp.pt", "", lapd_bitstream_handle);
810 * Editor modelines - https://www.wireshark.org/tools/modelines.html
812 * Local variables:
813 * c-basic-offset: 8
814 * tab-width: 8
815 * indent-tabs-mode: t
816 * End:
818 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
819 * :indentSize=8:tabSize=8:noTabs=false: