blob: 8fed0206817240409dd2b3dfca2b826fa925480d [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 *
Max7918f842018-12-10 10:57:59 +010017 */
18
Max5ec0cf52019-01-15 16:37:09 +010019#include "config.h"
20
Max7918f842018-12-10 10:57:59 +010021#include <osmocom/gsm/protocol/gsm_08_08.h>
22#include <osmocom/gsm/gsm29205.h>
23#include <osmocom/gsm/gsm0808.h>
Max5ec0cf52019-01-15 16:37:09 +010024#include <osmocom/core/utils.h>
Max7918f842018-12-10 10:57:59 +010025#include <osmocom/core/msgb.h>
26#include <osmocom/gsm/tlv.h>
27
28#include <errno.h>
29
30/*! \addtogroup gsm29205
31 * @{
32 * \file gsm29205.c
33 * Functions related to 3GPP TS 29.205, primarily message generation/encoding.
34 */
35
36/*! Create Global Call Reference.
37 * \param[out] msg Message Buffer for appending IE
38 * \param[in] g Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1
39 * \returns number of bytes added to \a msg */
40uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g)
41{
42 uint8_t buf[2];
43
44 if (!g)
45 return 0;
46
47 if (g->net_len < 3 || g->net_len > 5)
48 return 0;
49
50 msgb_lv_put(msg, g->net_len, g->net);
51
52 osmo_store16be(g->node, &buf);
53 msgb_lv_put(msg, 2, buf);
54
55 msgb_lv_put(msg, 5, g->cr);
56
57 /* Length: LV(Net) + LV(Node) + LV(CRef) - see 3GPP TS ยง3.2.2.115 */
58 return (g->net_len + 1) + (2 + 1) + (5 + 1);
59}
60
61/*! Decode Global Call Reference, 3GPP TS 29.205 Table B 2.1.9.1.
62 * \param[out] gcr Caller-provided memory to store Global Call Reference
63 * \param[in] elem IE value to be decoded
64 * \param[in] len Length of \a elem in bytes
65 * \returns number of bytes parsed; negative on error */
66int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len)
67{
68 uint16_t parsed = 1; /* account for length byte right away */
69
70 if (len < 13)
71 return -EBADMSG;
72
73 gcr->net_len = elem[0];
74 if (gcr->net_len < 3 || gcr->net_len > 5)
75 return -EINVAL;
76
77 memcpy(gcr->net, elem + parsed, gcr->net_len);
78 /* +1 for ignored Node ID length field */
79 parsed += (gcr->net_len + 1);
80
81 gcr->node = osmo_load16be(elem + parsed);
82 parsed += 2;
83
84 if (elem[parsed] != 5) /* see Table B 2.1.9.2 */
85 return -ENOENT;
86
87 parsed++;
88
89 memcpy(gcr->cr, elem + parsed, 5);
90
91 return parsed + 5;
92}
Max1bec3902019-01-14 19:31:42 +010093
94/*! Compare two GCR structs.
95 * \param[in] gcr1 pointer to the GCR struct
96 * \param[in] gcr2 pointer to the GCR struct
97 * \returns true if GCRs are equal, false otherwise */
98bool osmo_gcr_eq(const struct osmo_gcr_parsed *gcr1, const struct osmo_gcr_parsed *gcr2)
99{
100 if (gcr1->net_len != gcr2->net_len)
101 return false;
102
103 if (gcr1->node != gcr2->node)
104 return false;
105
106 if (memcmp(gcr1->cr, gcr2->cr, 5) != 0)
107 return false;
108
109 if (memcmp(gcr1->net, gcr2->net, gcr2->net_len) != 0)
110 return false;
111
112 return true;
113}