blob: 13641c1e1d4a11d003097204c8a098bbaf4b7a10 [file] [log] [blame]
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +02001/* GPRS utility functions */
2
3/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2010-2014 by On-Waves
5 * (C) 2013 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020022#include <osmocom/sgsn/gprs_utils.h>
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020023
24#include <osmocom/core/msgb.h>
25#include <osmocom/gprs/gprs_ns.h>
26
Harald Welte53373bc2016-04-20 17:11:43 +020027#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020028#include <osmocom/gsm/protocol/gsm_04_08.h>
Jacob Erlbecke7bcdc32016-01-04 18:43:34 +010029#include <osmocom/gsm/gsm48.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020030
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020031#include <string.h>
32
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +020033int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020034{
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +020035 uint8_t *last_len_field;
36 int len;
37
38 /* Can we even write the length field to the output? */
39 if (max_len == 0)
40 return -1;
41
42 /* Remember where we need to put the length once we know it */
43 last_len_field = apn_enc;
44 len = 1;
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020045 apn_enc += 1;
46
47 while (str[0]) {
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +020048 if (len >= max_len)
49 return -1;
50
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020051 if (str[0] == '.') {
52 *last_len_field = (apn_enc - last_len_field) - 1;
53 last_len_field = apn_enc;
54 } else {
55 *apn_enc = str[0];
56 }
57 apn_enc += 1;
58 str += 1;
59 len += 1;
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020060 }
61
62 *last_len_field = (apn_enc - last_len_field) - 1;
63
64 return len;
65}
66
Jacob Erlbeck79af67d2015-01-19 08:27:34 +010067/* GSM 04.08, 10.5.7.3 GPRS Timer */
68int gprs_tmr_to_secs(uint8_t tmr)
69{
70 switch (tmr & GPRS_TMR_UNIT_MASK) {
71 case GPRS_TMR_2SECONDS:
72 return 2 * (tmr & GPRS_TMR_FACT_MASK);
73 default:
74 case GPRS_TMR_MINUTE:
75 return 60 * (tmr & GPRS_TMR_FACT_MASK);
76 case GPRS_TMR_6MINUTE:
77 return 360 * (tmr & GPRS_TMR_FACT_MASK);
78 case GPRS_TMR_DEACTIVATED:
79 return -1;
80 }
81}
82
83/* This functions returns a tmr value such that
84 * - f is monotonic
85 * - f(s) <= s
86 * - f(s) == s if a tmr exists with s = gprs_tmr_to_secs(tmr)
87 * - the best possible resolution is used
88 * where
89 * f(s) = gprs_tmr_to_secs(gprs_secs_to_tmr_floor(s))
90 */
91uint8_t gprs_secs_to_tmr_floor(int secs)
92{
93 if (secs < 0)
94 return GPRS_TMR_DEACTIVATED;
95 if (secs < 2 * 32)
96 return GPRS_TMR_2SECONDS | (secs / 2);
97 if (secs < 60 * 2)
98 /* Ensure monotonicity */
99 return GPRS_TMR_2SECONDS | GPRS_TMR_FACT_MASK;
100 if (secs < 60 * 32)
101 return GPRS_TMR_MINUTE | (secs / 60);
102 if (secs < 360 * 6)
103 /* Ensure monotonicity */
104 return GPRS_TMR_MINUTE | GPRS_TMR_FACT_MASK;
105 if (secs < 360 * 32)
106 return GPRS_TMR_6MINUTE | (secs / 360);
107
108 return GPRS_TMR_6MINUTE | GPRS_TMR_FACT_MASK;
109}
110
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200111/* GSM 04.08, 10.5.1.4 */
112int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len)
113{
114 if (value_len != GSM48_TMSI_LEN)
115 return 0;
116
117 if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_TMSI)
118 return 0;
119
120 return 1;
121}
122
123/* GSM 04.08, 10.5.1.4 */
124int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
125{
126 if (value_len == 0)
127 return 0;
128
129 if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI)
130 return 0;
131
132 return 1;
133}
134
135int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
136{
137 uint32_t tmsi_be;
138
139 if (!gprs_is_mi_tmsi(value, value_len))
140 return 0;
141
142 memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
143
144 *tmsi = ntohl(tmsi_be);
145 return 1;
146}
147
Jacob Erlbeck49389172014-10-02 16:14:47 +0200148void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
149{
150 uint32_t tmsi_be;
151
152 memcpy(&tmsi_be, value, sizeof(tmsi_be));
153
154 *tmsi = ntohl(tmsi_be);
155}
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100156
Jacob Erlbecke7bcdc32016-01-04 18:43:34 +0100157int gprs_ra_id_equals(const struct gprs_ra_id *id1,
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100158 const struct gprs_ra_id *id2)
Jacob Erlbecke7bcdc32016-01-04 18:43:34 +0100159{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100160 return (id1->mcc == id2->mcc
161 && !osmo_mnc_cmp(id1->mnc, id1->mnc_3_digits,
162 id2->mnc, id2->mnc_3_digits)
163 && id1->lac == id2->lac && id1->rac == id2->rac);
Jacob Erlbecke7bcdc32016-01-04 18:43:34 +0100164}