blob: a532eb7db7b33d277a3ed8849d0f4675d28f84ec [file] [log] [blame]
Harald Weltea814f262017-07-24 13:21:35 +02001///////////////////////////////////////////////////////////////////////////////
2// //
3// Copyright Test Competence Center (TCC) ETH 2016 //
4// //
5// The copyright to the computer program(s) herein is the property of TCC. //
6// The program(s) may be used and/or copied only with the written permission //
7// of TCC or in accordance with the terms and conditions stipulated in the //
8// agreement/contract under which the program(s) has been supplied. //
9// //
10///////////////////////////////////////////////////////////////////////////////
11//
12// File: GTPU_EncDec.cc
13// Rev: R1B
14// Prodnr: CNL 113 843
15// Contact: http://ttcn.ericsson.se
16// Reference: 3GPP TS 29.060 v13.5.0
17
18#include "GTPU_Types.hh"
19
20namespace GTPU__Types {
21
22// find the length of the optional part and decode optional part into OPT_PART
23int find_optpart_length(const unsigned char * opt_part_ptr,GTPU__Header__optional__part& OPT_PART)// pointer to opt part start
24{
25 int opt_part_length = 4; // mandatory minimum length of opt_part
26 OPT_PART.sequenceNumber() = OCTETSTRING(2,opt_part_ptr);
27 OPT_PART.npduNumber() = OCTETSTRING(1,opt_part_ptr+2);
28 OPT_PART.nextExtHeader() = OCTETSTRING(1,opt_part_ptr+3);
29 OPT_PART.gTPU__extensionHeader__List() = OMIT_VALUE;
30
31 int i = 0;
32 bool opt_part_end = false;
33 while(!opt_part_end)
34 {
35 if (opt_part_ptr[opt_part_length-1] != 0x00) // 0x00 means end of optional part
36 {
37 unsigned char lengthfield = opt_part_ptr[opt_part_length];
38
39 OPT_PART.gTPU__extensionHeader__List()()[i].lengthfield() = lengthfield;
40 OPT_PART.gTPU__extensionHeader__List()()[i].content() =
41 OCTETSTRING(4*lengthfield-2,opt_part_ptr + opt_part_length +1);
42 OPT_PART.gTPU__extensionHeader__List()()[i].nextExtHeader() =
43 OCTETSTRING(1,opt_part_ptr + opt_part_length + 4*lengthfield - 1);
44
45 opt_part_length = opt_part_length + 4*lengthfield;
46 i++;
47 }
48 else
49 {opt_part_end = true;}
50 }
51
52 return opt_part_length;
53}
54
55//////////////////////////////////
56// Decoding function for GTPC__DialoguePDU
57//////////////////////////////////
58PDU__GTPU dec__PDU__GTPU(const OCTETSTRING& udp__pdu)
59{
60 TTCN_Buffer buf;
61 PDU__GTPU pdu;
62
63 const unsigned char *gtpu_message = (const unsigned char *) udp__pdu;
64
65 int opt_part_length = 0;
66 if ( gtpu_message[0] & 0x07 ) // opt_part is present
67 {
68 GTPU__Header__optional__part OPT_PART;
69
70 // find the length of the optional part and decode optional part into OPT_PART
71 opt_part_length = find_optpart_length(gtpu_message+8,OPT_PART);
72 if( ((gtpu_message[2] << 8) + gtpu_message[3] - opt_part_length) < 0 )
73 {TTCN_error("Decoding error, lengthf field is shorter that decoded length of opt_part");};
74
75 // build PDU without optional part
76 unsigned int gtpu_IEs_length = (gtpu_message[2] << 8) + gtpu_message[3] - opt_part_length;
77 unsigned char gtpuBuf[8 + gtpu_IEs_length];
78 memcpy(gtpuBuf,gtpu_message,8);
79 memcpy(gtpuBuf+8,gtpu_message+8+opt_part_length,gtpu_IEs_length);
80
81 // substitute dummy bits (indicating there is no optional part)
82 gtpuBuf[0] = gtpuBuf[0] & 0xf8;
83
84 // substitute dummy length (not including optional part)
85 gtpuBuf[2] = (gtpu_IEs_length & 0xff00) >> 8;
86 gtpuBuf[3] = gtpu_IEs_length & 0xff;
87
88 // RAW decoding
89 buf.put_s(8 + gtpu_IEs_length,gtpuBuf);
90 pdu.decode(PDU__GTPU_descr_, buf, TTCN_EncDec::CT_RAW);
91 buf.clear();
92
93 // put back the original values
94 unsigned char pn = gtpu_message[0] & 0x01;
95 pdu.pn__bit() = BITSTRING(1,&pn);
96
97 unsigned char s = (gtpu_message[0] & 0x02) >> 1;
98 pdu.s__bit() = BITSTRING(1,&s);
99
100 unsigned char e = (gtpu_message[0] & 0x04) >> 2;
101 pdu.e__bit() = BITSTRING(1,&e);
102
103 pdu.lengthf() = (gtpu_message[2] << 8) + gtpu_message[3];
104
105 pdu.opt__part() = OPT_PART;
106
107 return pdu;
108 }
109 else // opt_part is not present
110 {
111 buf.put_os(udp__pdu);
112 pdu.decode(PDU__GTPU_descr_, buf, TTCN_EncDec::CT_RAW);
113 buf.clear();
114 return pdu;
115 }
116} // end of function
117
118
119}//namespace