blob: a9f2ebd8eaf348f3bfec1c9a065444b7863cac81 [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
Harald Weltebf5e8df2009-02-03 12:59:45 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte498b0bb2009-01-09 21:27:43 +00005 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
Harald Welte7584aea2009-02-11 11:44:12 +000035#include <openbsc/tlv.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000040#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000042#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000043#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000044#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000045#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000046#include <openbsc/trau_mux.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020047#include <openbsc/talloc.h>
Harald Welteaa0b29c2009-07-23 18:56:43 +020048#include <openbsc/transaction.h>
Harald Welte52b1f982008-12-23 20:25:15 +000049
Harald Welte8470bf22008-12-25 23:28:35 +000050#define GSM48_ALLOC_SIZE 1024
51#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000052
Harald Welte0c389302009-06-10 12:08:54 +080053#define GSM_MAX_FACILITY 128
54#define GSM_MAX_SSVERSION 128
55#define GSM_MAX_USERUSER 128
56
Harald Welte2cf161b2009-06-20 22:36:41 +020057static void *tall_locop_ctx;
Harald Welte2cf161b2009-06-20 22:36:41 +020058
Harald Welte09e38af2009-02-16 22:52:23 +000059static const struct tlv_definition rsl_att_tlvdef = {
60 .def = {
61 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
62 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
63 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
64 [GSM48_IE_UTC] = { TLV_TYPE_TV },
65 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
66 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
67
68 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
69 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
70 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
71 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
72 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
73 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
74 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080075 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000076 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
77 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080078 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
79 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000080 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
81 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
82 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
83 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
84 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
86 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
87 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
88 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
89 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
90 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
91 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
92 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
93 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080094 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
95 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +000096 /* FIXME: more elements */
97 },
98};
Harald Weltecf5b3592009-05-01 18:28:42 +000099
100static const char *rr_cause_names[] = {
101 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
102 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
103 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
104 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
105 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
106 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
107 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
108 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
109 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
110 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
111 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
112 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
113 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
114 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
115 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
116 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
117 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
118};
119
Harald Welte4bfdfe72009-06-10 23:11:52 +0800120static const char *cc_state_names[] = {
121 "NULL",
122 "INITIATED",
123 "illegal state 2",
124 "MO_CALL_PROC",
125 "CALL_DELIVERED",
126 "illegal state 5",
127 "CALL_PRESENT",
128 "CALL_RECEIVED",
129 "CONNECT_REQUEST",
130 "MO_TERM_CALL_CONF",
131 "ACTIVE",
132 "DISCONNECT_REQ",
133 "DISCONNECT_IND",
134 "illegal state 13",
135 "illegal state 14",
136 "illegal state 15",
137 "illegal state 16",
138 "illegal state 17",
139 "illegal state 18",
140 "RELEASE_REQ",
141 "illegal state 20",
142 "illegal state 21",
143 "illegal state 22",
144 "illegal state 23",
145 "illegal state 24",
146 "illegal state 25",
147 "MO_ORIG_MODIFY",
148 "MO_TERM_MODIFY",
149 "CONNECT_IND",
150 "illegal state 29",
151 "illegal state 30",
152 "illegal state 31",
153};
154
155static const char *cc_msg_names[] = {
156 "unknown 0x00",
157 "ALERTING",
158 "CALL_PROC",
159 "PROGRESS",
160 "ESTAB",
161 "SETUP",
162 "ESTAB_CONF",
163 "CONNECT",
164 "CALL_CONF",
165 "START_CC",
166 "unknown 0x0a",
167 "RECALL",
168 "unknown 0x0c",
169 "unknown 0x0d",
170 "EMERG_SETUP",
171 "CONNECT_ACK",
172 "USER_INFO",
173 "unknown 0x11",
174 "unknown 0x12",
175 "MODIFY_REJECT",
176 "unknown 0x14",
177 "unknown 0x15",
178 "unknown 0x16",
179 "MODIFY",
180 "HOLD",
181 "HOLD_ACK",
182 "HOLD_REJ",
183 "unknown 0x1b",
184 "RETR",
185 "RETR_ACK",
186 "RETR_REJ",
187 "MODIFY_COMPL",
188 "unknown 0x20",
189 "unknown 0x21",
190 "unknown 0x22",
191 "unknown 0x23",
192 "unknown 0x24",
193 "DISCONNECT",
194 "unknown 0x26",
195 "unknown 0x27",
196 "unknown 0x28",
197 "unknown 0x29",
198 "RELEASE_COMPL",
199 "unknown 0x2b",
200 "unknown 0x2c",
201 "RELEASE",
202 "unknown 0x2e",
203 "unknown 0x2f",
204 "unknown 0x30",
205 "STOP_DTMF",
206 "STOP_DTMF_ACK",
207 "unknown 0x33",
208 "STATUS_ENQ",
209 "START_DTMF",
210 "START_DTMF_ACK",
211 "START_DTMF_REJ",
212 "unknown 0x38",
213 "CONG_CTRL",
214 "FACILITY",
215 "unknown 0x3b",
216 "STATUS",
217 "unknown 0x3c",
218 "NOTIFY",
219 "unknown 0x3f",
220};
221
Harald Weltecf5b3592009-05-01 18:28:42 +0000222static char strbuf[64];
223
224static const char *rr_cause_name(u_int8_t cause)
225{
226 if (cause < ARRAY_SIZE(rr_cause_names) &&
227 rr_cause_names[cause])
228 return rr_cause_names[cause];
229
230 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
231 return strbuf;
232}
233
Harald Weltef7c43522009-06-09 20:24:21 +0000234static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
235 int len)
236{
237 memset(rep, 0, sizeof(*rep));
238
239 if (data[0] & 0x80)
240 rep->flags |= MEAS_REP_F_BA1;
241 if (data[0] & 0x40)
242 rep->flags |= MEAS_REP_F_DTX;
243 if (data[1] & 0x40)
244 rep->flags |= MEAS_REP_F_VALID;
245
246 rep->rxlev_full = data[0] & 0x3f;
247 rep->rxlev_sub = data[1] & 0x3f;
248 rep->rxqual_full = (data[3] >> 4) & 0x7;
249 rep->rxqual_sub = (data[3] >> 1) & 0x7;
250 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
251 if (rep->num_cell < 1)
252 return;
253
254 /* an encoding nightmare in perfection */
255
256 rep->cell[0].rxlev = data[4] & 0x3f;
257 rep->cell[0].bcch_freq = data[5] >> 2;
258 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
259 if (rep->num_cell < 2)
260 return;
261
262 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
263 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
264 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
265 if (rep->num_cell < 3)
266 return;
267
268 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
269 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
270 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
271 if (rep->num_cell < 4)
272 return;
273
274 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
275 rep->cell[3].bcch_freq = data[11] & 0x1f;
276 rep->cell[3].bsic = data[12] >> 2;
277 if (rep->num_cell < 5)
278 return;
279
280 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
281 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
282 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
283 if (rep->num_cell < 6)
284 return;
285
286 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
287 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
288 rep->cell[5].bsic = data[16] & 0x3f;
289}
290
Holger Freytherd51524f2009-06-09 08:27:07 +0000291int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000292static int gsm48_tx_simple(struct gsm_lchan *lchan,
293 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000294static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte65e74cc2008-12-29 01:55:35 +0000295
Harald Welte52b1f982008-12-23 20:25:15 +0000296struct gsm_lai {
297 u_int16_t mcc;
298 u_int16_t mnc;
299 u_int16_t lac;
300};
301
Holger Freyther89824fc2008-12-30 16:18:18 +0000302static int authorize_everonye = 0;
303void gsm0408_allow_everyone(int everyone)
304{
305 printf("Allowing everyone?\n");
306 authorize_everonye = everyone;
307}
308
Holger Freythere97f7fb2008-12-31 18:52:11 +0000309static int reject_cause = 0;
310void gsm0408_set_reject_cause(int cause)
311{
312 reject_cause = cause;
313}
314
Harald Welte4bfdfe72009-06-10 23:11:52 +0800315static u_int32_t new_callref = 0x80000001;
316
Holger Freyther73487a22008-12-31 18:53:57 +0000317static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
318 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000319{
320 if (!subscriber)
321 return 0;
322
Holger Freyther73487a22008-12-31 18:53:57 +0000323 /*
324 * Do not send accept yet as more information should arrive. Some
325 * phones will not send us the information and we will have to check
326 * what we want to do with that.
327 */
328 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
329 return 0;
330
Holger Freyther89824fc2008-12-30 16:18:18 +0000331 if (authorize_everonye)
332 return 1;
333
334 return subscriber->authorized;
335}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000336
Holger Freyther73487a22008-12-31 18:53:57 +0000337static void release_loc_updating_req(struct gsm_lchan *lchan)
338{
Harald Welte179f0642008-12-31 23:59:18 +0000339 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000340 return;
341
Harald Welteff117a82009-05-23 05:22:08 +0000342 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200343 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000344 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000345 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000346}
347
348static void allocate_loc_updating_req(struct gsm_lchan *lchan)
349{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000350 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000351 release_loc_updating_req(lchan);
352
Harald Welte470ec292009-06-26 20:25:23 +0200353 lchan->loc_operation = talloc_zero(tall_locop_ctx,
354 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000355}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000356
Holger Freytherd51524f2009-06-09 08:27:07 +0000357static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
358{
359 u_int32_t tmsi;
360
361 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
362 db_subscriber_alloc_tmsi(lchan->subscr);
363 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
364 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
365 release_loc_updating_req(lchan);
366 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
367 }
368
369 return 0;
370}
371
Holger Freyther7c19f742009-06-06 13:54:35 +0000372static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
373 void *handler_data, void *signal_data)
374{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800375 struct gsm_trans *trans, *temp;
376
Holger Freyther7c19f742009-06-06 13:54:35 +0000377 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
378 return 0;
379
380 /*
381 * Cancel any outstanding location updating request
382 * operation taking place on the lchan.
383 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200384 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200385 if (!lchan)
386 return 0;
387
Holger Freyther7c19f742009-06-06 13:54:35 +0000388 release_loc_updating_req(lchan);
389
Harald Welte4bfdfe72009-06-10 23:11:52 +0800390 /* Free all transactions that are associated with the released lchan */
Harald Welteaa0b29c2009-07-23 18:56:43 +0200391 /* FIXME: this is not neccessarily the right thing to do, we should
392 * only set trans->lchan to NULL and wait for another lchan to be
393 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800394 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
395 if (trans->lchan == lchan)
Harald Welteaa0b29c2009-07-23 18:56:43 +0200396 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800397 }
398
Holger Freyther7c19f742009-06-06 13:54:35 +0000399 return 0;
400}
401
402/*
403 * This will be ran by the linker when loading the DSO. We use it to
404 * do system initialization, e.g. registration of signal handlers.
405 */
406static __attribute__((constructor)) void on_dso_load_0408(void)
407{
Harald Welte7bfc2672009-07-28 00:41:45 +0200408 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
409 "loc_updating_oper");
Holger Freyther7c19f742009-06-06 13:54:35 +0000410 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
411}
412
Harald Welte52b1f982008-12-23 20:25:15 +0000413static void to_bcd(u_int8_t *bcd, u_int16_t val)
414{
Harald Welte4b634542008-12-27 01:55:51 +0000415 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000416 val = val / 10;
417 bcd[1] = val % 10;
418 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000419 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000420 val = val / 10;
421}
422
Holger Freyther17746612008-12-28 16:32:44 +0000423void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000424 u_int16_t mnc, u_int16_t lac)
425{
426 u_int8_t bcd[3];
427
428 to_bcd(bcd, mcc);
429 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
430 lai48->digits[1] = bcd[2];
431
432 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000433 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
434#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000435 lai48->digits[1] |= bcd[2] << 4;
436 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000437#else
438 lai48->digits[1] |= 0xf << 4;
439 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
440#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000441
Harald Welte4b634542008-12-27 01:55:51 +0000442 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000443}
444
Harald Welte255539c2008-12-28 02:26:27 +0000445#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000446#define MID_TMSI_LEN (TMSI_LEN + 2)
447
Harald Welte255539c2008-12-28 02:26:27 +0000448int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000449{
Harald Welte65e74cc2008-12-29 01:55:35 +0000450 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000451
Harald Welte4b634542008-12-27 01:55:51 +0000452 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000453 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000454 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000455 *tptr = htonl(tmsi);
456
457 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000458}
459
Harald Welte09e38af2009-02-16 22:52:23 +0000460static const char bcd_num_digits[] = {
461 '0', '1', '2', '3', '4', '5', '6', '7',
462 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
463};
464
Harald Welte0c389302009-06-10 12:08:54 +0800465/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
466int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
467 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000468{
469 u_int8_t in_len = bcd_lv[0];
470 int i;
471
Harald Welte0c389302009-06-10 12:08:54 +0800472 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000473 /* lower nibble */
474 output_len--;
475 if (output_len <= 1)
476 break;
477 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
478
479 /* higher nibble */
480 output_len--;
481 if (output_len <= 1)
482 break;
483 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
484 }
485 if (output_len >= 1)
486 *output++ = '\0';
487
Harald Welte0c389302009-06-10 12:08:54 +0800488 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000489}
490
491/* convert a single ASCII character to call-control BCD */
492static int asc_to_bcd(const char asc)
493{
494 int i;
495
496 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
497 if (bcd_num_digits[i] == asc)
498 return i;
499 }
500 return -EINVAL;
501}
502
Harald Welte0c389302009-06-10 12:08:54 +0800503/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000504int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800505 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000506{
507 int in_len = strlen(input);
508 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800509 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000510
511 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800512 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000513 if (in_len % 2)
514 bcd_lv[0]++;
515
Harald Welte0c389302009-06-10 12:08:54 +0800516 if (bcd_lv[0] > max_len)
517 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000518
519 for (i = 0; i < in_len; i++) {
520 int rc = asc_to_bcd(input[i]);
521 if (rc < 0)
522 return rc;
523 if (i % 2 == 0)
524 *bcd_cur = rc;
525 else
526 *bcd_cur++ |= (rc << 4);
527 }
528 /* append padding nibble in case of odd length */
529 if (i % 2)
530 *bcd_cur++ |= 0xf0;
531
532 /* return how many bytes we used */
533 return (bcd_cur - bcd_lv);
534}
535
Harald Welte0c389302009-06-10 12:08:54 +0800536/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800537static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800538 const u_int8_t *lv)
539{
540 u_int8_t in_len = lv[0];
541 int i, s;
542
543 if (in_len < 1)
544 return -EINVAL;
545
Harald Welte4bfdfe72009-06-10 23:11:52 +0800546 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800547
548 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800549 bcap->transfer = lv[1] & 0x07;
550 bcap->mode = (lv[1] & 0x08) >> 3;
551 bcap->coding = (lv[1] & 0x10) >> 4;
552 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800553
554 i = 1;
555 s = 0;
556 while(!(lv[i] & 0x80)) {
557 i++; /* octet 3a etc */
558 if (in_len < i)
559 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800560 bcap->speech_ver[s++] = lv[i] & 0x0f;
561 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800562 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800563 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800564 if (s == 7) /* maximum speech versions + end of list */
565 return 0;
566 }
567
568 return 0;
569}
570
571/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800572static int encode_bearer_cap(struct msgb *msg, int lv_only,
573 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800574{
575 u_int8_t lv[32 + 1];
576 int i, s;
577
Harald Welte4bfdfe72009-06-10 23:11:52 +0800578 lv[1] = bcap->transfer;
579 lv[1] |= bcap->mode << 3;
580 lv[1] |= bcap->coding << 4;
581 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800582
583 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800584 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800585 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800586 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800587 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800588 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800589 }
590 lv[i] |= 0x80; /* last IE of octet 3 etc */
591
592 lv[0] = i;
593 if (lv_only)
594 msgb_lv_put(msg, lv[0], lv+1);
595 else
596 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
597
598 return 0;
599}
600
601/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800602static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800603{
604 u_int8_t in_len = lv[0];
605
606 if (in_len < 1)
607 return -EINVAL;
608
609 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800610 ccap->dtmf = lv[1] & 0x01;
611 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800612
613 return 0;
614}
615
616/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800617static int decode_called(struct gsm_mncc_number *called,
618 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800619{
620 u_int8_t in_len = lv[0];
621
622 if (in_len < 1)
623 return -EINVAL;
624
625 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800626 called->plan = lv[1] & 0x0f;
627 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800628
629 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800630 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800631
632 return 0;
633}
634
635/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800636static int encode_called(struct msgb *msg,
637 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800638{
639 u_int8_t lv[18];
640 int ret;
641
642 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800643 lv[1] = called->plan;
644 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800645
646 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800647 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800648 if (ret < 0)
649 return ret;
650
651 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
652
653 return 0;
654}
655
656/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800657static int encode_callerid(struct msgb *msg, int ie,
658 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800659{
660 u_int8_t lv[13];
661 int h_len = 1;
662 int ret;
663
664 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800665 lv[1] = callerid->plan;
666 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800667
Harald Welte4bfdfe72009-06-10 23:11:52 +0800668 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800669 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800670 lv[2] = callerid->screen;
671 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800672 lv[2] |= 0x80;
673 h_len++;
674 } else
675 lv[1] |= 0x80;
676
677 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800678 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800679 if (ret < 0)
680 return ret;
681
682 msgb_tlv_put(msg, ie, lv[0], lv+1);
683
684 return 0;
685}
686
687/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800688static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800689 const u_int8_t *lv)
690{
691 u_int8_t in_len = lv[0];
692 int i;
693
694 if (in_len < 2)
695 return -EINVAL;
696
Harald Welte4bfdfe72009-06-10 23:11:52 +0800697 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800698
699 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800700 cause->location = lv[1] & 0x0f;
701 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800702
703 i = 1;
704 if (!(lv[i] & 0x80)) {
705 i++; /* octet 3a */
706 if (in_len < i+1)
707 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800708 cause->rec = 1;
709 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800710
711 }
712 i++;
713
714 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800715 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800716 i++;
717
718 if (in_len < i) /* no diag */
719 return 0;
720
721 if (in_len - (i-1) > 32) /* maximum 32 octets */
722 return 0;
723
724 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800725 memcpy(cause->diag, lv + i, in_len - (i-1));
726 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800727
728 return 0;
729}
730
731/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800732static int encode_cause(struct msgb *msg, int lv_only,
733 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800734{
735 u_int8_t lv[32+4];
736 int i;
737
Harald Welte4bfdfe72009-06-10 23:11:52 +0800738 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800739 return -EINVAL;
740
741 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800742 lv[1] = cause->location;
743 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800744
745 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800746 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800747 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800748 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800749 }
750 lv[i] |= 0x80; /* end of octet 3 */
751
752 /* octet 4 */
753 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800754 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800755
756 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800757 if (cause->diag_len) {
758 memcpy(lv + i, cause->diag, cause->diag_len);
759 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800760 }
761
762 lv[0] = i;
763 if (lv_only)
764 msgb_lv_put(msg, lv[0], lv+1);
765 else
766 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
767
768 return 0;
769}
770
771/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800772static int encode_calling(struct msgb *msg,
773 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800774{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800775 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800776}
777
778/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800779static int encode_connected(struct msgb *msg,
780 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800781{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800782 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800783}
784
785/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800786static int encode_redirecting(struct msgb *msg,
787 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800788{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800789 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800790}
791
792/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800793static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800794 const u_int8_t *lv)
795{
796 u_int8_t in_len = lv[0];
797
798 if (in_len < 1)
799 return -EINVAL;
800
Harald Welte4bfdfe72009-06-10 23:11:52 +0800801 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800802 return -EINVAL;
803
Harald Welte4bfdfe72009-06-10 23:11:52 +0800804 memcpy(facility->info, lv+1, in_len);
805 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800806
807 return 0;
808}
809
810/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800811static int encode_facility(struct msgb *msg, int lv_only,
812 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800813{
814 u_int8_t lv[GSM_MAX_FACILITY + 1];
815
Harald Welte4bfdfe72009-06-10 23:11:52 +0800816 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800817 return -EINVAL;
818
Harald Welte4bfdfe72009-06-10 23:11:52 +0800819 memcpy(lv+1, facility->info, facility->len);
820 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800821 if (lv_only)
822 msgb_lv_put(msg, lv[0], lv+1);
823 else
824 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
825
826 return 0;
827}
828
829/* decode 'notify' */
830static int decode_notify(int *notify, const u_int8_t *v)
831{
832 *notify = v[0] & 0x7f;
833
834 return 0;
835}
836
837/* encode 'notify' */
838static int encode_notify(struct msgb *msg, int notify)
839{
840 msgb_v_put(msg, notify | 0x80);
841
842 return 0;
843}
844
845/* encode 'signal' */
846static int encode_signal(struct msgb *msg, int signal)
847{
848 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
849
850 return 0;
851}
852
853/* decode 'keypad' */
854static int decode_keypad(int *keypad, const u_int8_t *lv)
855{
856 u_int8_t in_len = lv[0];
857
858 if (in_len < 1)
859 return -EINVAL;
860
861 *keypad = lv[1] & 0x7f;
862
863 return 0;
864}
865
866/* encode 'keypad' */
867static int encode_keypad(struct msgb *msg, int keypad)
868{
869 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
870
871 return 0;
872}
873
874/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800875static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800876 const u_int8_t *lv)
877{
878 u_int8_t in_len = lv[0];
879
880 if (in_len < 2)
881 return -EINVAL;
882
Harald Welte4bfdfe72009-06-10 23:11:52 +0800883 progress->coding = (lv[1] & 0x60) >> 5;
884 progress->location = lv[1] & 0x0f;
885 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800886
887 return 0;
888}
889
890/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800891static int encode_progress(struct msgb *msg, int lv_only,
892 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800893{
894 u_int8_t lv[3];
895
896 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800897 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
898 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800899 if (lv_only)
900 msgb_lv_put(msg, lv[0], lv+1);
901 else
902 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
903
904 return 0;
905}
906
907/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800908static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800909 const u_int8_t *lv)
910{
911 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800912 char *info = uu->info;
913 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800914 int i;
915
916 if (in_len < 1)
917 return -EINVAL;
918
Harald Welte4bfdfe72009-06-10 23:11:52 +0800919 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800920
921 for (i = 2; i <= in_len; i++) {
922 info_len--;
923 if (info_len <= 1)
924 break;
925 *info++ = lv[i];
926 }
927 if (info_len >= 1)
928 *info++ = '\0';
929
930 return 0;
931}
932
933/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800934static int encode_useruser(struct msgb *msg, int lv_only,
935 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800936{
937 u_int8_t lv[GSM_MAX_USERUSER + 2];
938
Harald Welte4bfdfe72009-06-10 23:11:52 +0800939 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800940 return -EINVAL;
941
Harald Welte4bfdfe72009-06-10 23:11:52 +0800942 lv[0] = 1 + strlen(uu->info);
943 lv[1] = uu->proto;
944 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800945 if (lv_only)
946 msgb_lv_put(msg, lv[0], lv+1);
947 else
948 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
949
950 return 0;
951}
952
953/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800954static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800955 const u_int8_t *lv)
956{
957 u_int8_t in_len = lv[0];
958
Harald Welte4bfdfe72009-06-10 23:11:52 +0800959 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800960 return -EINVAL;
961
Harald Welte4bfdfe72009-06-10 23:11:52 +0800962 memcpy(ssv->info, lv + 1, in_len);
963 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800964
965 return 0;
966}
967
968/* encode 'more data' */
969static int encode_more(struct msgb *msg)
970{
971 u_int8_t *ie;
972
973 ie = msgb_put(msg, 1);
974 ie[0] = GSM48_IE_MORE_DATA;
975
976 return 0;
977}
978
Holger Freyther819dd202009-01-04 03:52:50 +0000979struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000980{
Harald Welte966636f2009-06-26 19:39:35 +0200981 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
982 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000983}
984
Harald Welte39e2ead2009-07-23 21:13:03 +0200985int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000986{
Harald Welte39e2ead2009-07-23 21:13:03 +0200987 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
988
989 /* if we get passed a transaction reference, do some common
990 * work that the caller no longer has to do */
991 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200992 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200993 msg->lchan = trans->lchan;
994 }
995
Harald Welte65e74cc2008-12-29 01:55:35 +0000996 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000997 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000998
Harald Welte4bfdfe72009-06-10 23:11:52 +0800999 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1000 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1001 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1002 msg->trx->nr, msg->lchan->ts->nr,
1003 gh->proto_discr & 0xf0,
1004 cc_msg_names[gh->msg_type & 0x3f]);
1005 else
1006 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1007 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1008 msg->trx->nr, msg->lchan->ts->nr,
1009 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001010 }
1011
Harald Welte4b634542008-12-27 01:55:51 +00001012 msg->l3h = msg->data;
1013
Harald Welte8470bf22008-12-25 23:28:35 +00001014 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001015}
1016
Holger Freyther429e7762008-12-30 13:28:30 +00001017/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001018int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001019{
Harald Welte8470bf22008-12-25 23:28:35 +00001020 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001021 struct gsm48_hdr *gh;
1022
Harald Welte8470bf22008-12-25 23:28:35 +00001023 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001024
1025 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1026 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001027 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001028 gh->data[0] = cause;
1029
Harald Weltedb253af2008-12-30 17:56:55 +00001030 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1031
Harald Welte39e2ead2009-07-23 21:13:03 +02001032 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001033}
1034
1035/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001036int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001037{
Harald Welte8470bf22008-12-25 23:28:35 +00001038 struct gsm_bts *bts = lchan->ts->trx->bts;
1039 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001040 struct gsm48_hdr *gh;
1041 struct gsm48_loc_area_id *lai;
1042 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001043 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001044
Harald Welte8470bf22008-12-25 23:28:35 +00001045 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001046
1047 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1048 gh->proto_discr = GSM48_PDISC_MM;
1049 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1050
1051 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001052 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001053 bts->network->network_code, bts->location_area_code);
1054
1055 mid = msgb_put(msg, MID_TMSI_LEN);
1056 generate_mid_from_tmsi(mid, tmsi);
1057
1058 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1059
Harald Welte39e2ead2009-07-23 21:13:03 +02001060 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001061
Harald Weltedb253af2008-12-30 17:56:55 +00001062 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001063
Holger Freyther07cc8d82008-12-29 06:23:46 +00001064 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001065}
1066
Harald Weltefc977a82008-12-27 10:19:37 +00001067static char bcd2char(u_int8_t bcd)
1068{
1069 if (bcd < 0xa)
1070 return '0' + bcd;
1071 else
1072 return 'A' + (bcd - 0xa);
1073}
1074
Harald Weltebf5e8df2009-02-03 12:59:45 +00001075/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001076static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1077{
1078 int i;
1079 u_int8_t mi_type;
1080 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001081 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001082
1083 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1084
1085 switch (mi_type) {
1086 case GSM_MI_TYPE_NONE:
1087 break;
1088 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001089 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1090 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1091 memcpy(&tmsi, &mi[1], 4);
1092 tmsi = ntohl(tmsi);
1093 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001094 }
1095 break;
1096 case GSM_MI_TYPE_IMSI:
1097 case GSM_MI_TYPE_IMEI:
1098 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001099 *str_cur++ = bcd2char(mi[0] >> 4);
1100
1101 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001102 if (str_cur + 2 >= string + str_len)
1103 return str_cur - string;
1104 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001105 /* skip last nibble in last input byte when GSM_EVEN */
1106 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1107 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001108 }
1109 break;
1110 default:
1111 break;
1112 }
Harald Weltefc977a82008-12-27 10:19:37 +00001113 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001114
Harald Weltefc977a82008-12-27 10:19:37 +00001115 return str_cur - string;
1116}
1117
Harald Weltebf5e8df2009-02-03 12:59:45 +00001118/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001119static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1120{
1121 struct msgb *msg = gsm48_msgb_alloc();
1122 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001123
Harald Welte231ad4f2008-12-27 11:15:38 +00001124 msg->lchan = lchan;
1125
1126 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1127 gh->proto_discr = GSM48_PDISC_MM;
1128 gh->msg_type = GSM48_MT_MM_ID_REQ;
1129 gh->data[0] = id_type;
1130
Harald Welte39e2ead2009-07-23 21:13:03 +02001131 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001132}
1133
1134#define MI_SIZE 32
1135
Harald Weltebf5e8df2009-02-03 12:59:45 +00001136/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001137static int mm_rx_id_resp(struct msgb *msg)
1138{
1139 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001140 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001141 struct gsm_bts *bts = lchan->ts->trx->bts;
1142 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001143 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1144 char mi_string[MI_SIZE];
1145
1146 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001147 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001148 mi_type, mi_string);
1149
Harald Welte75a983f2008-12-27 21:34:06 +00001150 switch (mi_type) {
1151 case GSM_MI_TYPE_IMSI:
1152 if (!lchan->subscr)
Harald Welte761e9442009-07-23 19:21:02 +02001153 lchan->subscr = db_create_subscriber(net, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001154 if (lchan->loc_operation)
1155 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001156 break;
1157 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001158 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001159 /* update subscribe <-> IMEI mapping */
1160 if (lchan->subscr)
1161 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001162 if (lchan->loc_operation)
1163 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001164 break;
1165 }
Holger Freyther73487a22008-12-31 18:53:57 +00001166
1167 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001168 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001169}
1170
Harald Welte255539c2008-12-28 02:26:27 +00001171
1172static void loc_upd_rej_cb(void *data)
1173{
1174 struct gsm_lchan *lchan = data;
1175
Holger Freyther73487a22008-12-31 18:53:57 +00001176 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001177 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001178 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001179}
1180
Holger Freytherb7193e42008-12-29 17:44:08 +00001181static void schedule_reject(struct gsm_lchan *lchan)
1182{
Holger Freyther73487a22008-12-31 18:53:57 +00001183 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1184 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001185 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001186}
1187
Harald Welte2a139372009-02-22 21:14:55 +00001188static const char *lupd_name(u_int8_t type)
1189{
1190 switch (type) {
1191 case GSM48_LUPD_NORMAL:
1192 return "NORMAL";
1193 case GSM48_LUPD_PERIODIC:
1194 return "PEROIDOC";
1195 case GSM48_LUPD_IMSI_ATT:
1196 return "IMSI ATTACH";
1197 default:
1198 return "UNKNOWN";
1199 }
1200}
1201
Harald Welte231ad4f2008-12-27 11:15:38 +00001202#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001203/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001204static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001205{
Harald Welte8470bf22008-12-25 23:28:35 +00001206 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001207 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001208 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001209 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001210 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001211 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001212 char mi_string[MI_SIZE];
1213 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001214
Harald Welte8470bf22008-12-25 23:28:35 +00001215 lu = (struct gsm48_loc_upd_req *) gh->data;
1216
1217 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001218
Harald Weltefc977a82008-12-27 10:19:37 +00001219 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1220
Harald Weltea0368542009-06-27 02:58:43 +02001221 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001222 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001223
Holger Freythereaf04692009-06-06 13:54:44 +00001224 /*
1225 * Pseudo Spoof detection: Just drop a second/concurrent
1226 * location updating request.
1227 */
1228 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001229 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001230 lchan->loc_operation);
1231 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1232 return 0;
1233 }
1234
Holger Freyther73487a22008-12-31 18:53:57 +00001235 allocate_loc_updating_req(lchan);
1236
Harald Welte52b1f982008-12-23 20:25:15 +00001237 switch (mi_type) {
1238 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001239 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001240 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001241 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001242 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001243
Harald Welte52b1f982008-12-23 20:25:15 +00001244 /* look up subscriber based on IMSI */
Harald Welte761e9442009-07-23 19:21:02 +02001245 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001246 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001247 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001248 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001249 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001250 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001251 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001252
Harald Welte52b1f982008-12-23 20:25:15 +00001253 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte761e9442009-07-23 19:21:02 +02001254 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001255 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001256 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001257 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001258 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001259 }
1260 break;
1261 case GSM_MI_TYPE_IMEI:
1262 case GSM_MI_TYPE_IMEISV:
1263 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001264 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001265 break;
1266 default:
Harald Weltea0368542009-06-27 02:58:43 +02001267 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001268 break;
1269 }
1270
Harald Welte24516ea2009-07-04 10:18:00 +02001271 /* schedule the reject timer */
1272 schedule_reject(lchan);
1273
Harald Welte4bfdfe72009-06-10 23:11:52 +08001274 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001275 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001276 /* FIXME: request id? close channel? */
1277 return -EINVAL;
1278 }
1279
Harald Welte255539c2008-12-28 02:26:27 +00001280 lchan->subscr = subscr;
1281
Harald Welte24516ea2009-07-04 10:18:00 +02001282 /* check if we can let the subscriber into our network immediately
1283 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001284 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001285}
1286
Harald Welte7584aea2009-02-11 11:44:12 +00001287/* 9.1.5 Channel mode modify */
1288int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1289{
1290 struct msgb *msg = gsm48_msgb_alloc();
1291 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1292 struct gsm48_chan_mode_modify *cmm =
1293 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001294 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001295
Harald Welte4a543e82009-02-28 13:17:55 +00001296 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001297
Harald Welte45b407a2009-05-23 15:51:12 +00001298 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001299 msg->lchan = lchan;
1300 gh->proto_discr = GSM48_PDISC_RR;
1301 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1302
1303 /* fill the channel information element, this code
1304 * should probably be shared with rsl_rx_chan_rqd() */
1305 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001306 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001307 cmm->chan_desc.h0.h = 0;
1308 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1309 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1310 cmm->mode = mode;
1311
Harald Welte39e2ead2009-07-23 21:13:03 +02001312 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001313}
1314
Harald Welte4bfdfe72009-06-10 23:11:52 +08001315#if 0
1316static u_int8_t to_bcd8(u_int8_t val)
1317{
1318 return ((val / 10) << 4) | (val % 10);
1319}
1320#endif
1321
Harald Weltedb253af2008-12-30 17:56:55 +00001322/* Section 9.2.15a */
1323int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1324{
1325 struct msgb *msg = gsm48_msgb_alloc();
1326 struct gsm48_hdr *gh;
1327 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001328 u_int8_t *ptr8;
1329 u_int16_t *ptr16;
1330 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001331 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001332#if 0
1333 time_t cur_t;
1334 struct tm* cur_time;
1335 int tz15min;
1336#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001337
1338 msg->lchan = lchan;
1339
1340 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1341 gh->proto_discr = GSM48_PDISC_MM;
1342 gh->msg_type = GSM48_MT_MM_INFO;
1343
1344 if (net->name_long) {
1345 name_len = strlen(net->name_long);
1346 /* 10.5.3.5a */
1347 ptr8 = msgb_put(msg, 3);
1348 ptr8[0] = GSM48_IE_NAME_LONG;
1349 ptr8[1] = name_len*2 +1;
1350 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1351
1352 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1353 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001354 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001355
1356 /* FIXME: Use Cell Broadcast, not UCS-2, since
1357 * UCS-2 is only supported by later revisions of the spec */
1358 }
1359
1360 if (net->name_short) {
1361 name_len = strlen(net->name_short);
1362 /* 10.5.3.5a */
1363 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001364 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001365 ptr8[1] = name_len*2 + 1;
1366 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1367
Harald Weltee872cb12009-01-01 00:33:37 +00001368 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001369 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001370 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001371 }
1372
1373#if 0
1374 /* Section 10.5.3.9 */
1375 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001376 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001377 ptr8 = msgb_put(msg, 8);
1378 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1379 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1380 ptr8[2] = to_bcd8(cur_time->tm_mon);
1381 ptr8[3] = to_bcd8(cur_time->tm_mday);
1382 ptr8[4] = to_bcd8(cur_time->tm_hour);
1383 ptr8[5] = to_bcd8(cur_time->tm_min);
1384 ptr8[6] = to_bcd8(cur_time->tm_sec);
1385 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1386 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001387 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001388 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001389 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001390#endif
1391
Harald Welte39e2ead2009-07-23 21:13:03 +02001392 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001393}
1394
Harald Welte4b634542008-12-27 01:55:51 +00001395static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1396{
Harald Welte4b634542008-12-27 01:55:51 +00001397 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001398 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001399}
Harald Welteba4cf162009-01-10 01:49:35 +00001400
1401/* 9.2.6 CM service reject */
1402static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1403 enum gsm48_reject_value value)
1404{
1405 struct msgb *msg = gsm48_msgb_alloc();
1406 struct gsm48_hdr *gh;
1407
1408 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1409
1410 msg->lchan = lchan;
1411 use_lchan(lchan);
1412
1413 gh->proto_discr = GSM48_PDISC_MM;
1414 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1415 gh->data[0] = value;
1416 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1417
Harald Welte39e2ead2009-07-23 21:13:03 +02001418 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001419}
1420
Harald Welte4ed0e922009-01-10 03:17:30 +00001421
1422/*
1423 * Handle CM Service Requests
1424 * a) Verify that the packet is long enough to contain the information
1425 * we require otherwsie reject with INCORRECT_MESSAGE
1426 * b) Try to parse the TMSI. If we do not have one reject
1427 * c) Check that we know the subscriber with the TMSI otherwise reject
1428 * with a HLR cause
1429 * d) Set the subscriber on the gsm_lchan and accept
1430 */
Harald Welte4b634542008-12-27 01:55:51 +00001431static int gsm48_rx_mm_serv_req(struct msgb *msg)
1432{
Harald Welteba4cf162009-01-10 01:49:35 +00001433 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001434 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001435
Harald Welte761e9442009-07-23 19:21:02 +02001436 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001437 struct gsm_subscriber *subscr;
1438 struct gsm48_hdr *gh = msgb_l3(msg);
1439 struct gsm48_service_request *req =
1440 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001441 /* unfortunately in Phase1 the classmar2 length is variable */
1442 u_int8_t classmark2_len = gh->data[1];
1443 u_int8_t *classmark2 = gh->data+2;
1444 u_int8_t mi_len = *(classmark2 + classmark2_len);
1445 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001446
Harald Weltec9e02182009-05-01 19:07:53 +00001447 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001448 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001449 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001450 return gsm48_tx_mm_serv_rej(msg->lchan,
1451 GSM48_REJECT_INCORRECT_MESSAGE);
1452 }
1453
1454 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001455 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001456 return gsm48_tx_mm_serv_rej(msg->lchan,
1457 GSM48_REJECT_INCORRECT_MESSAGE);
1458 }
1459
Harald Weltec9e02182009-05-01 19:07:53 +00001460 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001461 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001462 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001463 return gsm48_tx_mm_serv_rej(msg->lchan,
1464 GSM48_REJECT_INCORRECT_MESSAGE);
1465 }
1466
Harald Weltec9e02182009-05-01 19:07:53 +00001467 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001468 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001469 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001470
Harald Welte761e9442009-07-23 19:21:02 +02001471 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001472
Harald Welte2a139372009-02-22 21:14:55 +00001473 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001474 if (!subscr)
1475 return gsm48_tx_mm_serv_rej(msg->lchan,
1476 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1477
1478 if (!msg->lchan->subscr)
1479 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001480 else if (msg->lchan->subscr != subscr) {
1481 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1482 subscr_put(subscr);
1483 }
1484
Harald Weltec2e302d2009-07-05 14:08:13 +02001485 subscr->equipment.classmark2_len = classmark2_len;
1486 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1487 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001488
Harald Welte4b634542008-12-27 01:55:51 +00001489 return gsm48_tx_mm_serv_ack(msg->lchan);
1490}
1491
Harald Welte2a139372009-02-22 21:14:55 +00001492static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1493{
Harald Welte761e9442009-07-23 19:21:02 +02001494 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001495 struct gsm48_hdr *gh = msgb_l3(msg);
1496 struct gsm48_imsi_detach_ind *idi =
1497 (struct gsm48_imsi_detach_ind *) gh->data;
1498 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1499 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001500 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001501
1502 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1503 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1504 mi_type, mi_string);
1505
1506 switch (mi_type) {
1507 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001508 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001509 break;
1510 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001511 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001512 break;
1513 case GSM_MI_TYPE_IMEI:
1514 case GSM_MI_TYPE_IMEISV:
1515 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001516 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001517 break;
1518 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001519 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001520 break;
1521 }
1522
Holger Freyther4a49e772009-04-12 05:37:29 +00001523 if (subscr) {
1524 subscr_update(subscr, msg->trx->bts,
1525 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001526 DEBUGP(DMM, "Subscriber: %s\n",
1527 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001528 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001529 } else
Harald Welte2a139372009-02-22 21:14:55 +00001530 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1531
Harald Welte2a139372009-02-22 21:14:55 +00001532 return 0;
1533}
1534
Harald Welted2a7f5a2009-06-05 20:08:20 +00001535static int gsm48_rx_mm_status(struct msgb *msg)
1536{
1537 struct gsm48_hdr *gh = msgb_l3(msg);
1538
1539 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1540
1541 return 0;
1542}
1543
Harald Weltebf5e8df2009-02-03 12:59:45 +00001544/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001545static int gsm0408_rcv_mm(struct msgb *msg)
1546{
1547 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001548 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001549
1550 switch (gh->msg_type & 0xbf) {
1551 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001552 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001553 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001554 break;
1555 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001556 rc = mm_rx_id_resp(msg);
1557 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001558 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001559 rc = gsm48_rx_mm_serv_req(msg);
1560 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001561 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001562 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001563 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001564 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001565 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1566 msg->lchan->subscr ?
1567 msg->lchan->subscr->imsi :
1568 "unknown subscriber");
1569 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001570 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001571 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1572 break;
1573 case GSM48_MT_MM_CM_REEST_REQ:
1574 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1575 break;
1576 case GSM48_MT_MM_AUTH_RESP:
1577 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001578 break;
1579 default:
1580 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1581 gh->msg_type);
1582 break;
1583 }
1584
1585 return rc;
1586}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001587
Harald Welte2d35ae62009-02-06 12:02:13 +00001588/* Receive a PAGING RESPONSE message from the MS */
1589static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1590{
Harald Welte761e9442009-07-23 19:21:02 +02001591 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001592 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001593 u_int8_t *classmark2_lv = gh->data + 1;
1594 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1595 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001596 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001597 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001598 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001599 int rc = 0;
1600
Harald Welte61548982009-02-22 21:26:29 +00001601 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001602 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1603 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001604 switch (mi_type) {
1605 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001606 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001607 break;
1608 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001609 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001610 break;
1611 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001612
1613 if (!subscr) {
1614 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001615 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001616 return -EINVAL;
1617 }
1618 DEBUGP(DRR, "<- Channel was requested by %s\n",
1619 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001620
Harald Weltec2e302d2009-07-05 14:08:13 +02001621 subscr->equipment.classmark2_len = *classmark2_lv;
1622 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1623 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001624
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001625 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001626 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001627 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001628 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1629 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001630 return -EINVAL;
1631 } else {
1632 DEBUGP(DRR, "<- Channel already owned by us\n");
1633 subscr_put(subscr);
1634 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001635 }
1636
Harald Welte595ad7b2009-02-16 22:05:44 +00001637 sig_data.subscr = subscr;
1638 sig_data.bts = msg->lchan->ts->trx->bts;
1639 sig_data.lchan = msg->lchan;
1640
1641 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001642
1643 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001644 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001645
Harald Welte7584aea2009-02-11 11:44:12 +00001646 /* FIXME: somehow signal the completion of the PAGING to
1647 * the entity that requested the paging */
1648
Harald Welte2d35ae62009-02-06 12:02:13 +00001649 return rc;
1650}
1651
Harald Weltef7c43522009-06-09 20:24:21 +00001652static int gsm48_rx_rr_classmark(struct msgb *msg)
1653{
1654 struct gsm48_hdr *gh = msgb_l3(msg);
1655 struct gsm_subscriber *subscr = msg->lchan->subscr;
1656 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1657 u_int8_t cm2_len, cm3_len = 0;
1658 u_int8_t *cm2, *cm3 = NULL;
1659
1660 DEBUGP(DRR, "CLASSMARK CHANGE ");
1661
1662 /* classmark 2 */
1663 cm2_len = gh->data[0];
1664 cm2 = &gh->data[1];
1665 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1666
1667 if (payload_len > cm2_len + 1) {
1668 /* we must have a classmark3 */
1669 if (gh->data[cm2_len+1] != 0x20) {
1670 DEBUGPC(DRR, "ERR CM3 TAG\n");
1671 return -EINVAL;
1672 }
1673 if (cm2_len > 3) {
1674 DEBUGPC(DRR, "CM2 too long!\n");
1675 return -EINVAL;
1676 }
1677
1678 cm3_len = gh->data[cm2_len+2];
1679 cm3 = &gh->data[cm2_len+3];
1680 if (cm3_len > 14) {
1681 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1682 return -EINVAL;
1683 }
1684 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1685 }
1686 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001687 subscr->equipment.classmark2_len = cm2_len;
1688 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001689 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001690 subscr->equipment.classmark3_len = cm3_len;
1691 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001692 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001693 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001694 }
1695
Harald Weltef7c43522009-06-09 20:24:21 +00001696 return 0;
1697}
1698
Harald Weltecf5b3592009-05-01 18:28:42 +00001699static int gsm48_rx_rr_status(struct msgb *msg)
1700{
1701 struct gsm48_hdr *gh = msgb_l3(msg);
1702
1703 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1704 rr_cause_name(gh->data[0]));
1705
1706 return 0;
1707}
1708
Harald Weltef7c43522009-06-09 20:24:21 +00001709static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1710{
1711 struct gsm48_hdr *gh = msgb_l3(msg);
1712 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1713 static struct gsm_meas_rep meas_rep;
1714
Harald Welte10d0e672009-06-27 02:53:10 +02001715 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001716 parse_meas_rep(&meas_rep, gh->data, payload_len);
1717 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001718 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001719 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001720 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001721 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001722 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001723 else
Harald Welte10d0e672009-06-27 02:53:10 +02001724 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001725 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1726 meas_rep.rxqual_sub);
1727
Harald Welte10d0e672009-06-27 02:53:10 +02001728 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001729
1730 /* FIXME: put the results somwhere */
1731
1732 return 0;
1733}
1734
Harald Weltebf5e8df2009-02-03 12:59:45 +00001735/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001736static int gsm0408_rcv_rr(struct msgb *msg)
1737{
1738 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001739 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001740
1741 switch (gh->msg_type) {
1742 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001743 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001744 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001745 case GSM48_MT_RR_GPRS_SUSP_REQ:
1746 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1747 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001748 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001749 rc = gsm48_rr_rx_pag_resp(msg);
1750 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001751 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1752 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001753 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001754 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001755 case GSM48_MT_RR_STATUS:
1756 rc = gsm48_rx_rr_status(msg);
1757 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001758 case GSM48_MT_RR_MEAS_REP:
1759 rc = gsm48_rx_rr_meas_rep(msg);
1760 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001761 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001762 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001763 gh->msg_type);
1764 break;
1765 }
1766
Harald Welte2d35ae62009-02-06 12:02:13 +00001767 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001768}
1769
Holger Freythere64a7a32009-02-06 21:55:37 +00001770/* 7.1.7 and 9.1.7 Channel release*/
1771int gsm48_send_rr_release(struct gsm_lchan *lchan)
1772{
1773 struct msgb *msg = gsm48_msgb_alloc();
1774 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1775 u_int8_t *cause;
1776
1777 msg->lchan = lchan;
1778 gh->proto_discr = GSM48_PDISC_RR;
1779 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1780
1781 cause = msgb_put(msg, 1);
1782 cause[0] = GSM48_RR_CAUSE_NORMAL;
1783
1784 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1785 lchan->nr, lchan->type);
1786
Harald Welteae0f2362009-07-19 18:36:49 +02001787 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001788 gsm48_sendmsg(msg, NULL);
Harald Welteae0f2362009-07-19 18:36:49 +02001789
1790 /* Deactivate the SACCH on the BTS side */
1791 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001792}
1793
Harald Welte4bc90a12008-12-27 16:32:52 +00001794/* Call Control */
1795
Harald Welte7584aea2009-02-11 11:44:12 +00001796/* The entire call control code is written in accordance with Figure 7.10c
1797 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1798 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1799 * it for voice */
1800
Harald Welte4bfdfe72009-06-10 23:11:52 +08001801static void new_cc_state(struct gsm_trans *trans, int state)
1802{
1803 if (state > 31 || state < 0)
1804 return;
1805
1806 DEBUGP(DCC, "new state %s -> %s\n",
Harald Welteaa0b29c2009-07-23 18:56:43 +02001807 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001808
Harald Welteaa0b29c2009-07-23 18:56:43 +02001809 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001810}
1811
1812static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001813{
1814 struct msgb *msg = gsm48_msgb_alloc();
1815 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1816 u_int8_t *cause, *call_state;
1817
Harald Welte4bc90a12008-12-27 16:32:52 +00001818 gh->msg_type = GSM48_MT_CC_STATUS;
1819
1820 cause = msgb_put(msg, 3);
1821 cause[0] = 2;
1822 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1823 cause[2] = 0x80 | 30; /* response to status inquiry */
1824
1825 call_state = msgb_put(msg, 1);
1826 call_state[0] = 0xc0 | 0x00;
1827
Harald Welte39e2ead2009-07-23 21:13:03 +02001828 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001829}
1830
Harald Welte6f4b7532008-12-29 00:39:37 +00001831static int gsm48_tx_simple(struct gsm_lchan *lchan,
1832 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001833{
1834 struct msgb *msg = gsm48_msgb_alloc();
1835 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1836
1837 msg->lchan = lchan;
1838
Harald Welte6f4b7532008-12-29 00:39:37 +00001839 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001840 gh->msg_type = msg_type;
1841
Harald Welte39e2ead2009-07-23 21:13:03 +02001842 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001843}
1844
Harald Welte4bfdfe72009-06-10 23:11:52 +08001845static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1846{
Harald Welteaa0b29c2009-07-23 18:56:43 +02001847 if (bsc_timer_pending(&trans->cc.timer)) {
1848 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1849 bsc_del_timer(&trans->cc.timer);
1850 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001851 }
1852}
1853
1854static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1855 int msg_type, struct gsm_mncc *mncc)
1856{
1857 struct msgb *msg;
1858
1859 if (trans)
1860 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001861 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001862 "Sending '%s' to MNCC.\n",
1863 trans->lchan->ts->trx->bts->nr,
1864 trans->lchan->ts->trx->nr,
1865 trans->lchan->ts->nr, trans->transaction_id,
1866 (trans->subscr)?(trans->subscr->extension):"-",
1867 get_mncc_name(msg_type));
1868 else
1869 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1870 "Sending '%s' to MNCC.\n",
1871 (trans->subscr)?(trans->subscr->extension):"-",
1872 get_mncc_name(msg_type));
1873 else
1874 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1875 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1876
1877 mncc->msg_type = msg_type;
1878
Harald Welte966636f2009-06-26 19:39:35 +02001879 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001880 if (!msg)
1881 return -ENOMEM;
1882 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1883 msgb_enqueue(&net->upqueue, msg);
1884
1885 return 0;
1886}
1887
1888int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1889 u_int32_t callref, int location, int value)
1890{
1891 struct gsm_mncc rel;
1892
Harald Welte92f70c52009-06-12 01:54:08 +08001893 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001894 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001895 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001896 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1897}
1898
Harald Welteaa0b29c2009-07-23 18:56:43 +02001899/* Call Control Specific transaction release.
1900 * gets called by trans_free, DO NOT CALL YOURSELF! */
1901void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001902{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001903 gsm48_stop_cc_timer(trans);
1904
1905 /* send release to L4, if callref still exists */
1906 if (trans->callref) {
1907 /* Ressource unavailable */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001908 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001909 GSM48_CAUSE_LOC_PRN_S_LU,
1910 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001911 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02001912 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001913 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Welteaa0b29c2009-07-23 18:56:43 +02001914 if (trans->lchan)
1915 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001916}
1917
1918static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1919
Harald Welte09e38af2009-02-16 22:52:23 +00001920/* call-back from paging the B-end of the connection */
1921static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001922 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001923{
Harald Welte7ccf7782009-02-17 01:43:01 +00001924 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001925 struct gsm_subscriber *subscr = param;
1926 struct gsm_trans *transt, *tmp;
1927 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001928
Harald Welte09e38af2009-02-16 22:52:23 +00001929 if (hooknum != GSM_HOOK_RR_PAGING)
1930 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001931
1932 if (!subscr)
1933 return -EINVAL;
1934 net = subscr->net;
1935 if (!net) {
1936 DEBUGP(DCC, "Error Network not set!\n");
1937 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001938 }
Harald Welte7584aea2009-02-11 11:44:12 +00001939
Harald Welte4bfdfe72009-06-10 23:11:52 +08001940 /* check all tranactions (without lchan) for subscriber */
1941 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1942 if (transt->subscr != subscr || transt->lchan)
1943 continue;
1944 switch (event) {
1945 case GSM_PAGING_SUCCEEDED:
1946 if (!lchan) // paranoid
1947 break;
1948 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1949 subscr->extension);
1950 /* Assign lchan */
1951 if (!transt->lchan) {
1952 transt->lchan = lchan;
1953 use_lchan(lchan);
1954 }
1955 /* send SETUP request to called party */
Harald Welteaa0b29c2009-07-23 18:56:43 +02001956 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001957 if (is_ipaccess_bts(lchan->ts->trx->bts))
1958 rsl_ipacc_bind(lchan);
1959 break;
1960 case GSM_PAGING_EXPIRED:
1961 DEBUGP(DCC, "Paging subscr %s expired!\n",
1962 subscr->extension);
1963 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001964 mncc_release_ind(transt->subscr->net, transt,
1965 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001966 GSM48_CAUSE_LOC_PRN_S_LU,
1967 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001968 transt->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02001969 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001970 break;
1971 }
1972 }
Harald Welte09e38af2009-02-16 22:52:23 +00001973 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001974}
Harald Welte7584aea2009-02-11 11:44:12 +00001975
Harald Welte49f48b82009-02-17 15:29:33 +00001976/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001977static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001978{
Harald Welte11fa29c2009-02-19 17:24:39 +00001979 struct gsm_bts *bts = lchan->ts->trx->bts;
1980 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001981 struct gsm_bts_trx_ts *ts;
1982
Harald Welte11fa29c2009-02-19 17:24:39 +00001983 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1984 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1985 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1986
1987 if (bts->type != remote_bts->type) {
1988 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1989 return -EINVAL;
1990 }
Harald Welte49f48b82009-02-17 15:29:33 +00001991
Harald Welte11fa29c2009-02-19 17:24:39 +00001992 switch (bts->type) {
1993 case GSM_BTS_TYPE_NANOBTS_900:
1994 case GSM_BTS_TYPE_NANOBTS_1800:
1995 ts = remote_lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02001996 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
1997 ts->abis_ip.bound_port,
1998 lchan->ts->abis_ip.conn_id,
1999 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002000
2001 ts = lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002002 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2003 ts->abis_ip.bound_port,
2004 remote_lchan->ts->abis_ip.conn_id,
2005 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002006 break;
2007 case GSM_BTS_TYPE_BS11:
2008 trau_mux_map_lchan(lchan, remote_lchan);
2009 break;
2010 default:
2011 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2012 break;
2013 }
Harald Welte49f48b82009-02-17 15:29:33 +00002014
2015 return 0;
2016}
2017
Harald Welte4bfdfe72009-06-10 23:11:52 +08002018/* bridge channels of two transactions */
2019static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002020{
Harald Welteaa0b29c2009-07-23 18:56:43 +02002021 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2022 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002023
Harald Welte4bfdfe72009-06-10 23:11:52 +08002024 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002025 return -EIO;
2026
Harald Welte4bfdfe72009-06-10 23:11:52 +08002027 if (!trans1->lchan || !trans2->lchan)
2028 return -EIO;
2029
2030 /* through-connect channel */
2031 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002032}
2033
Harald Welte4bfdfe72009-06-10 23:11:52 +08002034/* enable receive of channels to upqueue */
2035static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2036{
2037 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002038
Harald Welte4bfdfe72009-06-10 23:11:52 +08002039 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002040 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002041 if (!trans)
2042 return -EIO;
2043 if (!trans->lchan)
2044 return 0;
2045
2046 // todo IPACCESS
2047 if (enable)
2048 return trau_recv_lchan(trans->lchan, data->callref);
2049 return trau_mux_unmap(NULL, data->callref);
2050}
2051
2052/* send a frame to channel */
2053static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2054{
2055 struct gsm_trans *trans;
2056
2057 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002058 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002059 if (!trans)
2060 return -EIO;
2061 if (!trans->lchan)
2062 return 0;
2063 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2064 trans->lchan->type != GSM_LCHAN_TCH_H)
2065 return 0;
2066
2067 // todo IPACCESS
2068 return trau_send_lchan(trans->lchan,
2069 (struct decoded_trau_frame *)frame->data);
2070}
2071
2072
2073static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2074{
2075 DEBUGP(DCC, "-> STATUS ENQ\n");
2076 return gsm48_cc_tx_status(trans, msg);
2077}
2078
2079static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2080static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2081
2082static void gsm48_cc_timeout(void *arg)
2083{
2084 struct gsm_trans *trans = arg;
2085 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002086 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2087 int mo_location = GSM48_CAUSE_LOC_USER;
2088 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2089 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002090 struct gsm_mncc mo_rel, l4_rel;
2091
2092 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2093 mo_rel.callref = trans->callref;
2094 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2095 l4_rel.callref = trans->callref;
2096
Harald Welteaa0b29c2009-07-23 18:56:43 +02002097 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002098 case 0x303:
2099 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002100 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002101 break;
2102 case 0x310:
2103 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002104 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002105 break;
2106 case 0x313:
2107 disconnect = 1;
2108 /* unknown, did not find it in the specs */
2109 break;
2110 case 0x301:
2111 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002112 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002113 break;
2114 case 0x308:
Harald Welteaa0b29c2009-07-23 18:56:43 +02002115 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002116 /* restart T308 a second time */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002117 gsm48_cc_tx_release(trans, &trans->cc.msg);
2118 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002119 break; /* stay in release state */
2120 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02002121 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002122 return;
2123// release = 1;
2124// l4_cause = 14;
2125// break;
2126 case 0x306:
2127 release = 1;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002128 mo_cause = trans->cc.msg.cause.value;
2129 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002130 break;
2131 case 0x323:
2132 disconnect = 1;
2133 break;
2134 default:
2135 release = 1;
2136 }
2137
2138 if (release && trans->callref) {
2139 /* process release towards layer 4 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002140 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002141 l4_location, l4_cause);
2142 trans->callref = 0;
2143 }
2144
2145 if (disconnect && trans->callref) {
2146 /* process disconnect towards layer 4 */
2147 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welteb3c3fae2009-07-23 19:06:52 +02002148 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002149 }
2150
2151 /* process disconnect towards mobile station */
2152 if (disconnect || release) {
2153 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002154 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2155 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2156 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002157 mo_rel.cause.diag_len = 3;
2158
2159 if (disconnect)
2160 gsm48_cc_tx_disconnect(trans, &mo_rel);
2161 if (release)
2162 gsm48_cc_tx_release(trans, &mo_rel);
2163 }
2164
2165}
2166
2167static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2168 int sec, int micro)
2169{
2170 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002171 trans->cc.timer.cb = gsm48_cc_timeout;
2172 trans->cc.timer.data = trans;
2173 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2174 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002175}
2176
2177static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2178{
2179 struct gsm48_hdr *gh = msgb_l3(msg);
2180 u_int8_t msg_type = gh->msg_type & 0xbf;
2181 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2182 struct tlv_parsed tp;
2183 struct gsm_mncc setup;
2184
2185 memset(&setup, 0, sizeof(struct gsm_mncc));
2186 setup.callref = trans->callref;
2187 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2188 /* emergency setup is identified by msg_type */
2189 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2190 setup.emergency = 1;
2191
2192 /* use subscriber as calling party number */
2193 if (trans->subscr) {
2194 setup.fields |= MNCC_F_CALLING;
2195 strncpy(setup.calling.number, trans->subscr->extension,
2196 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002197 strncpy(setup.imsi, trans->subscr->imsi,
2198 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002199 }
2200 /* bearer capability */
2201 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2202 setup.fields |= MNCC_F_BEARER_CAP;
2203 decode_bearer_cap(&setup.bearer_cap,
2204 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2205 }
2206 /* facility */
2207 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2208 setup.fields |= MNCC_F_FACILITY;
2209 decode_facility(&setup.facility,
2210 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2211 }
2212 /* called party bcd number */
2213 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2214 setup.fields |= MNCC_F_CALLED;
2215 decode_called(&setup.called,
2216 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2217 }
2218 /* user-user */
2219 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2220 setup.fields |= MNCC_F_USERUSER;
2221 decode_useruser(&setup.useruser,
2222 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2223 }
2224 /* ss-version */
2225 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2226 setup.fields |= MNCC_F_SSVERSION;
2227 decode_ssversion(&setup.ssversion,
2228 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2229 }
2230 /* CLIR suppression */
2231 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2232 setup.clir.sup = 1;
2233 /* CLIR invocation */
2234 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2235 setup.clir.inv = 1;
2236 /* cc cap */
2237 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2238 setup.fields |= MNCC_F_CCCAP;
2239 decode_cccap(&setup.cccap,
2240 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2241 }
2242
2243 if (is_ipaccess_bts(msg->trx->bts))
2244 rsl_ipacc_bind(msg->lchan);
2245
2246 new_cc_state(trans, GSM_CSTATE_INITIATED);
2247
2248 /* indicate setup to MNCC */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002249 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002250
2251 return 0;
2252}
2253
2254static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002255{
2256 struct msgb *msg = gsm48_msgb_alloc();
2257 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002258 struct gsm_mncc *setup = arg;
Harald Welteb49248b2009-07-23 21:36:44 +02002259 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00002260
Harald Welte7ccf7782009-02-17 01:43:01 +00002261 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002262
Harald Welte4bfdfe72009-06-10 23:11:52 +08002263 /* transaction id must not be assigned */
2264 if (trans->transaction_id != 0xff) { /* unasssigned */
2265 DEBUGP(DCC, "TX Setup with assigned transaction. "
2266 "This is not allowed!\n");
2267 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002268 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002269 GSM48_CAUSE_LOC_PRN_S_LU,
2270 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002271 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002272 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002273 return rc;
2274 }
2275
2276 /* Get free transaction_id */
Harald Welteb49248b2009-07-23 21:36:44 +02002277 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2278 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002279 /* no free transaction ID */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002280 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002281 GSM48_CAUSE_LOC_PRN_S_LU,
2282 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002283 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002284 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002285 return rc;
2286 }
Harald Welteb49248b2009-07-23 21:36:44 +02002287 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00002288
Harald Welte65e74cc2008-12-29 01:55:35 +00002289 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002290
Harald Welte4bfdfe72009-06-10 23:11:52 +08002291 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002292
Harald Welte4bfdfe72009-06-10 23:11:52 +08002293 /* bearer capability */
2294 if (setup->fields & MNCC_F_BEARER_CAP)
2295 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2296 /* facility */
2297 if (setup->fields & MNCC_F_FACILITY)
2298 encode_facility(msg, 0, &setup->facility);
2299 /* progress */
2300 if (setup->fields & MNCC_F_PROGRESS)
2301 encode_progress(msg, 0, &setup->progress);
2302 /* calling party BCD number */
2303 if (setup->fields & MNCC_F_CALLING)
2304 encode_calling(msg, &setup->calling);
2305 /* called party BCD number */
2306 if (setup->fields & MNCC_F_CALLED)
2307 encode_called(msg, &setup->called);
2308 /* user-user */
2309 if (setup->fields & MNCC_F_USERUSER)
2310 encode_useruser(msg, 0, &setup->useruser);
2311 /* redirecting party BCD number */
2312 if (setup->fields & MNCC_F_REDIRECTING)
2313 encode_redirecting(msg, &setup->redirecting);
2314 /* signal */
2315 if (setup->fields & MNCC_F_SIGNAL)
2316 encode_signal(msg, setup->signal);
2317
2318 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002319
Harald Welte39e2ead2009-07-23 21:13:03 +02002320 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002321}
2322
Harald Welte4bfdfe72009-06-10 23:11:52 +08002323static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2324{
2325 struct gsm48_hdr *gh = msgb_l3(msg);
2326 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2327 struct tlv_parsed tp;
2328 struct gsm_mncc call_conf;
2329
2330 gsm48_stop_cc_timer(trans);
2331 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2332
2333 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2334 call_conf.callref = trans->callref;
2335 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2336#if 0
2337 /* repeat */
2338 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2339 call_conf.repeat = 1;
2340 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2341 call_conf.repeat = 2;
2342#endif
2343 /* bearer capability */
2344 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2345 call_conf.fields |= MNCC_F_BEARER_CAP;
2346 decode_bearer_cap(&call_conf.bearer_cap,
2347 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2348 }
2349 /* cause */
2350 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2351 call_conf.fields |= MNCC_F_CAUSE;
2352 decode_cause(&call_conf.cause,
2353 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2354 }
2355 /* cc cap */
2356 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2357 call_conf.fields |= MNCC_F_CCCAP;
2358 decode_cccap(&call_conf.cccap,
2359 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2360 }
2361
2362 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2363
Harald Welteb3c3fae2009-07-23 19:06:52 +02002364 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2365 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002366}
2367
2368static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2369{
2370 struct gsm_mncc *proceeding = arg;
2371 struct msgb *msg = gsm48_msgb_alloc();
2372 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2373
Harald Welte4bfdfe72009-06-10 23:11:52 +08002374 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2375
2376 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2377
2378 /* bearer capability */
2379 if (proceeding->fields & MNCC_F_BEARER_CAP)
2380 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2381 /* facility */
2382 if (proceeding->fields & MNCC_F_FACILITY)
2383 encode_facility(msg, 0, &proceeding->facility);
2384 /* progress */
2385 if (proceeding->fields & MNCC_F_PROGRESS)
2386 encode_progress(msg, 0, &proceeding->progress);
2387
Harald Welte39e2ead2009-07-23 21:13:03 +02002388 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002389}
2390
2391static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2392{
2393 struct gsm48_hdr *gh = msgb_l3(msg);
2394 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2395 struct tlv_parsed tp;
2396 struct gsm_mncc alerting;
2397
2398 gsm48_stop_cc_timer(trans);
2399 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2400
2401 memset(&alerting, 0, sizeof(struct gsm_mncc));
2402 alerting.callref = trans->callref;
2403 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2404 /* facility */
2405 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2406 alerting.fields |= MNCC_F_FACILITY;
2407 decode_facility(&alerting.facility,
2408 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2409 }
2410
2411 /* progress */
2412 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2413 alerting.fields |= MNCC_F_PROGRESS;
2414 decode_progress(&alerting.progress,
2415 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2416 }
2417 /* ss-version */
2418 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2419 alerting.fields |= MNCC_F_SSVERSION;
2420 decode_ssversion(&alerting.ssversion,
2421 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2422 }
2423
2424 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2425
Harald Welteb3c3fae2009-07-23 19:06:52 +02002426 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2427 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002428}
2429
2430static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2431{
2432 struct gsm_mncc *alerting = arg;
2433 struct msgb *msg = gsm48_msgb_alloc();
2434 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2435
Harald Welte4bfdfe72009-06-10 23:11:52 +08002436 gh->msg_type = GSM48_MT_CC_ALERTING;
2437
2438 /* facility */
2439 if (alerting->fields & MNCC_F_FACILITY)
2440 encode_facility(msg, 0, &alerting->facility);
2441 /* progress */
2442 if (alerting->fields & MNCC_F_PROGRESS)
2443 encode_progress(msg, 0, &alerting->progress);
2444 /* user-user */
2445 if (alerting->fields & MNCC_F_USERUSER)
2446 encode_useruser(msg, 0, &alerting->useruser);
2447
2448 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2449
Harald Welte39e2ead2009-07-23 21:13:03 +02002450 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002451}
2452
2453static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2454{
2455 struct gsm_mncc *progress = arg;
2456 struct msgb *msg = gsm48_msgb_alloc();
2457 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2458
Harald Welte4bfdfe72009-06-10 23:11:52 +08002459 gh->msg_type = GSM48_MT_CC_PROGRESS;
2460
2461 /* progress */
2462 encode_progress(msg, 1, &progress->progress);
2463 /* user-user */
2464 if (progress->fields & MNCC_F_USERUSER)
2465 encode_useruser(msg, 0, &progress->useruser);
2466
Harald Welte39e2ead2009-07-23 21:13:03 +02002467 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002468}
2469
2470static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2471{
2472 struct gsm_mncc *connect = arg;
2473 struct msgb *msg = gsm48_msgb_alloc();
2474 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2475
Harald Welte4bfdfe72009-06-10 23:11:52 +08002476 gh->msg_type = GSM48_MT_CC_CONNECT;
2477
2478 gsm48_stop_cc_timer(trans);
2479 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2480
2481 /* facility */
2482 if (connect->fields & MNCC_F_FACILITY)
2483 encode_facility(msg, 0, &connect->facility);
2484 /* progress */
2485 if (connect->fields & MNCC_F_PROGRESS)
2486 encode_progress(msg, 0, &connect->progress);
2487 /* connected number */
2488 if (connect->fields & MNCC_F_CONNECTED)
2489 encode_connected(msg, &connect->connected);
2490 /* user-user */
2491 if (connect->fields & MNCC_F_USERUSER)
2492 encode_useruser(msg, 0, &connect->useruser);
2493
2494 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2495
Harald Welte39e2ead2009-07-23 21:13:03 +02002496 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002497}
2498
2499static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2500{
2501 struct gsm48_hdr *gh = msgb_l3(msg);
2502 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2503 struct tlv_parsed tp;
2504 struct gsm_mncc connect;
2505
2506 gsm48_stop_cc_timer(trans);
2507
2508 memset(&connect, 0, sizeof(struct gsm_mncc));
2509 connect.callref = trans->callref;
2510 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2511 /* use subscriber as connected party number */
2512 if (trans->subscr) {
2513 connect.fields |= MNCC_F_CONNECTED;
2514 strncpy(connect.connected.number, trans->subscr->extension,
2515 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002516 strncpy(connect.imsi, trans->subscr->imsi,
2517 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002518 }
2519 /* facility */
2520 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2521 connect.fields |= MNCC_F_FACILITY;
2522 decode_facility(&connect.facility,
2523 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2524 }
2525 /* user-user */
2526 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2527 connect.fields |= MNCC_F_USERUSER;
2528 decode_useruser(&connect.useruser,
2529 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2530 }
2531 /* ss-version */
2532 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2533 connect.fields |= MNCC_F_SSVERSION;
2534 decode_ssversion(&connect.ssversion,
2535 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2536 }
2537
2538 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2539
Harald Welteb3c3fae2009-07-23 19:06:52 +02002540 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002541}
2542
2543
2544static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2545{
2546 struct gsm_mncc connect_ack;
2547
2548 gsm48_stop_cc_timer(trans);
2549
2550 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2551
2552 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2553 connect_ack.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002554 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002555 &connect_ack);
2556}
2557
2558static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2559{
2560 struct msgb *msg = gsm48_msgb_alloc();
2561 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2562
Harald Welte4bfdfe72009-06-10 23:11:52 +08002563 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2564
2565 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2566
Harald Welte39e2ead2009-07-23 21:13:03 +02002567 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002568}
2569
2570static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2571{
2572 struct gsm48_hdr *gh = msgb_l3(msg);
2573 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2574 struct tlv_parsed tp;
2575 struct gsm_mncc disc;
2576
2577 gsm48_stop_cc_timer(trans);
2578
2579 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2580
2581 memset(&disc, 0, sizeof(struct gsm_mncc));
2582 disc.callref = trans->callref;
2583 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2584 /* cause */
2585 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2586 disc.fields |= MNCC_F_CAUSE;
2587 decode_cause(&disc.cause,
2588 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2589 }
2590 /* facility */
2591 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2592 disc.fields |= MNCC_F_FACILITY;
2593 decode_facility(&disc.facility,
2594 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2595 }
2596 /* user-user */
2597 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2598 disc.fields |= MNCC_F_USERUSER;
2599 decode_useruser(&disc.useruser,
2600 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2601 }
2602 /* ss-version */
2603 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2604 disc.fields |= MNCC_F_SSVERSION;
2605 decode_ssversion(&disc.ssversion,
2606 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2607 }
2608
Harald Welteb3c3fae2009-07-23 19:06:52 +02002609 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002610
2611}
2612
Harald Weltec66b71c2009-06-11 14:23:20 +08002613static struct gsm_mncc_cause default_cause = {
2614 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2615 .coding = 0,
2616 .rec = 0,
2617 .rec_val = 0,
2618 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2619 .diag_len = 0,
2620 .diag = { 0 },
2621};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002622
2623static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2624{
2625 struct gsm_mncc *disc = arg;
2626 struct msgb *msg = gsm48_msgb_alloc();
2627 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2628
Harald Welte4bfdfe72009-06-10 23:11:52 +08002629 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2630
2631 gsm48_stop_cc_timer(trans);
2632 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2633
2634 /* cause */
2635 if (disc->fields & MNCC_F_CAUSE)
2636 encode_cause(msg, 1, &disc->cause);
2637 else
2638 encode_cause(msg, 1, &default_cause);
2639
2640 /* facility */
2641 if (disc->fields & MNCC_F_FACILITY)
2642 encode_facility(msg, 0, &disc->facility);
2643 /* progress */
2644 if (disc->fields & MNCC_F_PROGRESS)
2645 encode_progress(msg, 0, &disc->progress);
2646 /* user-user */
2647 if (disc->fields & MNCC_F_USERUSER)
2648 encode_useruser(msg, 0, &disc->useruser);
2649
2650 /* store disconnect cause for T306 expiry */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002651 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002652
2653 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2654
Harald Welte39e2ead2009-07-23 21:13:03 +02002655 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002656}
2657
2658static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2659{
2660 struct gsm48_hdr *gh = msgb_l3(msg);
2661 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2662 struct tlv_parsed tp;
2663 struct gsm_mncc rel;
2664 int rc;
2665
2666 gsm48_stop_cc_timer(trans);
2667
2668 memset(&rel, 0, sizeof(struct gsm_mncc));
2669 rel.callref = trans->callref;
2670 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2671 /* cause */
2672 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2673 rel.fields |= MNCC_F_CAUSE;
2674 decode_cause(&rel.cause,
2675 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2676 }
2677 /* facility */
2678 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2679 rel.fields |= MNCC_F_FACILITY;
2680 decode_facility(&rel.facility,
2681 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2682 }
2683 /* user-user */
2684 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2685 rel.fields |= MNCC_F_USERUSER;
2686 decode_useruser(&rel.useruser,
2687 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2688 }
2689 /* ss-version */
2690 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2691 rel.fields |= MNCC_F_SSVERSION;
2692 decode_ssversion(&rel.ssversion,
2693 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2694 }
2695
Harald Welteaa0b29c2009-07-23 18:56:43 +02002696 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002697 /* release collision 5.4.5 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002698 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002699 } else {
Harald Welteb3c3fae2009-07-23 19:06:52 +02002700 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002701 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welteb3c3fae2009-07-23 19:06:52 +02002702 GSM48_MT_CC_RELEASE_COMPL);
2703 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002704 }
2705
2706 new_cc_state(trans, GSM_CSTATE_NULL);
2707
2708 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002709 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002710
2711 return rc;
2712}
2713
2714static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2715{
2716 struct gsm_mncc *rel = arg;
2717 struct msgb *msg = gsm48_msgb_alloc();
2718 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2719
Harald Welte4bfdfe72009-06-10 23:11:52 +08002720 gh->msg_type = GSM48_MT_CC_RELEASE;
2721
2722 trans->callref = 0;
2723
2724 gsm48_stop_cc_timer(trans);
2725 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2726
2727 /* cause */
2728 if (rel->fields & MNCC_F_CAUSE)
2729 encode_cause(msg, 0, &rel->cause);
2730 /* facility */
2731 if (rel->fields & MNCC_F_FACILITY)
2732 encode_facility(msg, 0, &rel->facility);
2733 /* user-user */
2734 if (rel->fields & MNCC_F_USERUSER)
2735 encode_useruser(msg, 0, &rel->useruser);
2736
Harald Welteaa0b29c2009-07-23 18:56:43 +02002737 trans->cc.T308_second = 0;
2738 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002739
Harald Welteaa0b29c2009-07-23 18:56:43 +02002740 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002741 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2742
Harald Welte39e2ead2009-07-23 21:13:03 +02002743 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002744}
2745
2746static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2747{
2748 struct gsm48_hdr *gh = msgb_l3(msg);
2749 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2750 struct tlv_parsed tp;
2751 struct gsm_mncc rel;
2752 int rc = 0;
2753
2754 gsm48_stop_cc_timer(trans);
2755
2756 memset(&rel, 0, sizeof(struct gsm_mncc));
2757 rel.callref = trans->callref;
2758 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2759 /* cause */
2760 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2761 rel.fields |= MNCC_F_CAUSE;
2762 decode_cause(&rel.cause,
2763 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2764 }
2765 /* facility */
2766 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2767 rel.fields |= MNCC_F_FACILITY;
2768 decode_facility(&rel.facility,
2769 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2770 }
2771 /* user-user */
2772 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2773 rel.fields |= MNCC_F_USERUSER;
2774 decode_useruser(&rel.useruser,
2775 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2776 }
2777 /* ss-version */
2778 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2779 rel.fields |= MNCC_F_SSVERSION;
2780 decode_ssversion(&rel.ssversion,
2781 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2782 }
2783
2784 if (trans->callref) {
Harald Welteaa0b29c2009-07-23 18:56:43 +02002785 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002786 case GSM_CSTATE_CALL_PRESENT:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002787 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002788 MNCC_REJ_IND, &rel);
2789 break;
2790 case GSM_CSTATE_RELEASE_REQ:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002791 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002792 MNCC_REL_CNF, &rel);
2793 break;
2794 default:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002795 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002796 MNCC_REL_IND, &rel);
2797 }
2798 }
2799
2800 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002801 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002802
2803 return rc;
2804}
2805
2806static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2807{
2808 struct gsm_mncc *rel = arg;
2809 struct msgb *msg = gsm48_msgb_alloc();
2810 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2811
Harald Welte4bfdfe72009-06-10 23:11:52 +08002812 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2813
2814 trans->callref = 0;
2815
2816 gsm48_stop_cc_timer(trans);
2817
2818 /* cause */
2819 if (rel->fields & MNCC_F_CAUSE)
2820 encode_cause(msg, 0, &rel->cause);
2821 /* facility */
2822 if (rel->fields & MNCC_F_FACILITY)
2823 encode_facility(msg, 0, &rel->facility);
2824 /* user-user */
2825 if (rel->fields & MNCC_F_USERUSER)
2826 encode_useruser(msg, 0, &rel->useruser);
2827
Harald Welteaa0b29c2009-07-23 18:56:43 +02002828 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002829
Harald Welte39e2ead2009-07-23 21:13:03 +02002830 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002831}
2832
2833static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2834{
2835 struct gsm48_hdr *gh = msgb_l3(msg);
2836 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2837 struct tlv_parsed tp;
2838 struct gsm_mncc fac;
2839
2840 memset(&fac, 0, sizeof(struct gsm_mncc));
2841 fac.callref = trans->callref;
2842 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2843 /* facility */
2844 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2845 fac.fields |= MNCC_F_FACILITY;
2846 decode_facility(&fac.facility,
2847 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2848 }
2849 /* ss-version */
2850 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2851 fac.fields |= MNCC_F_SSVERSION;
2852 decode_ssversion(&fac.ssversion,
2853 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2854 }
2855
Harald Welteb3c3fae2009-07-23 19:06:52 +02002856 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002857}
2858
2859static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2860{
2861 struct gsm_mncc *fac = arg;
2862 struct msgb *msg = gsm48_msgb_alloc();
2863 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2864
Harald Welte4bfdfe72009-06-10 23:11:52 +08002865 gh->msg_type = GSM48_MT_CC_FACILITY;
2866
2867 /* facility */
2868 encode_facility(msg, 1, &fac->facility);
2869
Harald Welte39e2ead2009-07-23 21:13:03 +02002870 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002871}
2872
2873static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2874{
2875 struct gsm_mncc hold;
2876
2877 memset(&hold, 0, sizeof(struct gsm_mncc));
2878 hold.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002879 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002880}
2881
2882static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2883{
2884 struct msgb *msg = gsm48_msgb_alloc();
2885 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2886
Harald Welte4bfdfe72009-06-10 23:11:52 +08002887 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2888
Harald Welte39e2ead2009-07-23 21:13:03 +02002889 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002890}
2891
2892static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2893{
2894 struct gsm_mncc *hold_rej = arg;
2895 struct msgb *msg = gsm48_msgb_alloc();
2896 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2897
Harald Welte4bfdfe72009-06-10 23:11:52 +08002898 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2899
2900 /* cause */
2901 if (hold_rej->fields & MNCC_F_CAUSE)
2902 encode_cause(msg, 1, &hold_rej->cause);
2903 else
2904 encode_cause(msg, 1, &default_cause);
2905
Harald Welte39e2ead2009-07-23 21:13:03 +02002906 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002907}
2908
2909static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2910{
2911 struct gsm_mncc retrieve;
2912
2913 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2914 retrieve.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002915 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2916 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002917}
2918
2919static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2920{
2921 struct msgb *msg = gsm48_msgb_alloc();
2922 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2923
Harald Welte4bfdfe72009-06-10 23:11:52 +08002924 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2925
Harald Welte39e2ead2009-07-23 21:13:03 +02002926 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002927}
2928
2929static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2930{
2931 struct gsm_mncc *retrieve_rej = arg;
2932 struct msgb *msg = gsm48_msgb_alloc();
2933 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2934
Harald Welte4bfdfe72009-06-10 23:11:52 +08002935 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2936
2937 /* cause */
2938 if (retrieve_rej->fields & MNCC_F_CAUSE)
2939 encode_cause(msg, 1, &retrieve_rej->cause);
2940 else
2941 encode_cause(msg, 1, &default_cause);
2942
Harald Welte39e2ead2009-07-23 21:13:03 +02002943 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002944}
2945
2946static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2947{
2948 struct gsm48_hdr *gh = msgb_l3(msg);
2949 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2950 struct tlv_parsed tp;
2951 struct gsm_mncc dtmf;
2952
2953 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2954 dtmf.callref = trans->callref;
2955 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2956 /* keypad facility */
2957 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
2958 dtmf.fields |= MNCC_F_KEYPAD;
2959 decode_keypad(&dtmf.keypad,
2960 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
2961 }
2962
Harald Welteb3c3fae2009-07-23 19:06:52 +02002963 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002964}
2965
2966static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
2967{
2968 struct gsm_mncc *dtmf = arg;
2969 struct msgb *msg = gsm48_msgb_alloc();
2970 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2971
Harald Welte4bfdfe72009-06-10 23:11:52 +08002972 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
2973
2974 /* keypad */
2975 if (dtmf->fields & MNCC_F_KEYPAD)
2976 encode_keypad(msg, dtmf->keypad);
2977
Harald Welte39e2ead2009-07-23 21:13:03 +02002978 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002979}
2980
2981static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
2982{
2983 struct gsm_mncc *dtmf = arg;
2984 struct msgb *msg = gsm48_msgb_alloc();
2985 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2986
Harald Welte4bfdfe72009-06-10 23:11:52 +08002987 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
2988
2989 /* cause */
2990 if (dtmf->fields & MNCC_F_CAUSE)
2991 encode_cause(msg, 1, &dtmf->cause);
2992 else
2993 encode_cause(msg, 1, &default_cause);
2994
Harald Welte39e2ead2009-07-23 21:13:03 +02002995 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002996}
2997
2998static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
2999{
3000 struct msgb *msg = gsm48_msgb_alloc();
3001 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3002
Harald Welte4bfdfe72009-06-10 23:11:52 +08003003 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3004
Harald Welte39e2ead2009-07-23 21:13:03 +02003005 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003006}
3007
3008static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3009{
3010 struct gsm_mncc dtmf;
3011
3012 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3013 dtmf.callref = trans->callref;
3014
Harald Welteb3c3fae2009-07-23 19:06:52 +02003015 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003016}
3017
3018static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3019{
3020 struct gsm48_hdr *gh = msgb_l3(msg);
3021 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3022 struct tlv_parsed tp;
3023 struct gsm_mncc modify;
3024
3025 memset(&modify, 0, sizeof(struct gsm_mncc));
3026 modify.callref = trans->callref;
3027 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3028 /* bearer capability */
3029 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3030 modify.fields |= MNCC_F_BEARER_CAP;
3031 decode_bearer_cap(&modify.bearer_cap,
3032 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3033 }
3034
3035 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3036
Harald Welteb3c3fae2009-07-23 19:06:52 +02003037 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003038}
3039
3040static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3041{
3042 struct gsm_mncc *modify = arg;
3043 struct msgb *msg = gsm48_msgb_alloc();
3044 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3045
Harald Welte4bfdfe72009-06-10 23:11:52 +08003046 gh->msg_type = GSM48_MT_CC_MODIFY;
3047
3048 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3049
3050 /* bearer capability */
3051 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3052
3053 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3054
Harald Welte39e2ead2009-07-23 21:13:03 +02003055 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003056}
3057
3058static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3059{
3060 struct gsm48_hdr *gh = msgb_l3(msg);
3061 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3062 struct tlv_parsed tp;
3063 struct gsm_mncc modify;
3064
3065 gsm48_stop_cc_timer(trans);
3066
3067 memset(&modify, 0, sizeof(struct gsm_mncc));
3068 modify.callref = trans->callref;
3069 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3070 /* bearer capability */
3071 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3072 modify.fields |= MNCC_F_BEARER_CAP;
3073 decode_bearer_cap(&modify.bearer_cap,
3074 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3075 }
3076
3077 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3078
Harald Welteb3c3fae2009-07-23 19:06:52 +02003079 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003080}
3081
3082static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3083{
3084 struct gsm_mncc *modify = arg;
3085 struct msgb *msg = gsm48_msgb_alloc();
3086 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3087
Harald Welte4bfdfe72009-06-10 23:11:52 +08003088 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3089
3090 /* bearer capability */
3091 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3092
3093 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3094
Harald Welte39e2ead2009-07-23 21:13:03 +02003095 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003096}
3097
3098static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3099{
3100 struct gsm48_hdr *gh = msgb_l3(msg);
3101 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3102 struct tlv_parsed tp;
3103 struct gsm_mncc modify;
3104
3105 gsm48_stop_cc_timer(trans);
3106
3107 memset(&modify, 0, sizeof(struct gsm_mncc));
3108 modify.callref = trans->callref;
3109 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3110 /* bearer capability */
3111 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3112 modify.fields |= GSM48_IE_BEARER_CAP;
3113 decode_bearer_cap(&modify.bearer_cap,
3114 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3115 }
3116 /* cause */
3117 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3118 modify.fields |= MNCC_F_CAUSE;
3119 decode_cause(&modify.cause,
3120 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3121 }
3122
3123 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3124
Harald Welteb3c3fae2009-07-23 19:06:52 +02003125 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003126}
3127
3128static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3129{
3130 struct gsm_mncc *modify = arg;
3131 struct msgb *msg = gsm48_msgb_alloc();
3132 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3133
Harald Welte4bfdfe72009-06-10 23:11:52 +08003134 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3135
3136 /* bearer capability */
3137 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3138 /* cause */
3139 encode_cause(msg, 1, &modify->cause);
3140
3141 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3142
Harald Welte39e2ead2009-07-23 21:13:03 +02003143 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003144}
3145
3146static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3147{
3148 struct gsm_mncc *notify = arg;
3149 struct msgb *msg = gsm48_msgb_alloc();
3150 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3151
Harald Welte4bfdfe72009-06-10 23:11:52 +08003152 gh->msg_type = GSM48_MT_CC_NOTIFY;
3153
3154 /* notify */
3155 encode_notify(msg, notify->notify);
3156
Harald Welte39e2ead2009-07-23 21:13:03 +02003157 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003158}
3159
3160static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3161{
3162 struct gsm48_hdr *gh = msgb_l3(msg);
3163 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3164// struct tlv_parsed tp;
3165 struct gsm_mncc notify;
3166
3167 memset(&notify, 0, sizeof(struct gsm_mncc));
3168 notify.callref = trans->callref;
3169// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3170 if (payload_len >= 1)
3171 decode_notify(&notify.notify, gh->data);
3172
Harald Welteb3c3fae2009-07-23 19:06:52 +02003173 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003174}
3175
3176static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3177{
3178 struct gsm_mncc *user = arg;
3179 struct msgb *msg = gsm48_msgb_alloc();
3180 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3181
Harald Welte4bfdfe72009-06-10 23:11:52 +08003182 gh->msg_type = GSM48_MT_CC_USER_INFO;
3183
3184 /* user-user */
3185 if (user->fields & MNCC_F_USERUSER)
3186 encode_useruser(msg, 1, &user->useruser);
3187 /* more data */
3188 if (user->more)
3189 encode_more(msg);
3190
Harald Welte39e2ead2009-07-23 21:13:03 +02003191 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003192}
3193
3194static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3195{
3196 struct gsm48_hdr *gh = msgb_l3(msg);
3197 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3198 struct tlv_parsed tp;
3199 struct gsm_mncc user;
3200
3201 memset(&user, 0, sizeof(struct gsm_mncc));
3202 user.callref = trans->callref;
3203 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3204 /* user-user */
3205 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3206 user.fields |= MNCC_F_USERUSER;
3207 decode_useruser(&user.useruser,
3208 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3209 }
3210 /* more data */
3211 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3212 user.more = 1;
3213
Harald Welteb3c3fae2009-07-23 19:06:52 +02003214 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003215}
3216
3217static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3218{
3219 struct gsm_mncc *mode = arg;
3220
3221 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3222}
3223
3224static struct downstate {
3225 u_int32_t states;
3226 int type;
3227 int (*rout) (struct gsm_trans *trans, void *arg);
3228} downstatelist[] = {
3229 /* mobile originating call establishment */
3230 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3231 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3232 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3233 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3234 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) | SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.2 | 5.2.1.6 | 5.2.1.6 */
3235 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3236 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3237 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3238 /* mobile terminating call establishment */
3239 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3240 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3241 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3242 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3243 /* signalling during call */
3244 {SBIT(GSM_CSTATE_ACTIVE),
3245 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3246 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3247 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3248 {ALL_STATES,
3249 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3250 {ALL_STATES,
3251 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3252 {ALL_STATES,
3253 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3254 {SBIT(GSM_CSTATE_ACTIVE),
3255 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3256 {SBIT(GSM_CSTATE_ACTIVE),
3257 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3258 {SBIT(GSM_CSTATE_ACTIVE),
3259 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3260 {SBIT(GSM_CSTATE_ACTIVE),
3261 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3262 {SBIT(GSM_CSTATE_ACTIVE),
3263 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3264 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3265 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3266 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3267 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3268 {SBIT(GSM_CSTATE_ACTIVE),
3269 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3270 /* clearing */
3271 {SBIT(GSM_CSTATE_INITIATED),
3272 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3273 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3274 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3275 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3276 MNCC_REL_REQ, gsm48_cc_tx_release},
3277 /* special */
3278 {ALL_STATES,
3279 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3280};
3281
3282#define DOWNSLLEN \
3283 (sizeof(downstatelist) / sizeof(struct downstate))
3284
3285
3286int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3287{
3288 int i, j, k, l, rc = 0;
3289 struct gsm_trans *trans = NULL, *transt;
3290 struct gsm_subscriber *subscr;
3291 struct gsm_lchan *lchan = NULL, *lchant;
3292 struct gsm_bts *bts = NULL;
3293 struct gsm_bts_trx *trx;
3294 struct gsm_bts_trx_ts *ts;
3295 struct gsm_mncc *data = arg, rel;
3296
3297 /* handle special messages */
3298 switch(msg_type) {
3299 case MNCC_BRIDGE:
3300 return tch_bridge(net, arg);
3301 case MNCC_FRAME_DROP:
3302 return tch_recv(net, arg, 0);
3303 case MNCC_FRAME_RECV:
3304 return tch_recv(net, arg, 1);
3305 case GSM_TRAU_FRAME:
3306 return tch_frame(net, arg);
3307 }
3308
3309 memset(&rel, 0, sizeof(struct gsm_mncc));
3310 rel.callref = data->callref;
3311
3312 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003313 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003314
3315 /* Callref unknown */
3316 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003317 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003318 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3319 "Received '%s' from MNCC with "
3320 "unknown callref %d\n", data->called.number,
3321 get_mncc_name(msg_type), data->callref);
3322 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003323 return mncc_release_ind(net, NULL, data->callref,
3324 GSM48_CAUSE_LOC_PRN_S_LU,
3325 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003326 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003327 if (!data->called.number[0] && !data->imsi[0]) {
3328 DEBUGP(DCC, "(bts - trx - ts - ti) "
3329 "Received '%s' from MNCC with "
3330 "no number or IMSI\n", get_mncc_name(msg_type));
3331 /* Invalid number */
3332 return mncc_release_ind(net, NULL, data->callref,
3333 GSM48_CAUSE_LOC_PRN_S_LU,
3334 GSM48_CC_CAUSE_INV_NR_FORMAT);
3335 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003336 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003337 if (data->called.number[0])
Harald Welte761e9442009-07-23 19:21:02 +02003338 subscr = subscr_get_by_extension(net,
3339 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003340 else
Harald Welte761e9442009-07-23 19:21:02 +02003341 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003342 /* If subscriber is not found */
3343 if (!subscr) {
3344 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3345 "Received '%s' from MNCC with "
3346 "unknown subscriber %s\n", data->called.number,
3347 get_mncc_name(msg_type), data->called.number);
3348 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003349 return mncc_release_ind(net, NULL, data->callref,
3350 GSM48_CAUSE_LOC_PRN_S_LU,
3351 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003352 }
3353 /* If subscriber is not "attached" */
3354 if (!subscr->lac) {
3355 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3356 "Received '%s' from MNCC with "
3357 "detached subscriber %s\n", data->called.number,
3358 get_mncc_name(msg_type), data->called.number);
3359 subscr_put(subscr);
3360 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003361 return mncc_release_ind(net, NULL, data->callref,
3362 GSM48_CAUSE_LOC_PRN_S_LU,
3363 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003364 }
3365 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003366 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3367 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003368 DEBUGP(DCC, "No memory for trans.\n");
3369 subscr_put(subscr);
3370 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003371 mncc_release_ind(net, NULL, data->callref,
3372 GSM48_CAUSE_LOC_PRN_S_LU,
3373 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003374 return -ENOMEM;
3375 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003376 /* Find lchan */
3377 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003378 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003379 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003380 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003381 for (k = 0; k < TRX_NR_TS; k++) {
3382 ts = &trx->ts[k];
3383 for (l = 0; l < TS_MAX_LCHAN; l++) {
3384 lchant = &ts->lchan[l];
3385 if (lchant->subscr == subscr) {
3386 lchan = lchant;
3387 break;
3388 }
3389 }
3390 }
3391 }
3392 }
3393
3394 /* If subscriber has no lchan */
3395 if (!lchan) {
3396 /* find transaction with this subscriber already paging */
3397 llist_for_each_entry(transt, &net->trans_list, entry) {
3398 /* Transaction of our lchan? */
3399 if (transt == trans ||
3400 transt->subscr != subscr)
3401 continue;
3402 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3403 "Received '%s' from MNCC with "
3404 "unallocated channel, paging already "
3405 "started.\n", bts->nr,
3406 data->called.number,
3407 get_mncc_name(msg_type));
3408 return 0;
3409 }
3410 /* store setup informations until paging was successfull */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003411 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08003412 /* start paging subscriber on all BTS with her location */
3413 subscr->net = net;
3414 bts = NULL;
3415 do {
3416 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3417 if (!bts)
3418 break;
3419 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3420 "Received '%s' from MNCC with "
3421 "unallocated channel, paging.\n",
3422 bts->nr, data->called.number,
3423 get_mncc_name(msg_type));
3424 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003425 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003426 setup_trig_pag_evt, subscr);
3427 } while (1);
3428 return 0;
3429 }
3430 /* Assign lchan */
3431 trans->lchan = lchan;
3432 use_lchan(lchan);
3433 }
3434 lchan = trans->lchan;
3435
3436 /* if paging did not respond yet */
3437 if (!lchan) {
3438 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3439 "Received '%s' from MNCC in paging state\n",
3440 (trans->subscr)?(trans->subscr->extension):"-",
3441 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003442 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3443 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003444 if (msg_type == MNCC_REL_REQ)
3445 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3446 else
3447 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3448 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003449 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003450 return rc;
3451 }
3452
3453 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3454 "Received '%s' from MNCC in state %d (%s)\n",
3455 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3456 trans->transaction_id,
3457 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003458 get_mncc_name(msg_type), trans->cc.state,
3459 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003460
3461 /* Find function for current state and message */
3462 for (i = 0; i < DOWNSLLEN; i++)
3463 if ((msg_type == downstatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003464 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003465 break;
3466 if (i == DOWNSLLEN) {
3467 DEBUGP(DCC, "Message unhandled at this state.\n");
3468 return 0;
3469 }
3470
3471 rc = downstatelist[i].rout(trans, arg);
3472
3473 return rc;
3474}
3475
3476
3477static struct datastate {
3478 u_int32_t states;
3479 int type;
3480 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3481} datastatelist[] = {
3482 /* mobile originating call establishment */
3483 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3484 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3485 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3486 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3487 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3488 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3489 /* mobile terminating call establishment */
3490 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3491 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3492 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3493 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3494 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */
3495 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3496 /* signalling during call */
3497 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3498 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3499 {SBIT(GSM_CSTATE_ACTIVE),
3500 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3501 {ALL_STATES,
3502 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3503 {ALL_STATES,
3504 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3505 {ALL_STATES,
3506 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3507 {SBIT(GSM_CSTATE_ACTIVE),
3508 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3509 {SBIT(GSM_CSTATE_ACTIVE),
3510 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3511 {SBIT(GSM_CSTATE_ACTIVE),
3512 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3513 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3514 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3515 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3516 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3517 {SBIT(GSM_CSTATE_ACTIVE),
3518 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3519 /* clearing */
3520 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3521 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3522 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3523 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3524 {ALL_STATES, /* 5.4.3.4 */
3525 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3526};
3527
3528#define DATASLLEN \
3529 (sizeof(datastatelist) / sizeof(struct datastate))
3530
Harald Welte4bc90a12008-12-27 16:32:52 +00003531static int gsm0408_rcv_cc(struct msgb *msg)
3532{
3533 struct gsm48_hdr *gh = msgb_l3(msg);
3534 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003535 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003536 struct gsm_lchan *lchan = msg->lchan;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003537 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003538 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003539
Harald Welte4bfdfe72009-06-10 23:11:52 +08003540 if (msg_type & 0x80) {
3541 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3542 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003543 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003544
3545 /* Find transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003546 trans = trans_find_by_id(lchan, transaction_id);
3547
Harald Welte6f5aee02009-07-23 21:21:14 +02003548 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003549 "Received '%s' from MS in state %d (%s)\n",
3550 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3551 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003552 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3553 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003554
3555 /* Create transaction */
3556 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003557 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003558 "creating new trans.\n", transaction_id);
3559 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003560 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3561 transaction_id, new_callref++);
3562 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003563 DEBUGP(DCC, "No memory for trans.\n");
3564 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003565 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003566 GSM48_MT_CC_RELEASE_COMPL);
3567 return -ENOMEM;
3568 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003569 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003570 trans->lchan = lchan;
3571 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003572 }
3573
3574 /* find function for current state and message */
3575 for (i = 0; i < DATASLLEN; i++)
3576 if ((msg_type == datastatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003577 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003578 break;
3579 if (i == DATASLLEN) {
3580 DEBUGP(DCC, "Message unhandled at this state.\n");
3581 return 0;
3582 }
3583
3584 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003585
3586 return rc;
3587}
3588
Harald Welte52b1f982008-12-23 20:25:15 +00003589/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3590int gsm0408_rcvmsg(struct msgb *msg)
3591{
3592 struct gsm48_hdr *gh = msgb_l3(msg);
3593 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003594 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003595
3596 switch (pdisc) {
3597 case GSM48_PDISC_CC:
3598 rc = gsm0408_rcv_cc(msg);
3599 break;
3600 case GSM48_PDISC_MM:
3601 rc = gsm0408_rcv_mm(msg);
3602 break;
3603 case GSM48_PDISC_RR:
3604 rc = gsm0408_rcv_rr(msg);
3605 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003606 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003607 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003608 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003609 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003610 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003611 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3612 pdisc);
3613 break;
3614 default:
3615 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3616 pdisc);
3617 break;
3618 }
3619
3620 return rc;
3621}
Harald Welte8470bf22008-12-25 23:28:35 +00003622
Harald Welte8470bf22008-12-25 23:28:35 +00003623/* Section 9.1.8 / Table 9.9 */
3624struct chreq {
3625 u_int8_t val;
3626 u_int8_t mask;
3627 enum chreq_type type;
3628};
3629
3630/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3631static const struct chreq chreq_type_neci1[] = {
3632 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3633 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3634 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3635 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3636 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3637 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3638 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3639 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3640 { 0x10, 0xf0, CHREQ_T_SDCCH },
3641 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3642 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3643 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3644};
3645
3646/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3647static const struct chreq chreq_type_neci0[] = {
3648 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3649 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3650 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3651 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3652 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3653 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3654 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3655 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3656};
3657
3658static const enum gsm_chan_t ctype_by_chreq[] = {
3659 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3660 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3661 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3662 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3663 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3664 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3665 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3666 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3667 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3668 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3669 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3670 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3671};
3672
Harald Weltee14a57c2008-12-29 04:08:28 +00003673static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3674 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3675 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3676 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3677 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3678 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3679 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3680 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3681 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3682 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3683 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3684 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3685 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3686};
3687
Harald Welte8470bf22008-12-25 23:28:35 +00003688enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3689{
3690 int i;
3691 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3692
3693 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3694 const struct chreq *chr = &chreq_type_neci0[i];
3695 if ((ra & chr->mask) == chr->val)
3696 return ctype_by_chreq[chr->type];
3697 }
3698 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3699 return GSM_LCHAN_SDCCH;
3700}
Harald Weltee14a57c2008-12-29 04:08:28 +00003701
3702enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3703{
3704 int i;
3705 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3706
3707 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3708 const struct chreq *chr = &chreq_type_neci0[i];
3709 if ((ra & chr->mask) == chr->val)
3710 return reason_by_chreq[chr->type];
3711 }
3712 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3713 return GSM_CHREQ_REASON_OTHER;
3714}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003715
3716/* dequeue messages to layer 4 */
3717int bsc_upqueue(struct gsm_network *net)
3718{
3719 struct gsm_mncc *mncc;
3720 struct msgb *msg;
3721 int work = 0;
3722
3723 if (net)
3724 while ((msg = msgb_dequeue(&net->upqueue))) {
3725 mncc = (struct gsm_mncc *)msg->data;
3726 if (net->mncc_recv)
3727 net->mncc_recv(net, mncc->msg_type, mncc);
3728 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003729 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003730 }
3731
3732 return work;
3733}
Harald Welteaa0b29c2009-07-23 18:56:43 +02003734