Project

General

Profile

egprs-gsmtap-dissector.patch

WIP patch to add EDGE decoding for RLC frames contained in GSMTAP. - zecke2, 02/04/2016 05:50 PM

View differences:

epan/dissectors/packet-gsmtap.c
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 */
Add picture from clipboard (Maximum size: 48.8 MB)