3 |
3 |
*
|
4 |
4 |
* (C) 2008-2013 by Harald Welte <laforge@gnumonks.org>
|
5 |
5 |
* (C) 2011 by Holger Hans Peter Freyther
|
|
6 |
* (C) 2016 by Sysmocom s.f.m.c. GmbH, Berlin
|
6 |
7 |
*
|
7 |
8 |
* Wireshark - Network traffic analyzer
|
8 |
9 |
* By Gerald Combs <gerald@wireshark.org>
|
... | ... | |
41 |
42 |
#include "config.h"
|
42 |
43 |
|
43 |
44 |
#include <epan/packet.h>
|
|
45 |
#include <epan/dissectors/packet-gsm_rlcmac.h>
|
44 |
46 |
|
45 |
47 |
#include "packet-tetra.h"
|
46 |
48 |
|
... | ... | |
463 |
465 |
tetra_dissect_pdu(tetra_chan, TETRA_DOWNLINK, payload_tvb, tree, pinfo);
|
464 |
466 |
}
|
465 |
467 |
|
|
468 |
static void
|
|
469 |
setup_rlc_mac_priv(RlcMacPrivateData_t *rm, gsize len, gboolean is_uplink,
|
|
470 |
gsize *n_calls, gsize *data_block_bits, gsize *data_block_offsets)
|
|
471 |
{
|
|
472 |
gsize nc, dbl = 0, dbo[2] = {0,0};
|
|
473 |
RLCMAC_block_format_t frm;
|
|
474 |
gsize mcs = 0;
|
|
475 |
|
|
476 |
memset(rm, 0, sizeof(*rm));
|
|
477 |
rm->magic = GSM_RLC_MAC_MAGIC_NUMBER;
|
|
478 |
|
|
479 |
switch (len)
|
|
480 |
{
|
|
481 |
default:
|
|
482 |
if (len <= 5 && is_uplink) {
|
|
483 |
/* Assume random access burst */
|
|
484 |
frm = RLCMAC_PRACH;
|
|
485 |
nc = 1;
|
|
486 |
break;
|
|
487 |
}
|
|
488 |
/* fall through */
|
|
489 |
case 23: frm = RLCMAC_CS1; nc = 1; dbl = 20; break;
|
|
490 |
case 34: frm = RLCMAC_CS2; nc = 1; dbl = 30; break;
|
|
491 |
case 40: frm = RLCMAC_CS3; nc = 1; dbl = 36; break;
|
|
492 |
case 54: frm = RLCMAC_CS4; nc = 1; dbl = 50; break;
|
|
493 |
case 27: frm = RLCMAC_HDR_TYPE_3; mcs = 1; nc = 2; dbl = 22; break;
|
|
494 |
case 33: frm = RLCMAC_HDR_TYPE_3; mcs = 2; nc = 2; dbl = 28; break;
|
|
495 |
case 42: frm = RLCMAC_HDR_TYPE_3; mcs = 3; nc = 2; dbl = 37; break;
|
|
496 |
case 49: frm = RLCMAC_HDR_TYPE_3; mcs = 4; nc = 2; dbl = 44; break;
|
|
497 |
case 60:
|
|
498 |
case 61: frm = RLCMAC_HDR_TYPE_2; mcs = 5; nc = 2; dbl = 56; break;
|
|
499 |
case 78:
|
|
500 |
case 79: frm = RLCMAC_HDR_TYPE_2; mcs = 6; nc = 2; dbl = 74; break;
|
|
501 |
case 118:
|
|
502 |
case 119: frm = RLCMAC_HDR_TYPE_1; mcs = 7; nc = 3; dbl = 56; break;
|
|
503 |
case 142:
|
|
504 |
case 143: frm = RLCMAC_HDR_TYPE_1; mcs = 8; nc = 3; dbl = 68; break;
|
|
505 |
case 154:
|
|
506 |
case 155: frm = RLCMAC_HDR_TYPE_1; mcs = 9; nc = 3; dbl = 74; break;
|
|
507 |
}
|
|
508 |
|
|
509 |
switch (frm)
|
|
510 |
{
|
|
511 |
case RLCMAC_HDR_TYPE_1:
|
|
512 |
nc = 3;
|
|
513 |
dbo[0] = is_uplink ? 5*8 + 6 : 5*8 + 0;
|
|
514 |
dbo[1] = dbo[0] + dbl * 8 + 2;
|
|
515 |
break;
|
|
516 |
case RLCMAC_HDR_TYPE_2:
|
|
517 |
nc = 2;
|
|
518 |
dbo[0] = is_uplink ? 4*8 + 5 : 3*8 + 4;
|
|
519 |
break;
|
|
520 |
case RLCMAC_HDR_TYPE_3:
|
|
521 |
nc = 2;
|
|
522 |
dbo[0] = 3*8 + 7;
|
|
523 |
break;
|
|
524 |
default:
|
|
525 |
nc = 1;
|
|
526 |
break;
|
|
527 |
|
|
528 |
}
|
|
529 |
|
|
530 |
rm->block_format = frm;
|
|
531 |
rm->mcs = mcs;
|
|
532 |
*n_calls = nc;
|
|
533 |
*data_block_bits = dbl * 8 + 2;
|
|
534 |
data_block_offsets[0] = dbo[0];
|
|
535 |
data_block_offsets[1] = dbo[1];
|
|
536 |
}
|
|
537 |
|
|
538 |
static void clone_aligned_buffer_lsbf(gsize offset_bits, gsize length_bytes,
|
|
539 |
const guint8 *src, guint8 *buffer)
|
|
540 |
{
|
|
541 |
gsize hdr_bytes;
|
|
542 |
gsize extra_bits;
|
|
543 |
gsize i;
|
|
544 |
|
|
545 |
guint8 c, last_c;
|
|
546 |
guint8 *dst;
|
|
547 |
|
|
548 |
hdr_bytes = offset_bits / 8;
|
|
549 |
extra_bits = offset_bits % 8;
|
|
550 |
|
|
551 |
if (extra_bits == 0) {
|
|
552 |
/* It is aligned already */
|
|
553 |
memmove(buffer, src + hdr_bytes, length_bytes);
|
|
554 |
return;
|
|
555 |
}
|
|
556 |
|
|
557 |
dst = buffer;
|
|
558 |
src = src + hdr_bytes;
|
|
559 |
last_c = *(src++);
|
|
560 |
|
|
561 |
for (i = 0; i < length_bytes; i++) {
|
|
562 |
c = src[i];
|
|
563 |
*(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
|
|
564 |
last_c = c;
|
|
565 |
}
|
|
566 |
}
|
|
567 |
|
|
568 |
static tvbuff_t *get_egprs_data_block(tvbuff_t *tvb, gsize offset_bits,
|
|
569 |
gsize length_bits)
|
|
570 |
{
|
|
571 |
tvbuff_t *aligned_tvb;
|
|
572 |
const gsize initial_spare_bits = 6;
|
|
573 |
guint8 *aligned_buf;
|
|
574 |
gsize min_src_length_bytes = (offset_bits + length_bits + 7) / 8;
|
|
575 |
gsize length_bytes = (initial_spare_bits + length_bits + 7) / 8;
|
|
576 |
|
|
577 |
DISSECTOR_ASSERT(offset_bits >= initial_spare_bits);
|
|
578 |
|
|
579 |
tvb_ensure_bytes_exist(tvb, 0, min_src_length_bytes);
|
|
580 |
|
|
581 |
aligned_buf = (guint8 *) g_malloc(length_bytes);
|
|
582 |
|
|
583 |
/* Copy the data out of the tvb to an aligned buffer */
|
|
584 |
clone_aligned_buffer_lsbf(
|
|
585 |
offset_bits - initial_spare_bits, length_bytes,
|
|
586 |
tvb_get_ptr(tvb, 0, min_src_length_bytes),
|
|
587 |
aligned_buf);
|
|
588 |
|
|
589 |
/* clear spare bits and move block header bits to the right */
|
|
590 |
aligned_buf[0] = aligned_buf[0] >> initial_spare_bits;
|
|
591 |
|
|
592 |
aligned_tvb = tvb_new_child_real_data(tvb, aligned_buf,
|
|
593 |
length_bytes, length_bytes);
|
|
594 |
tvb_set_free_cb(aligned_tvb, g_free);
|
|
595 |
|
|
596 |
return aligned_tvb;
|
|
597 |
}
|
|
598 |
|
466 |
599 |
/* dissect a GSMTAP header and hand payload off to respective dissector */
|
467 |
600 |
static int
|
468 |
601 |
dissect_gsmtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
... | ... | |
712 |
845 |
if (sub_handle == GSMTAP_SUB_UMTS_RRC)
|
713 |
846 |
call_dissector(rrc_sub_handles[rrc_sub_handle], payload_tvb,
|
714 |
847 |
pinfo, tree);
|
|
848 |
else if (sub_handle == GSMTAP_SUB_UM_RLC_MAC_UL ||
|
|
849 |
sub_handle == GSMTAP_SUB_UM_RLC_MAC_DL) {
|
|
850 |
gsize num_calls;
|
|
851 |
gsize data_block_bits, data_block_offsets[2];
|
|
852 |
RlcMacPrivateData_t rlc_mac;
|
|
853 |
tvbuff_t *data_tvb;
|
|
854 |
|
|
855 |
setup_rlc_mac_priv(&rlc_mac,
|
|
856 |
tvb_reported_length(payload_tvb),
|
|
857 |
sub_handle == GSMTAP_SUB_UM_RLC_MAC_UL,
|
|
858 |
&num_calls, &data_block_bits, data_block_offsets);
|
|
859 |
|
|
860 |
if (sub_handles[sub_handle] == NULL)
|
|
861 |
return tvb_captured_length(tvb);
|
|
862 |
|
|
863 |
call_dissector_with_data(sub_handles[sub_handle], payload_tvb,
|
|
864 |
pinfo, tree, &rlc_mac);
|
|
865 |
|
|
866 |
/* We need a sub payload tvb which starts
|
|
867 |
* with 6 0 bits, followed by the data block
|
|
868 |
* bits. The offset depends on the header type,
|
|
869 |
* the size depends on the MCS */
|
|
870 |
if (num_calls > 1) {
|
|
871 |
data_tvb = get_egprs_data_block(payload_tvb,
|
|
872 |
data_block_offsets[0], data_block_bits);
|
|
873 |
rlc_mac.flags = GSM_RLC_MAC_EGPRS_BLOCK1;
|
|
874 |
call_dissector_with_data(sub_handles[sub_handle], data_tvb,
|
|
875 |
pinfo, tree, &rlc_mac);
|
|
876 |
}
|
|
877 |
if (num_calls > 2) {
|
|
878 |
data_tvb = get_egprs_data_block(payload_tvb,
|
|
879 |
data_block_offsets[1], data_block_bits);
|
|
880 |
rlc_mac.flags = GSM_RLC_MAC_EGPRS_BLOCK2;
|
|
881 |
call_dissector_with_data(sub_handles[sub_handle], data_tvb,
|
|
882 |
pinfo, tree, &rlc_mac);
|
|
883 |
}
|
|
884 |
}
|
715 |
885 |
else if (sub_handles[sub_handle] != NULL)
|
716 |
886 |
call_dissector(sub_handles[sub_handle], payload_tvb, pinfo, tree);
|
717 |
887 |
/* TODO: warn user that the WiMAX plugin must be enabled for some types */
|