Harald Welte | a814f26 | 2017-07-24 13:21:35 +0200 | [diff] [blame] | 1 | /////////////////////////////////////////////////////////////////////////////// |
| 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 | |
| 20 | namespace GTPU__Types { |
| 21 | |
| 22 | // find the length of the optional part and decode optional part into OPT_PART |
| 23 | int 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 | ////////////////////////////////// |
| 58 | PDU__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 |