Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-lapd.c
Line
Count
Source
1
/* packet-lapd.c
2
 * Routines for LAPD frame disassembly
3
 * Gilbert Ramirez <gram@alumni.rice.edu>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
/*
12
 * LAPD bitstream over RTP handling
13
 * Copyright 2008, Ericsson AB
14
 * Written by Balint Reczey <balint.reczey@ericsson.com>
15
 *
16
 * ISDN/LAPD references:
17
 *
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
24
 */
25
26
#include "config.h"
27
28
#include <epan/packet.h>
29
#include <epan/conversation.h>
30
#include <epan/crc16-tvb.h>
31
#include <epan/prefs.h>
32
#include <wiretap/wtap.h>
33
#include <epan/expert.h>
34
#include <epan/proto_data.h>
35
#include <epan/tfs.h>
36
#include <wsutil/array.h>
37
#include "packet-lapd.h"
38
#include "packet-xdlc.h"
39
40
void proto_register_lapd(void);
41
void proto_reg_handoff_lapd(void);
42
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;
67
68
static int ett_lapd;
69
static int ett_lapd_address;
70
static int ett_lapd_control;
71
static int ett_lapd_checksum;
72
73
static expert_field ei_lapd_abort;
74
static expert_field ei_lapd_checksum_bad;
75
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;
80
81
static dissector_table_t lapd_sapi_dissector_table;
82
static dissector_table_t lapd_gsm_sapi_dissector_table;
83
84
/* Whether to use GSM SAPI vals or not */
85
static bool global_lapd_gsm_sapis;
86
87
/*
88
 * Bits in the address field.
89
 */
90
63
#define LAPD_SAPI   0xfc00  /* Service Access Point Identifier */
91
35
#define LAPD_SAPI_SHIFT   10
92
49
#define LAPD_CR     0x0200  /* Command/Response bit */
93
14
#define LAPD_EA1    0x0100  /* First Address Extension bit */
94
49
#define LAPD_TEI    0x00fe  /* Terminal Endpoint Identifier */
95
35
#define LAPD_TEI_SHIFT    1
96
14
#define LAPD_EA2    0x0001  /* Second Address Extension bit */
97
98
4
#define LAPD_DIR_USER_TO_NETWORK  0
99
62
#define LAPD_DIR_NETWORK_TO_USER  1
100
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 }
105
};
106
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 }
113
};
114
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 }
122
};
123
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
135
};
136
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
148
};
149
150
48
#define MAX_LAPD_PACKET_LEN 1024
151
152
/* LAPD frame detection state */
153
enum lapd_bitstream_states {OUT_OF_SYNC, FLAGS, DATA};
154
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
  uint8_t         data[MAX_LAPD_PACKET_LEN];
161
  int             data_len;
162
} lapd_byte_state_t;
163
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;
168
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, const uint8_t *data, int data_len)
172
40
{
173
40
  ptr->state = state;
174
40
  ptr->full_byte = full_byte;
175
40
  ptr->bit_offset = bit_offset;
176
40
  ptr->ones = ones;
177
178
40
  ptr->data_len = MIN((int)sizeof(ptr->data), data_len);
179
40
  memcpy(ptr->data, data, ptr->data_len);
180
40
}
181
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;
190
191
192
static void
193
dissect_lapd_full(tvbuff_t*, packet_info*, proto_tree*, uint32_t);
194
195
/* got new LAPD frame byte */
196
48
static void new_byte(char full_byte, uint8_t data[], int *data_len) {
197
48
  if (*data_len < MAX_LAPD_PACKET_LEN) {
198
48
    data[*data_len] = full_byte;
199
48
    (*data_len)++;
200
48
  } else {
201
    /* XXX : we are not prepared for that big messages, drop the last byte */
202
0
  }
203
48
}
204
205
static void
206
lapd_log_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *msg)
207
28
{
208
28
  proto_item *ti;
209
210
28
  ti = proto_tree_add_item(tree, proto_lapd, tvb, offset, 1, ENC_NA);
211
28
  expert_add_info_format(pinfo, ti, &ei_lapd_abort, "%s", msg);
212
28
}
213
214
/*
215
 * Flags to pass to dissect_lapd_full.
216
 */
217
38
#define LAPD_HAS_CRC      0x00000001
218
103
#define LAPD_HAS_DIRECTION    0x00000002
219
33
#define LAPD_HAS_LINUX_SLL    0x00000004
220
70
#define LAPD_USER_TO_NETWORK    0x00000008
221
0
#define LAPD_NETWORK_IS_REMOTE    0x00000010
222
0
#define LAPD_USER_IS_REMOTE   0x00000020
223
224
static int
225
dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissector_data _U_)
226
27
{
227
27
  uint8_t   byte, full_byte = 0x00, bit_offset = 0;
228
27
  bool  bit;
229
27
  uint8_t   i, ones = 0, data[MAX_LAPD_PACKET_LEN];
230
27
  int   data_len = 0;
231
27
  int   offset = 0, available;
232
27
  uint8_t   *buff;
233
27
  tvbuff_t  *new_tvb;
234
235
27
  enum lapd_bitstream_states state = OUT_OF_SYNC;
236
27
  lapd_ppi_t    *lapd_ppi;
237
27
  conversation_t    *conversation = NULL;
238
27
  lapd_convo_data_t *convo_data = NULL;
239
27
  lapd_byte_state_t *lapd_byte_state, *prev_byte_state = NULL;
240
27
  bool    forward_stream = true;
241
242
  /* get remaining data from previous packets */
243
27
  conversation = find_or_create_conversation(pinfo);
244
27
  lapd_ppi = (lapd_ppi_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0);
245
27
  if (lapd_ppi) {
246
0
    prev_byte_state = &lapd_ppi->start_byte_state;
247
0
    if (prev_byte_state) {
248
0
      state = prev_byte_state->state;
249
0
      full_byte = prev_byte_state->full_byte;
250
0
      bit_offset = prev_byte_state->bit_offset;
251
0
      ones = prev_byte_state->ones;
252
0
      memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
253
0
      data_len = prev_byte_state->data_len;
254
0
    }
255
256
27
  } else if (conversation) {
257
27
    convo_data = (lapd_convo_data_t*)conversation_get_proto_data(conversation, proto_lapd);
258
27
    if (NULL != convo_data) {
259
15
      if (addresses_equal(&convo_data->addr_a, &pinfo->src)
260
15
          && addresses_equal(&convo_data->addr_b, &pinfo->dst)
261
15
          && convo_data-> port_a == pinfo->srcport
262
15
          && convo_data-> port_b == pinfo->destport) {
263
        /* "forward" direction */
264
15
        forward_stream = true;
265
15
        prev_byte_state = convo_data->byte_state_a;
266
15
      } else if (addresses_equal(&convo_data-> addr_b, &pinfo->src)
267
0
          && addresses_equal(&convo_data->addr_a, &pinfo->dst)
268
0
          && convo_data-> port_b == pinfo->srcport
269
0
          && convo_data-> port_a == pinfo->destport) {
270
        /* "backward" direction */
271
0
        forward_stream = false;
272
0
        prev_byte_state = convo_data->byte_state_b;
273
0
      }
274
15
    }
275
27
    if (prev_byte_state) {
276
15
      state = prev_byte_state->state;
277
15
      full_byte = prev_byte_state->full_byte;
278
15
      bit_offset = prev_byte_state->bit_offset;
279
15
      ones = prev_byte_state->ones;
280
281
15
      memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
282
15
      data_len = prev_byte_state->data_len;
283
15
    }
284
27
  }
285
286
  /* Consume tvb bytes */
287
27
  available = tvb_reported_length_remaining(tvb, offset);
288
225
  while (offset < available) {
289
198
    byte = tvb_get_uint8(tvb,offset);
290
198
    offset++;
291
1.74k
    for (i=0; i < 8; i++) { /* cycle through bits */
292
1.54k
      bit = byte & (0x80 >> i) ? true : false;
293
294
      /* consume a bit */
295
1.54k
      if (bit) {
296
794
        ones++;
297
794
        full_byte |= (1 << bit_offset++);
298
794
      } else {
299
751
        if (ones == 5 && state == DATA) {
300
          /* we don't increase bit_offset, it is an inserted zero */
301
748
        } else if (ones == 6 && state == DATA) { /* probably starting flag sequence */
302
3
          buff = (uint8_t *)wmem_memdup(pinfo->pool, data, data_len);
303
          /* Allocate new tvb for the LAPD frame */
304
3
          new_tvb = tvb_new_child_real_data(tvb, buff, data_len, data_len);
305
3
          add_new_data_source(pinfo, new_tvb, "Decoded LAPD bitstream");
306
3
          data_len = 0;
307
3
          state = FLAGS;
308
3
          bit_offset++;
309
310
3
          if (full_byte != 0x7E) {
311
3
            data_len = 0;
312
3
            state = OUT_OF_SYNC;
313
3
            lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 6 ones that don't match 0x7e!");
314
315
3
          }
316
3
          dissect_lapd_full(new_tvb, pinfo, tree, LAPD_HAS_CRC);
317
745
        } else if (ones >= 7) { /* frame reset or 11111111 flag byte */
318
25
          data_len = 0;
319
25
          state = OUT_OF_SYNC;
320
25
          bit_offset++;
321
322
25
          lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 7 ones!");
323
720
        } else {
324
720
          bit_offset++;
325
720
        }
326
751
        ones = 0;
327
751
      }
328
329
1.54k
      if (bit_offset == 8) { /* we have a new complete byte */
330
975
        switch (state) {
331
915
          case OUT_OF_SYNC:
332
915
            if (full_byte == 0x7E) { /* we have a flag byte */
333
11
              state = FLAGS;
334
11
              full_byte = 0x00;
335
11
              bit_offset = 0;
336
904
            } else { /* no sync yet, wait for a new byte */
337
904
              full_byte = (full_byte >> 1) & 0x7F;
338
904
              bit_offset--;
339
904
            }
340
915
            break;
341
342
23
          case FLAGS:
343
23
            if (full_byte == 0x7E) { /* we have a flag byte */
344
12
              full_byte = 0x00;
345
12
              bit_offset = 0;
346
12
            } else { /* we got the first data byte */
347
11
              state = DATA;
348
11
              new_byte(full_byte, data, &data_len);
349
11
              full_byte = 0x00;
350
11
              bit_offset = 0;
351
11
            }
352
23
            break;
353
354
37
          case DATA:
355
            /* we got a new data byte */
356
37
            new_byte(full_byte, data, &data_len);
357
37
            full_byte = 0x00;
358
37
            bit_offset = 0;
359
37
            break;
360
975
        }
361
975
      }
362
1.54k
    }
363
198
  }
364
365
27
  {
366
27
    if (NULL == p_get_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0)) {
367
      /* Per packet information */
368
20
      lapd_ppi = wmem_new(wmem_file_scope(), lapd_ppi_t);
369
20
      lapd_ppi->has_crc = true;
370
20
      if (prev_byte_state)
371
13
        fill_lapd_byte_state(&lapd_ppi->start_byte_state, prev_byte_state->state,
372
13
            prev_byte_state->full_byte, prev_byte_state->bit_offset,
373
13
            prev_byte_state->ones, prev_byte_state->data, prev_byte_state->data_len);
374
7
      else
375
7
        fill_lapd_byte_state(&lapd_ppi->start_byte_state, OUT_OF_SYNC, 0x00, 0, 0, data, 0);
376
377
20
      p_add_proto_data(wmem_file_scope(), pinfo, proto_lapd, 0, lapd_ppi);
378
379
380
      /* Conversation info*/
381
382
20
      if (conversation) {
383
20
        if (convo_data) { /* already have lapd convo data */
384
13
          if (forward_stream) {
385
13
            if (!convo_data->byte_state_a)
386
0
              convo_data->byte_state_a = wmem_new(wmem_file_scope(), lapd_byte_state_t);
387
13
            fill_lapd_byte_state(convo_data->byte_state_a, state, full_byte, bit_offset, ones, data, data_len);
388
13
          } else {
389
0
            if (!convo_data->byte_state_b)
390
0
              convo_data->byte_state_b = wmem_new(wmem_file_scope(), lapd_byte_state_t);
391
0
            fill_lapd_byte_state(convo_data->byte_state_b, state, full_byte, bit_offset, ones, data, data_len);
392
0
          }
393
13
        } else { /* lapd convo data has to be created */
394
7
          lapd_byte_state = wmem_new(wmem_file_scope(), lapd_byte_state_t);
395
7
          fill_lapd_byte_state(lapd_byte_state, state, full_byte, bit_offset, ones, data, data_len);
396
7
          convo_data = wmem_new(wmem_file_scope(), lapd_convo_data_t);
397
7
          copy_address_wmem(wmem_file_scope(), &convo_data->addr_a, &pinfo->src);
398
7
          copy_address_wmem(wmem_file_scope(), &convo_data->addr_b, &pinfo->dst);
399
7
          convo_data->port_a = pinfo->srcport;
400
7
          convo_data->port_b = pinfo->destport;
401
7
          convo_data->byte_state_a = lapd_byte_state;
402
7
          convo_data->byte_state_b = NULL;
403
7
          conversation_add_proto_data(conversation, proto_lapd, convo_data);
404
7
        }
405
20
      }
406
20
    }
407
27
  }
408
27
  return tvb_captured_length(tvb);
409
27
}
410
411
static int
412
dissect_linux_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
413
0
{
414
0
  uint32_t flags = LAPD_HAS_LINUX_SLL | LAPD_HAS_DIRECTION;
415
416
  /* frame is captured via libpcap */
417
0
  if (pinfo->pseudo_header->lapd.pkttype == 4 /*PACKET_OUTGOING*/) {
418
0
    if (pinfo->pseudo_header->lapd.we_network) {
419
      /*
420
       * We're the network side, so the user is remote,
421
       * and we're sending it, so this is Network->User.
422
       */
423
0
      flags |= LAPD_USER_IS_REMOTE;
424
0
    } else {
425
      /*
426
       * We're the user side, so the network is remote,
427
       * and we're sending it, so this is User->Network.
428
       */
429
0
      flags |= LAPD_NETWORK_IS_REMOTE | LAPD_USER_TO_NETWORK;
430
0
    }
431
0
  }
432
0
  else if (pinfo->pseudo_header->lapd.pkttype == 3 /*PACKET_OTHERHOST*/) {
433
    /*
434
     * We must be a TE, sniffing what other TE transmit, so
435
     * both sides are remote.
436
     *
437
     * XXX - do we know whether it's User->Network or
438
     * Network->User?
439
     */
440
0
    flags |= LAPD_USER_IS_REMOTE | LAPD_NETWORK_IS_REMOTE | LAPD_USER_TO_NETWORK;
441
0
  }
442
0
  else {
443
    /* The frame is incoming */
444
0
    if (pinfo->pseudo_header->lapd.we_network) {
445
      /*
446
       * We're the network side, so the user is remote,
447
       * and we received it, so this is User->Network.
448
       */
449
0
      flags |= LAPD_USER_IS_REMOTE | LAPD_USER_TO_NETWORK;
450
0
    } else {
451
      /*
452
       * We're the user side, so the network is remote,
453
       * and we received it, so this is Network->User.
454
       */
455
0
      flags |= LAPD_NETWORK_IS_REMOTE;
456
0
    }
457
0
  }
458
0
  dissect_lapd_full(tvb, pinfo, tree, flags);
459
0
  return tvb_captured_length(tvb);
460
0
}
461
462
/*
463
 * Called from dissectors, such as the ISDN dissector, that supply a
464
 * struct isdn_pndr giving the packet direction.
465
 */
466
static int
467
dissect_lapd_phdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
468
33
{
469
33
  struct isdn_phdr *isdn = (struct isdn_phdr *)data;
470
33
  uint32_t flags = LAPD_HAS_DIRECTION;
471
472
33
  if (isdn->uton)
473
4
    flags |= LAPD_USER_TO_NETWORK;
474
33
  dissect_lapd_full(tvb, pinfo, tree, flags);
475
33
  return tvb_captured_length(tvb);
476
33
}
477
478
/*
479
 * Called for link-layer encapsulation.
480
 */
481
static int
482
dissect_lapd_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
483
0
{
484
0
  uint32_t flags;
485
0
  uint32_t lapd_flags = 0;
486
487
  /*
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.
492
   */
493
0
  if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_uint32_option_value(pinfo->rec->block, OPT_PKT_FLAGS, &flags)) {
494
0
    switch (PACK_FLAGS_DIRECTION(flags)) {
495
496
0
    case PACK_FLAGS_DIRECTION_OUTBOUND:
497
0
      lapd_flags |= LAPD_HAS_DIRECTION | LAPD_USER_TO_NETWORK;
498
0
      break;
499
500
0
    case PACK_FLAGS_DIRECTION_INBOUND:
501
0
      lapd_flags |= LAPD_HAS_DIRECTION;
502
0
      break;
503
504
0
    default:
505
0
      break;
506
0
    }
507
0
  }
508
0
  dissect_lapd_full(tvb, pinfo, tree, lapd_flags);
509
0
  return tvb_captured_length(tvb);
510
0
}
511
512
static int
513
dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
514
0
{
515
  /* XXX - direction is unknown */
516
0
  dissect_lapd_full(tvb, pinfo, tree, 0);
517
0
  return tvb_captured_length(tvb);
518
0
}
519
520
static void
521
dissect_lapd_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t flags)
522
35
{
523
35
  proto_tree  *lapd_tree, *addr_tree;
524
35
  proto_item  *lapd_ti, *addr_ti;
525
35
  uint16_t    control;
526
35
  int   lapd_header_len, checksum_offset;
527
35
  uint16_t    addr, cr, sapi, tei;
528
35
  bool  is_response = 0;
529
35
  tvbuff_t  *next_tvb;
530
35
  const char  *srcname = "?";
531
35
  const char  *dstname = "?";
532
533
35
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPD");
534
35
  col_clear(pinfo->cinfo, COL_INFO);
535
536
35
  addr = tvb_get_ntohs(tvb, 0);
537
35
  cr = addr & LAPD_CR;
538
35
  tei = (addr & LAPD_TEI) >> LAPD_TEI_SHIFT;
539
35
  sapi = (addr & LAPD_SAPI) >> LAPD_SAPI_SHIFT;
540
35
  lapd_header_len = 2;  /* addr */
541
542
  /* Append TEI to info field */
543
35
  col_append_fstr(pinfo->cinfo, COL_INFO, "TEI:%02u ", tei);
544
35
  col_set_fence(pinfo->cinfo, COL_INFO);
545
546
35
  if (flags & LAPD_HAS_DIRECTION) {
547
33
    if (flags & LAPD_USER_TO_NETWORK) {
548
4
      is_response = cr ? true : false;
549
4
      if (flags & LAPD_HAS_LINUX_SLL) {
550
0
        srcname = (flags & LAPD_USER_IS_REMOTE) ?
551
0
            "Remote User" : "Local User";
552
0
        dstname = (flags & LAPD_NETWORK_IS_REMOTE) ?
553
0
            "Remote Network" : "Local Network";
554
4
      } else {
555
4
        srcname = "User";
556
4
        dstname = "Network";
557
4
      }
558
29
    } else {
559
29
      is_response = cr ? false : true;
560
29
      if (flags & LAPD_HAS_LINUX_SLL) {
561
0
        srcname = (flags & LAPD_NETWORK_IS_REMOTE) ?
562
0
            "Remote Network" : "Local Network";
563
0
        dstname = (flags & LAPD_USER_IS_REMOTE) ?
564
0
            "Remote User" : "Local User";
565
29
      } else {
566
29
        srcname = "Network";
567
29
        dstname = "User";
568
29
      }
569
29
    }
570
33
  }
571
35
  set_address(&pinfo->dl_dst, AT_STRINGZ, (int)strlen(dstname) + 1, dstname);
572
35
  set_address(&pinfo->dl_src, AT_STRINGZ, (int)strlen(srcname) + 1, srcname);
573
35
  copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
574
35
  copy_address_shallow(&pinfo->src, &pinfo->dl_src);
575
576
35
  if (tree) {
577
35
    proto_item *direction_ti;
578
579
35
    lapd_ti = proto_tree_add_item(tree, proto_lapd, tvb, 0, -1,
580
35
        ENC_NA);
581
35
    lapd_tree = proto_item_add_subtree(lapd_ti, ett_lapd);
582
583
    /*
584
     * Don't show the direction if we don't know it.
585
     */
586
35
    if (flags & LAPD_HAS_DIRECTION) {
587
33
      direction_ti = proto_tree_add_uint(lapd_tree, hf_lapd_direction,
588
33
                                         tvb, 0, 0,
589
33
                                         (flags & LAPD_USER_TO_NETWORK) ? LAPD_DIR_USER_TO_NETWORK : LAPD_DIR_NETWORK_TO_USER);
590
33
      proto_item_set_generated(direction_ti);
591
33
    }
592
593
35
    addr_ti = proto_tree_add_uint(lapd_tree, hf_lapd_address, tvb,
594
35
        0, 2, addr);
595
35
    addr_tree = proto_item_add_subtree(addr_ti, ett_lapd_address);
596
597
35
    if(global_lapd_gsm_sapis){
598
0
      proto_tree_add_uint(addr_tree, hf_lapd_gsm_sapi,tvb, 0, 1, addr);
599
35
    }else{
600
35
      proto_tree_add_uint(addr_tree, hf_lapd_sapi,tvb, 0, 1, addr);
601
35
    }
602
35
    proto_tree_add_uint(addr_tree, hf_lapd_cr,  tvb, 0, 1, addr);
603
35
    proto_tree_add_uint(addr_tree, hf_lapd_ea1, tvb, 0, 1, addr);
604
35
    proto_tree_add_uint(addr_tree, hf_lapd_tei, tvb, 1, 1, addr);
605
35
    proto_tree_add_uint(addr_tree, hf_lapd_ea2, tvb, 1, 1, addr);
606
35
  }
607
0
  else {
608
0
    lapd_ti = NULL;
609
0
    lapd_tree = NULL;
610
0
  }
611
612
35
  control = dissect_xdlc_control(tvb, 2, pinfo, lapd_tree, hf_lapd_control,
613
35
      ett_lapd_control, &lapd_cf_items, &lapd_cf_items_ext, NULL, NULL,
614
35
      is_response, true, false);
615
35
  lapd_header_len += XDLC_CONTROL_LEN(control, true);
616
617
35
  if (tree)
618
35
    proto_item_set_len(lapd_ti, lapd_header_len);
619
620
35
  if (flags & LAPD_HAS_CRC) {
621
622
    /* check checksum */
623
2
    checksum_offset = tvb_reported_length(tvb) - 2;
624
625
2
    proto_tree_add_checksum(lapd_tree, tvb, checksum_offset, hf_lapd_checksum, hf_lapd_checksum_status, &ei_lapd_checksum_bad, pinfo,
626
2
                crc16_ccitt_tvb(tvb, tvb_reported_length(tvb) - 2), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
627
628
2
    next_tvb = tvb_new_subset_length(tvb, lapd_header_len, tvb_reported_length_remaining(tvb,lapd_header_len) - 2);
629
630
2
  } else
631
33
    next_tvb = tvb_new_subset_remaining(tvb, lapd_header_len);
632
633
  /* Dissection done, append " | " to COL_INFO */
634
35
  col_append_str(pinfo->cinfo, COL_INFO, " | ");
635
35
  col_set_fence(pinfo->cinfo, COL_INFO);
636
637
35
  if (XDLC_IS_INFORMATION(control)) {
638
    /* call next protocol */
639
33
    if(global_lapd_gsm_sapis){
640
0
      if (!dissector_try_uint(lapd_gsm_sapi_dissector_table, sapi,
641
0
        next_tvb, pinfo, tree))
642
0
        call_data_dissector(next_tvb, pinfo, tree);
643
33
    }else{
644
33
      if (!dissector_try_uint(lapd_sapi_dissector_table, sapi,
645
33
        next_tvb, pinfo, tree))
646
3
        call_data_dissector(next_tvb, pinfo, tree);
647
33
    }
648
33
  } else
649
2
    call_data_dissector(next_tvb, pinfo, tree);
650
35
}
651
652
void
653
proto_register_lapd(void)
654
14
{
655
14
  static hf_register_info hf[] = {
656
657
14
    { &hf_lapd_direction,
658
14
      { "Direction", "lapd.direction", FT_UINT32, BASE_DEC, VALS(lapd_direction_vals), 0x0,
659
14
        NULL, HFILL }},
660
661
14
    { &hf_lapd_address,
662
14
      { "Address Field", "lapd.address", FT_UINT16, BASE_HEX, NULL, 0x0,
663
14
        NULL, HFILL }},
664
665
14
    { &hf_lapd_sapi,
666
14
      { "SAPI", "lapd.sapi", FT_UINT16, BASE_DEC, VALS(lapd_sapi_vals), LAPD_SAPI,
667
14
        "Service Access Point Identifier", HFILL }},
668
669
14
    { &hf_lapd_gsm_sapi,
670
14
      { "SAPI", "lapd.sapi", FT_UINT16, BASE_DEC, VALS(lapd_gsm_sapi_vals), LAPD_SAPI,
671
14
        "Service Access Point Identifier", HFILL }},
672
673
14
    { &hf_lapd_cr,
674
14
      { "C/R", "lapd.cr", FT_UINT16, BASE_DEC, NULL, LAPD_CR,
675
14
        "Command/Response bit", HFILL }},
676
677
14
    { &hf_lapd_ea1,
678
14
      { "EA1", "lapd.ea1", FT_UINT16, BASE_DEC, NULL, LAPD_EA1,
679
14
        "First Address Extension bit", HFILL }},
680
681
14
    { &hf_lapd_tei,
682
14
      { "TEI", "lapd.tei", FT_UINT16, BASE_DEC, NULL, LAPD_TEI,
683
14
        "Terminal Endpoint Identifier", HFILL }},
684
685
14
    { &hf_lapd_ea2,
686
14
      { "EA2", "lapd.ea2", FT_UINT16, BASE_DEC, NULL, LAPD_EA2,
687
14
        "Second Address Extension bit", HFILL }},
688
689
14
    { &hf_lapd_control,
690
14
      { "Control Field", "lapd.control", FT_UINT16, BASE_HEX, NULL, 0x0,
691
14
        NULL, HFILL }},
692
693
14
    { &hf_lapd_n_r,
694
14
      { "N(R)", "lapd.control.n_r", FT_UINT16, BASE_DEC,
695
14
        NULL, XDLC_N_R_EXT_MASK, NULL, HFILL }},
696
697
14
    { &hf_lapd_n_s,
698
14
      { "N(S)", "lapd.control.n_s", FT_UINT16, BASE_DEC,
699
14
        NULL, XDLC_N_S_EXT_MASK, NULL, HFILL }},
700
701
14
    { &hf_lapd_p,
702
14
      { "Poll", "lapd.control.p", FT_BOOLEAN, 8,
703
14
        TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }},
704
705
14
    { &hf_lapd_p_ext,
706
14
      { "Poll", "lapd.control.p", FT_BOOLEAN, 16,
707
14
        TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }},
708
709
14
    { &hf_lapd_f,
710
14
      { "Final", "lapd.control.f", FT_BOOLEAN, 8,
711
14
        TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }},
712
713
14
    { &hf_lapd_f_ext,
714
14
      { "Final", "lapd.control.f", FT_BOOLEAN, 16,
715
14
        TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }},
716
717
14
    { &hf_lapd_s_ftype,
718
14
      { "Supervisory frame type", "lapd.control.s_ftype", FT_UINT16, BASE_HEX,
719
14
        VALS(stype_vals), XDLC_S_FTYPE_MASK, NULL, HFILL }},
720
721
14
    { &hf_lapd_u_modifier_cmd,
722
14
      { "Command", "lapd.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
723
14
        VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, NULL, HFILL }},
724
725
14
    { &hf_lapd_u_modifier_resp,
726
14
      { "Response", "lapd.control.u_modifier_resp", FT_UINT8, BASE_HEX,
727
14
        VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, NULL, HFILL }},
728
729
14
    { &hf_lapd_ftype_i,
730
14
      { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
731
14
        VALS(ftype_vals), XDLC_I_MASK, NULL, HFILL }},
732
733
14
    { &hf_lapd_ftype_s_u,
734
14
      { "Frame type", "lapd.control.ftype", FT_UINT8, BASE_HEX,
735
14
        VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }},
736
737
14
    { &hf_lapd_ftype_s_u_ext,
738
14
      { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
739
14
        VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }},
740
741
14
    { &hf_lapd_checksum,
742
14
      { "Checksum", "lapd.checksum", FT_UINT16, BASE_HEX,
743
14
        NULL, 0x0, "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
744
745
14
    { &hf_lapd_checksum_status,
746
14
      { "Checksum Status", "lapd.checksum.status", FT_UINT8, BASE_NONE,
747
14
        VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
748
14
  };
749
14
  static int *ett[] = {
750
14
    &ett_lapd,
751
14
    &ett_lapd_address,
752
14
    &ett_lapd_control,
753
14
    &ett_lapd_checksum
754
14
  };
755
756
14
  static ei_register_info ei[] = {
757
14
    { &ei_lapd_abort, { "lapd.abort.expert", PI_PROTOCOL, PI_ERROR, "Formatted message", EXPFILL }},
758
14
    { &ei_lapd_checksum_bad, { "lapd.checksum_bad.expert", PI_CHECKSUM, PI_WARN, "Bad FCS", EXPFILL }},
759
14
  };
760
761
14
  module_t *lapd_module;
762
14
  expert_module_t* expert_lapd;
763
764
14
  proto_lapd = proto_register_protocol("Link Access Procedure, Channel D (LAPD)",
765
14
               "LAPD", "lapd");
766
14
  proto_register_field_array (proto_lapd, hf, array_length(hf));
767
14
  proto_register_subtree_array(ett, array_length(ett));
768
14
  expert_lapd = expert_register_protocol(proto_lapd);
769
14
  expert_register_field_array(expert_lapd, ei, array_length(ei));
770
771
14
  lapd_handle = register_dissector("lapd", dissect_lapd, proto_lapd);
772
14
  lapd_phdr_handle = register_dissector("lapd-phdr", dissect_lapd_phdr, proto_lapd);
773
14
  linux_lapd_handle = register_dissector("linux-lapd", dissect_linux_lapd, proto_lapd);
774
14
  lapd_bitstream_handle = register_dissector("lapd-bitstream", dissect_lapd_bitstream, proto_lapd);
775
776
14
  lapd_sapi_dissector_table = register_dissector_table("lapd.sapi",
777
14
                   "LAPD SAPI", proto_lapd, FT_UINT16, BASE_DEC);
778
779
14
  lapd_gsm_sapi_dissector_table = register_dissector_table("lapd.gsm.sapi",
780
14
                 "LAPD GSM SAPI", proto_lapd, FT_UINT16, BASE_DEC);
781
782
14
  lapd_module = prefs_register_protocol(proto_lapd, NULL);
783
784
14
  prefs_register_bool_preference(lapd_module, "use_gsm_sapi_values",
785
14
               "Use GSM SAPI values",
786
14
               "Use SAPI values as specified in TS 48 056",
787
14
               &global_lapd_gsm_sapis);
788
14
  prefs_register_obsolete_preference(lapd_module, "rtp_payload_type");
789
14
}
790
791
void
792
proto_reg_handoff_lapd(void)
793
14
{
794
14
  dissector_handle_t lapd_frame_handle;
795
796
14
  dissector_add_uint("wtap_encap", WTAP_ENCAP_LINUX_LAPD, linux_lapd_handle);
797
798
14
  lapd_frame_handle = create_dissector_handle(dissect_lapd_frame, proto_lapd);
799
14
  dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPD, lapd_frame_handle);
800
801
14
  dissector_add_for_decode_as("l2tp.pw_type", lapd_handle);
802
14
  dissector_add_for_decode_as_with_preference("sctp.ppi", lapd_handle);
803
14
  dissector_add_for_decode_as("sctp.port", lapd_handle);
804
14
  dissector_add_uint_range_with_preference("udp.port", "", lapd_handle);
805
14
  dissector_add_uint_range_with_preference("rtp.pt", "", lapd_bitstream_handle);
806
807
14
}
808
809
/*
810
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
811
 *
812
 * Local variables:
813
 * c-basic-offset: 8
814
 * tab-width: 8
815
 * indent-tabs-mode: t
816
 * End:
817
 *
818
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
819
 * :indentSize=8:tabSize=8:noTabs=false:
820
 */