blob: 39b0521bdf144cefcecb37b95244a8d098ca0c21 [file] [log] [blame]
Harald Welte77847ad2015-10-06 22:07:04 +02001/* Iu interface specific helper functions */
2
3/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
Harald Welte393f2bd2015-09-11 17:13:51 +020021#include <stdint.h>
Harald Welte1d2c39d2015-09-11 17:49:37 +020022#include <string.h>
Philipp Maieree038762017-12-19 17:42:36 +010023#include <errno.h>
24#include <arpa/inet.h>
25#include "asn1helpers.h"
Harald Welte393f2bd2015-09-11 17:13:51 +020026#include <osmocom/core/utils.h>
Philipp Maieree038762017-12-19 17:42:36 +010027#include <osmocom/ranap/RANAP_IuTransportAssociation.h>
28#include <osmocom/ranap/RANAP_TransportLayerAddress.h>
Harald Welte393f2bd2015-09-11 17:13:51 +020029
Harald Welte77847ad2015-10-06 22:07:04 +020030/* decode a BCD-string as used inside ASN.1 encoded Iu interface protocols */
Harald Welte056984f2016-01-03 16:31:31 +010031int ranap_bcd_decode(char *out, size_t out_len, const uint8_t *in, size_t in_len)
Harald Welte393f2bd2015-09-11 17:13:51 +020032{
33 const uint8_t *ch;
34 char *outch = out;
35
36 for (ch = in; ch < in + in_len; ch++) {
37 char c = osmo_bcd2char(*ch & 0xF);
38 *outch++ = c;
39 if (outch + 1 >= out + out_len)
40 break;
41 c = osmo_bcd2char(*ch >> 4);
42 /* skip padding nibble at end */
43 if (c == 'F')
44 break;
45 *outch++ = c;
46 }
47 *outch++ = '\0';
48 return outch - out;
49}
50
Harald Welte77847ad2015-10-06 22:07:04 +020051/* decode an IMSI as used inside ASN.1 encoded Iu interface protocols */
Harald Welte056984f2016-01-03 16:31:31 +010052int ranap_imsi_encode(uint8_t *out, size_t out_len, const char *in)
Harald Welte393f2bd2015-09-11 17:13:51 +020053{
54 unsigned int len = strlen(in);
Harald Welte208b7b02015-09-11 17:35:52 +020055 unsigned int octlen;
Harald Welte393f2bd2015-09-11 17:13:51 +020056 uint8_t odd = (len & 0x01) == 1;
57 unsigned int off = 0;
58 unsigned int i;
59
Harald Welte208b7b02015-09-11 17:35:52 +020060 octlen = len/2;
Harald Welte393f2bd2015-09-11 17:13:51 +020061 if (odd)
Harald Welte208b7b02015-09-11 17:35:52 +020062 octlen++;
Harald Welte393f2bd2015-09-11 17:13:51 +020063
Harald Welte208b7b02015-09-11 17:35:52 +020064 for (i = 0; i < octlen; i++) {
Harald Welte393f2bd2015-09-11 17:13:51 +020065 uint8_t lower, upper;
66
Harald Welte208b7b02015-09-11 17:35:52 +020067 lower = osmo_char2bcd(in[off++]) & 0x0f;
68 if (odd && off == len)
Harald Welte393f2bd2015-09-11 17:13:51 +020069 upper = 0x0f;
70 else
Harald Welte208b7b02015-09-11 17:35:52 +020071 upper = osmo_char2bcd(in[off++]) & 0x0f;
Harald Welte393f2bd2015-09-11 17:13:51 +020072
73 out[i] = (upper << 4) | lower;
74 }
75 return i;
76}
Philipp Maieree038762017-12-19 17:42:36 +010077
78/* decode a network port as used inside ASN.1 encoded Iu interface protocols */
79int ranap_transp_assoc_decode(uint16_t *port, const RANAP_IuTransportAssociation_t *transp_assoc)
80{
81 uint32_t result;
82
83 if (!transp_assoc)
84 return -EINVAL;
85
86 result = asn1bitstr_to_u32((BIT_STRING_t *) & transp_assoc->choice.bindingID);
87
88 /* The lower 16 bits should be zero, otherwise the decoding may
89 * have yielded some odd result */
90 if (result & 0xFFFF)
91 return -EINVAL;
92
93 *port = (uint16_t) ((result >> 16) & 0xFFFF);
94
95 if (*port == 0)
96 return -EINVAL;
97
98 return 0;
99}
100
101/* decode a network address as used inside ASN.1 encoded Iu interface protocols */
102int ranap_transp_layer_addr_decode(char *addr, unsigned int addr_len,
103 const RANAP_TransportLayerAddress_t *trasp_layer_addr)
104{
105 unsigned char *buf;
106 int len;
107 const char *rc;
108
109 buf = trasp_layer_addr->buf;
110 len = trasp_layer_addr->size;
111
Neels Hofmeyr236d1d42018-08-20 17:28:33 +0200112 if (buf[0] == 0x35 && len == 7)
Philipp Maieree038762017-12-19 17:42:36 +0100113 rc = inet_ntop(AF_INET, buf + 3, addr, addr_len);
114 else if (len > 3)
115 rc = inet_ntop(AF_INET, buf, addr, addr_len);
116 else
117 return -EINVAL;
118
119 if (!rc)
120 return -EINVAL;
121
122 return 0;
123}