blob: ac1e3f06fb9cd81cc2c8e9cc306d53cf0f09f876 [file] [log] [blame]
Harald Weltec676c682017-12-24 20:38:20 +01001
2#include "Octetstring.hh"
3#include "Error.hh"
4#include "Logger.hh"
5
6#include "IuUP_Types.hh"
7
8#include <stdint.h>
9
10extern "C" {
11
12typedef uint8_t ubit_t;
13typedef uint8_t pbit_t;
14
15static int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
16{
17 unsigned int i;
18 ubit_t *cur = out;
19 ubit_t *limit = out + num_bits;
20
21 for (i = 0; i < (num_bits/8)+1; i++) {
22 pbit_t byte = in[i];
23 *cur++ = (byte >> 7) & 1;
24 if (cur >= limit)
25 break;
26 *cur++ = (byte >> 6) & 1;
27 if (cur >= limit)
28 break;
29 *cur++ = (byte >> 5) & 1;
30 if (cur >= limit)
31 break;
32 *cur++ = (byte >> 4) & 1;
33 if (cur >= limit)
34 break;
35 *cur++ = (byte >> 3) & 1;
36 if (cur >= limit)
37 break;
38 *cur++ = (byte >> 2) & 1;
39 if (cur >= limit)
40 break;
41 *cur++ = (byte >> 1) & 1;
42 if (cur >= limit)
43 break;
44 *cur++ = (byte >> 0) & 1;
45 if (cur >= limit)
46 break;
47 }
48 return cur - out;
49}
50
51
52struct osmo_crc8gen_code {
53 int bits; /*!< Actual number of bits of the CRC */
54 uint8_t poly; /*!< Polynom (normal representation, MSB omitted */
55 uint8_t init; /*!< Initialization value of the CRC state */
56 uint8_t remainder; /*!< Remainder of the CRC (final XOR) */
57};
58
59static uint8_t
60osmo_crc8gen_compute_bits(const struct osmo_crc8gen_code *code,
61 const ubit_t *in, int len)
62{
63 const uint8_t poly = code->poly;
64 uint8_t crc = code->init;
65 int i, n = code->bits-1;
66
67 for (i=0; i<len; i++) {
68 uint8_t bit = in[i] & 1;
69 crc ^= (bit << n);
70 if (crc & ((uint8_t)1 << n)) {
71 crc <<= 1;
72 crc ^= poly;
73 } else {
74 crc <<= 1;
75 }
76 crc &= ((uint8_t)1 << code->bits) - 1;
77 }
78
79 crc ^= code->remainder;
80
81 return crc;
82}
83
84struct osmo_crc16gen_code {
85 int bits; /*!< Actual number of bits of the CRC */
86 uint16_t poly; /*!< Polynom (normal representation, MSB omitted */
87 uint16_t init; /*!< Initialization value of the CRC state */
88 uint16_t remainder; /*!< Remainder of the CRC (final XOR) */
89};
90
91static uint16_t
92osmo_crc16gen_compute_bits(const struct osmo_crc16gen_code *code,
93 const ubit_t *in, int len)
94{
95 const uint16_t poly = code->poly;
96 uint16_t crc = code->init;
97 int i, n = code->bits-1;
98
99 for (i=0; i<len; i++) {
100 uint16_t bit = in[i] & 1;
101 crc ^= (bit << n);
102 if (crc & ((uint16_t)1 << n)) {
103 crc <<= 1;
104 crc ^= poly;
105 } else {
106 crc <<= 1;
107 }
108 crc &= ((uint16_t)1 << code->bits) - 1;
109 }
110
111 crc ^= code->remainder;
112
113 return crc;
114}
115
116}
117
118
119static const struct osmo_crc8gen_code iuup_hdr_crc_code = {
120 .bits = 6,
121 .poly = 47,
122 .init = 0,
123 .remainder = 0,
124};
125
126static const struct osmo_crc16gen_code iuup_data_crc_code = {
127 .bits = 10,
128 .poly = 563,
129 .init = 0,
130 .remainder = 0,
131};
132
133static int iuup_get_payload_offset(const uint8_t *iuup_pdu)
134{
135 uint8_t pdu_type = iuup_pdu[0] >> 4;
136 switch (pdu_type) {
137 case 0:
138 case 14:
139 return 4;
140 case 1:
141 return 3;
142 default:
143 return -1;
144 }
145}
146
147int osmo_iuup_compute_payload_crc(const uint8_t *iuup_pdu, unsigned int pdu_len)
148{
149 ubit_t buf[1024*8];
150 uint8_t pdu_type;
151 int offset, payload_len_bytes;
152
153 if (pdu_len < 1)
154 return -1;
155
156 pdu_type = iuup_pdu[0] >> 4;
157
158 /* Type 1 has no CRC */
159 if (pdu_type == 1)
160 return 0;
161
162 offset = iuup_get_payload_offset(iuup_pdu);
163 if (offset < 0)
164 return offset;
165
166 if (pdu_len < (unsigned int)offset)
167 return -1;
168
169 payload_len_bytes = pdu_len - offset;
170 osmo_pbit2ubit(buf, iuup_pdu+offset, payload_len_bytes*8);
171 return osmo_crc16gen_compute_bits(&iuup_data_crc_code, buf, payload_len_bytes*8);
172}
173
174int osmo_iuup_compute_header_crc(const uint8_t *iuup_pdu, unsigned int pdu_len)
175{
176 ubit_t buf[2*8];
177
178 if (pdu_len < 2)
179 return -1;
180
181 osmo_pbit2ubit(buf, iuup_pdu, 2*8);
182 return osmo_crc8gen_compute_bits(&iuup_hdr_crc_code, buf, 2*8);
183}
184/* IuUP CRC Implementation */
185
186/* (C) 2017 by Harald Welte <laforge@gnumonks.org>
187 *
188 * All Rights Reserved
189 *
190 * This program is free software; you can redistribute it and/or modify
191 * it under the terms of the GNU General Public License as published by
192 * the Free Software Foundation; either version 2 of the License, or
193 * (at your option) any later version.
194 *
195 * This program is distributed in the hope that it will be useful,
196 * but WITHOUT ANY WARRANTY; without even the implied warranty of
197 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte4895d7a2020-03-01 20:26:26 +0100198 * GNU General Public License for more details.
Harald Weltec676c682017-12-24 20:38:20 +0100199 *
Harald Welte4895d7a2020-03-01 20:26:26 +0100200 * You should have received a copy of the GNU General Public License
Harald Weltec676c682017-12-24 20:38:20 +0100201 * along with this program. If not, see <http://www.gnu.org/licenses/>.
202 *
203 */
204
205namespace IuUP__Types {
206
207
208INTEGER f__IuUP__compute__crc__payload(OCTETSTRING const &in)
209{
210 int crc_calc;
211 const unsigned char *data = (const unsigned char *)in;
212 int len = in.lengthof();
213
214 crc_calc = osmo_iuup_compute_payload_crc(data, len);
215
216 return INTEGER(crc_calc);
217}
218
219INTEGER f__IuUP__compute__crc__header(OCTETSTRING const &in)
220{
221 int crc_calc;
222 const unsigned char *data = (const unsigned char *)in;
223 int len = in.lengthof();
224
225 crc_calc = osmo_iuup_compute_header_crc(data, len);
226
227 return INTEGER(crc_calc);
228}
229
230OCTETSTRING f__enc__IuUP__PDU(const IuUP__PDU& pdu)
231{
232 TTCN_Buffer buf;
233 int crc_hdr, crc_payload;
234 uint8_t in[2];
235 pdu.encode(IuUP__PDU_descr_, buf, TTCN_EncDec::CT_RAW);
236 OCTETSTRING ret_val(buf.get_len(), buf.get_data());
237
238 crc_hdr = osmo_iuup_compute_header_crc(buf.get_data(), buf.get_len());
239 crc_payload = osmo_iuup_compute_payload_crc(buf.get_data(), buf.get_len());
240 in[0] = (crc_hdr & 0x3f) << 2;
241 in[0] |= (crc_payload & 0x3ff) >> 8;
242 in[1] = crc_payload & 0xff;
243 OCTETSTRING CHECKSUM(2, in);
244
245 ret_val = substr(ret_val, 0, 2) + CHECKSUM + substr(ret_val, 4, ret_val.lengthof()-4);
246
247 return ret_val;
248}
249
250}