blob: 14f250d2f06c2a18a91e7e28385f303c0aecf7e0 [file] [log] [blame]
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001/* Common bits for RAN message handling */
2/*
Vadim Yanitskiy999a5932023-05-18 17:22:26 +07003 * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01004 * All Rights Reserved
5 *
6 * Author: Neels Hofmeyr
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010019 */
20
21#include <osmocom/core/utils.h>
22
23#include <osmocom/msc/ran_msg.h>
24
25const struct value_string ran_msg_type_names[] = {
26 { RAN_MSG_NONE, "NONE" },
27 { RAN_MSG_COMPL_L3, "COMPL_L3" },
28 { RAN_MSG_DTAP, "DTAP" },
29 { RAN_MSG_CLEAR_COMMAND, "CLEAR_COMMAND" },
30 { RAN_MSG_CLEAR_REQUEST, "CLEAR_REQUEST" },
31 { RAN_MSG_CLEAR_COMPLETE, "CLEAR_COMPLETE" },
32 { RAN_MSG_CLASSMARK_REQUEST, "CLASSMARK_REQUEST" },
33 { RAN_MSG_CLASSMARK_UPDATE, "CLASSMARK_UPDATE" },
34 { RAN_MSG_CIPHER_MODE_COMMAND, "CIPHER_MODE_COMMAND" },
35 { RAN_MSG_CIPHER_MODE_COMPLETE, "CIPHER_MODE_COMPLETE" },
36 { RAN_MSG_CIPHER_MODE_REJECT, "CIPHER_MODE_REJECT" },
37 { RAN_MSG_COMMON_ID, "COMMON_ID" },
38 { RAN_MSG_ASSIGNMENT_COMMAND, "ASSIGNMENT_COMMAND" },
39 { RAN_MSG_ASSIGNMENT_COMPLETE, "ASSIGNMENT_COMPLETE" },
40 { RAN_MSG_ASSIGNMENT_FAILURE, "ASSIGNMENT_FAILURE" },
41 { RAN_MSG_SAPI_N_REJECT, "SAPI_N_REJECT" },
42 { RAN_MSG_LCLS_STATUS, "LCLS_STATUS" },
43 { RAN_MSG_LCLS_BREAK_REQ, "LCLS_BREAK_REQ" },
44 { RAN_MSG_HANDOVER_COMMAND, "HANDOVER_COMMAND" },
45 { RAN_MSG_HANDOVER_SUCCEEDED, "HANDOVER_SUCCEEDED" },
46 { RAN_MSG_HANDOVER_PERFORMED, "HANDOVER_PERFORMED" },
47 { RAN_MSG_HANDOVER_REQUIRED, "HANDOVER_REQUIRED" },
48 { RAN_MSG_HANDOVER_REQUIRED_REJECT, "HANDOVER_REQUIRED_REJECT" },
49 { RAN_MSG_HANDOVER_REQUEST, "HANDOVER_REQUEST" },
50 { RAN_MSG_HANDOVER_REQUEST_ACK, "HANDOVER_REQUEST_ACK" },
51 { RAN_MSG_HANDOVER_DETECT, "HANDOVER_DETECT" },
52 { RAN_MSG_HANDOVER_COMPLETE, "HANDOVER_COMPLETE" },
53 { RAN_MSG_HANDOVER_FAILURE, "HANDOVER_FAILURE" },
Andreas Eversberg2d27e2c2023-04-23 12:05:44 +020054 { RAN_MSG_VGCS_VBS_SETUP, "VGCS_VBS_SETUP" },
55 { RAN_MSG_VGCS_VBS_SETUP_ACK, "VGCS_VBS_SETUP_ACK" },
56 { RAN_MSG_VGCS_VBS_SETUP_REFUSE, "VGCS_VBS_SETUP_REFUSE" },
57 { RAN_MSG_VGCS_VBS_ASSIGN_REQ, "VGCS_VBS_ASSIGN_REQ" },
58 { RAN_MSG_VGCS_VBS_ASSIGN_RES, "VGCS_VBS_ASSIGN_RES" },
59 { RAN_MSG_VGCS_VBS_ASSIGN_FAIL, "VGCS_VBS_ASSIGN_FAIL" },
60 { RAN_MSG_VGCS_VBS_QUEUING_IND, "VGCS_VBS_QUEUING_IND" },
61 { RAN_MSG_UPLINK_REQUEST, "UPLINK_REQUEST" },
62 { RAN_MSG_UPLINK_REQUEST_ACK, "UPLINK_REQUEST_ACK" },
63 { RAN_MSG_UPLINK_REQUEST_CNF, "UPLINK_REQUEST_CNF" },
64 { RAN_MSG_UPLINK_APPLICATION_DATA, "UPLINK_APPLICATION_DATA" },
65 { RAN_MSG_UPLINK_RELEASE_IND, "UPLINK_RELEASE_IND" },
66 { RAN_MSG_UPLINK_REJECT_CMD, "UPLINK_REJECT_CMD" },
67 { RAN_MSG_UPLINK_RELEASE_CMD, "UPLINK_RELEASE_CMD" },
68 { RAN_MSG_UPLINK_SEIZED_CMD, "UPLINK_SEIZED_CMD" },
69 { RAN_MSG_VGCS_ADDITIONAL_INFO, "VGCS_ADDITIONAL_INFO" },
70 { RAN_MSG_VGCS_VBS_AREA_CELL_INFO, "VGCS_VBS_AREA_CELL_INFO" },
71 { RAN_MSG_VGCS_VBS_ASSIGN_STATUS, "VGCS_VBS_ASSIGN_STATUS" },
72 { RAN_MSG_VGCS_SMS, "VGCS_SMS" },
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010073 {}
74};
75
76/* extract the N(SD) and return the modulo value for a R99 message */
77static uint8_t ran_dec_dtap_undup_determine_nsd_ret_modulo_r99(uint8_t pdisc, uint8_t msg_type, uint8_t *n_sd)
78{
79 switch (pdisc) {
80 case GSM48_PDISC_MM:
81 case GSM48_PDISC_CC:
82 case GSM48_PDISC_NC_SS:
83 *n_sd = (msg_type >> 6) & 0x3;
84 return 4;
85 case GSM48_PDISC_GROUP_CC:
86 case GSM48_PDISC_BCAST_CC:
87 case GSM48_PDISC_LOC:
88 *n_sd = (msg_type >> 6) & 0x1;
89 return 2;
90 default:
91 /* no sequence number, we cannot detect dups */
92 return 0;
93 }
94}
95
96/* extract the N(SD) and return the modulo value for a R98 message */
97static uint8_t gsm0407_determine_nsd_ret_modulo_r98(uint8_t pdisc, uint8_t msg_type, uint8_t *n_sd)
98{
99 switch (pdisc) {
100 case GSM48_PDISC_MM:
101 case GSM48_PDISC_CC:
102 case GSM48_PDISC_NC_SS:
103 case GSM48_PDISC_GROUP_CC:
104 case GSM48_PDISC_BCAST_CC:
105 case GSM48_PDISC_LOC:
106 *n_sd = (msg_type >> 6) & 0x1;
107 return 2;
108 default:
109 /* no sequence number, we cannot detect dups */
110 return 0;
111 }
112}
113
114/* TS 24.007 11.2.3.2.3 Message Type Octet / Duplicate Detection.
115 * (Not static for unit testing). */
116int ran_dec_dtap_undup_pdisc_ctr_bin(uint8_t pdisc)
117{
118 switch (pdisc) {
119 case GSM48_PDISC_MM:
120 case GSM48_PDISC_CC:
121 case GSM48_PDISC_NC_SS:
122 return 0;
123 case GSM48_PDISC_GROUP_CC:
124 return 1;
125 case GSM48_PDISC_BCAST_CC:
126 return 2;
127 case GSM48_PDISC_LOC:
128 return 3;
129 default:
130 return -1;
131 }
132}
133
134/* TS 24.007 11.2.3.2 Message Type Octet / Duplicate Detection */
135bool ran_dec_dtap_undup_is_duplicate(struct osmo_fsm_inst *log_fi, uint8_t *n_sd_next, bool is_r99, struct msgb *l3)
136{
137 struct gsm48_hdr *gh;
138 uint8_t pdisc;
139 uint8_t n_sd, modulo;
140 int bin;
141
142 gh = msgb_l3(l3);
143 pdisc = gsm48_hdr_pdisc(gh);
144
145 if (is_r99) {
146 modulo = ran_dec_dtap_undup_determine_nsd_ret_modulo_r99(pdisc, gh->msg_type, &n_sd);
147 } else { /* pre R99 */
148 modulo = gsm0407_determine_nsd_ret_modulo_r98(pdisc, gh->msg_type, &n_sd);
149 }
150 if (modulo == 0)
151 return false;
152 bin = ran_dec_dtap_undup_pdisc_ctr_bin(pdisc);
153 if (bin < 0)
154 return false;
155
156 OSMO_ASSERT(bin >= 0 && bin < 4);
157 if (n_sd != n_sd_next[bin]) {
158 /* not what we expected: duplicate */
159 LOGPFSML(log_fi, LOGL_NOTICE, "Duplicate DTAP: bin=%d, expected n_sd == %u, got %u\n",
160 bin, n_sd_next[bin], n_sd);
161 return true;
162 } else {
163 /* as expected: no dup; update expected counter for next message */
164 n_sd_next[bin] = (n_sd + 1) % modulo;
165 return false;
166 }
167}
168
169/* convenience: RAN decode implementations can call this to dispatch the decode_cb with a decoded ran_msg. */
170int ran_decoded(struct ran_dec *ran_dec, struct ran_msg *ran_msg)
171{
172 if (!ran_dec->decode_cb)
173 return -1;
174 return ran_dec->decode_cb(ran_dec->caller_fi, ran_dec->caller_data, ran_msg);
175}