blob: 6ceb8ee421c092d818e78a26851d65b8036c97bd [file] [log] [blame]
Max7918f842018-12-10 10:57:59 +01001/*
2 * (C) 2018 by sysmocom - s.f.m.c. GmbH
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
Max5ec0cf52019-01-15 16:37:09 +010023#include "config.h"
24
Max7918f842018-12-10 10:57:59 +010025#include <osmocom/gsm/protocol/gsm_08_08.h>
26#include <osmocom/gsm/gsm29205.h>
27#include <osmocom/gsm/gsm0808.h>
Max5ec0cf52019-01-15 16:37:09 +010028#include <osmocom/core/utils.h>
Max7918f842018-12-10 10:57:59 +010029#include <osmocom/core/msgb.h>
30#include <osmocom/gsm/tlv.h>
31
32#include <errno.h>
33
34/*! \addtogroup gsm29205
35 * @{
36 * \file gsm29205.c
37 * Functions related to 3GPP TS 29.205, primarily message generation/encoding.
38 */
39
40/*! Create Global Call Reference.
41 * \param[out] msg Message Buffer for appending IE
42 * \param[in] g Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1
43 * \returns number of bytes added to \a msg */
44uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g)
45{
46 uint8_t buf[2];
47
48 if (!g)
49 return 0;
50
51 if (g->net_len < 3 || g->net_len > 5)
52 return 0;
53
54 msgb_lv_put(msg, g->net_len, g->net);
55
56 osmo_store16be(g->node, &buf);
57 msgb_lv_put(msg, 2, buf);
58
59 msgb_lv_put(msg, 5, g->cr);
60
61 /* Length: LV(Net) + LV(Node) + LV(CRef) - see 3GPP TS ยง3.2.2.115 */
62 return (g->net_len + 1) + (2 + 1) + (5 + 1);
63}
64
65/*! Decode Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1.
66 * \param[out] gcr Caller-provided memory to store Global Call Reference
67 * \param[in] elem IE value to be decoded
68 * \param[in] len Length of \a elem in bytes
69 * \returns number of bytes parsed; negative on error */
70int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len)
71{
72 uint16_t parsed = 1; /* account for length byte right away */
73
74 if (len < 13)
75 return -EBADMSG;
76
77 gcr->net_len = elem[0];
78 if (gcr->net_len < 3 || gcr->net_len > 5)
79 return -EINVAL;
80
81 memcpy(gcr->net, elem + parsed, gcr->net_len);
82 /* +1 for ignored Node ID length field */
83 parsed += (gcr->net_len + 1);
84
85 gcr->node = osmo_load16be(elem + parsed);
86 parsed += 2;
87
88 if (elem[parsed] != 5) /* see Table B 2.1.9.2 */
89 return -ENOENT;
90
91 parsed++;
92
93 memcpy(gcr->cr, elem + parsed, 5);
94
95 return parsed + 5;
96}
Max1bec3902019-01-14 19:31:42 +010097
98/*! Compare two GCR structs.
99 * \param[in] gcr1 pointer to the GCR struct
100 * \param[in] gcr2 pointer to the GCR struct
101 * \returns true if GCRs are equal, false otherwise */
102bool osmo_gcr_eq(const struct osmo_gcr_parsed *gcr1, const struct osmo_gcr_parsed *gcr2)
103{
104 if (gcr1->net_len != gcr2->net_len)
105 return false;
106
107 if (gcr1->node != gcr2->node)
108 return false;
109
110 if (memcmp(gcr1->cr, gcr2->cr, 5) != 0)
111 return false;
112
113 if (memcmp(gcr1->net, gcr2->net, gcr2->net_len) != 0)
114 return false;
115
116 return true;
117}