blob: 28d573a1db5666ebc9fd7e0737703a8ae4939d70 [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 Welte2cf161b2009-06-20 22:36:41 +0200353 if (!tall_locop_ctx)
354 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
355 "loc_updating_oper");
Harald Welte470ec292009-06-26 20:25:23 +0200356 lchan->loc_operation = talloc_zero(tall_locop_ctx,
357 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000358}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000359
Holger Freytherd51524f2009-06-09 08:27:07 +0000360static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
361{
362 u_int32_t tmsi;
363
364 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
365 db_subscriber_alloc_tmsi(lchan->subscr);
366 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
367 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
368 release_loc_updating_req(lchan);
369 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
370 }
371
372 return 0;
373}
374
Holger Freyther7c19f742009-06-06 13:54:35 +0000375static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
376 void *handler_data, void *signal_data)
377{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800378 struct gsm_trans *trans, *temp;
379
Holger Freyther7c19f742009-06-06 13:54:35 +0000380 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
381 return 0;
382
383 /*
384 * Cancel any outstanding location updating request
385 * operation taking place on the lchan.
386 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200387 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200388 if (!lchan)
389 return 0;
390
Holger Freyther7c19f742009-06-06 13:54:35 +0000391 release_loc_updating_req(lchan);
392
Harald Welte4bfdfe72009-06-10 23:11:52 +0800393 /* Free all transactions that are associated with the released lchan */
Harald Welteaa0b29c2009-07-23 18:56:43 +0200394 /* FIXME: this is not neccessarily the right thing to do, we should
395 * only set trans->lchan to NULL and wait for another lchan to be
396 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800397 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
398 if (trans->lchan == lchan)
Harald Welteaa0b29c2009-07-23 18:56:43 +0200399 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800400 }
401
Holger Freyther7c19f742009-06-06 13:54:35 +0000402 return 0;
403}
404
405/*
406 * This will be ran by the linker when loading the DSO. We use it to
407 * do system initialization, e.g. registration of signal handlers.
408 */
409static __attribute__((constructor)) void on_dso_load_0408(void)
410{
411 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
412}
413
Harald Welte52b1f982008-12-23 20:25:15 +0000414static void to_bcd(u_int8_t *bcd, u_int16_t val)
415{
Harald Welte4b634542008-12-27 01:55:51 +0000416 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000417 val = val / 10;
418 bcd[1] = val % 10;
419 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000420 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000421 val = val / 10;
422}
423
Holger Freyther17746612008-12-28 16:32:44 +0000424void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000425 u_int16_t mnc, u_int16_t lac)
426{
427 u_int8_t bcd[3];
428
429 to_bcd(bcd, mcc);
430 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
431 lai48->digits[1] = bcd[2];
432
433 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000434 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
435#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000436 lai48->digits[1] |= bcd[2] << 4;
437 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000438#else
439 lai48->digits[1] |= 0xf << 4;
440 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
441#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000442
Harald Welte4b634542008-12-27 01:55:51 +0000443 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000444}
445
Harald Welte255539c2008-12-28 02:26:27 +0000446#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000447#define MID_TMSI_LEN (TMSI_LEN + 2)
448
Harald Welte255539c2008-12-28 02:26:27 +0000449int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000450{
Harald Welte65e74cc2008-12-29 01:55:35 +0000451 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000452
Harald Welte4b634542008-12-27 01:55:51 +0000453 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000454 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000455 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000456 *tptr = htonl(tmsi);
457
458 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000459}
460
Harald Welte09e38af2009-02-16 22:52:23 +0000461static const char bcd_num_digits[] = {
462 '0', '1', '2', '3', '4', '5', '6', '7',
463 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
464};
465
Harald Welte0c389302009-06-10 12:08:54 +0800466/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
467int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
468 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000469{
470 u_int8_t in_len = bcd_lv[0];
471 int i;
472
Harald Welte0c389302009-06-10 12:08:54 +0800473 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000474 /* lower nibble */
475 output_len--;
476 if (output_len <= 1)
477 break;
478 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
479
480 /* higher nibble */
481 output_len--;
482 if (output_len <= 1)
483 break;
484 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
485 }
486 if (output_len >= 1)
487 *output++ = '\0';
488
Harald Welte0c389302009-06-10 12:08:54 +0800489 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000490}
491
492/* convert a single ASCII character to call-control BCD */
493static int asc_to_bcd(const char asc)
494{
495 int i;
496
497 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
498 if (bcd_num_digits[i] == asc)
499 return i;
500 }
501 return -EINVAL;
502}
503
Harald Welte0c389302009-06-10 12:08:54 +0800504/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000505int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800506 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000507{
508 int in_len = strlen(input);
509 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800510 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000511
512 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800513 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000514 if (in_len % 2)
515 bcd_lv[0]++;
516
Harald Welte0c389302009-06-10 12:08:54 +0800517 if (bcd_lv[0] > max_len)
518 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000519
520 for (i = 0; i < in_len; i++) {
521 int rc = asc_to_bcd(input[i]);
522 if (rc < 0)
523 return rc;
524 if (i % 2 == 0)
525 *bcd_cur = rc;
526 else
527 *bcd_cur++ |= (rc << 4);
528 }
529 /* append padding nibble in case of odd length */
530 if (i % 2)
531 *bcd_cur++ |= 0xf0;
532
533 /* return how many bytes we used */
534 return (bcd_cur - bcd_lv);
535}
536
Harald Welte0c389302009-06-10 12:08:54 +0800537/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800538static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800539 const u_int8_t *lv)
540{
541 u_int8_t in_len = lv[0];
542 int i, s;
543
544 if (in_len < 1)
545 return -EINVAL;
546
Harald Welte4bfdfe72009-06-10 23:11:52 +0800547 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800548
549 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800550 bcap->transfer = lv[1] & 0x07;
551 bcap->mode = (lv[1] & 0x08) >> 3;
552 bcap->coding = (lv[1] & 0x10) >> 4;
553 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800554
555 i = 1;
556 s = 0;
557 while(!(lv[i] & 0x80)) {
558 i++; /* octet 3a etc */
559 if (in_len < i)
560 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800561 bcap->speech_ver[s++] = lv[i] & 0x0f;
562 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800563 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800564 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800565 if (s == 7) /* maximum speech versions + end of list */
566 return 0;
567 }
568
569 return 0;
570}
571
572/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800573static int encode_bearer_cap(struct msgb *msg, int lv_only,
574 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800575{
576 u_int8_t lv[32 + 1];
577 int i, s;
578
Harald Welte4bfdfe72009-06-10 23:11:52 +0800579 lv[1] = bcap->transfer;
580 lv[1] |= bcap->mode << 3;
581 lv[1] |= bcap->coding << 4;
582 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800583
584 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800586 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800588 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800589 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800590 }
591 lv[i] |= 0x80; /* last IE of octet 3 etc */
592
593 lv[0] = i;
594 if (lv_only)
595 msgb_lv_put(msg, lv[0], lv+1);
596 else
597 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
598
599 return 0;
600}
601
602/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800603static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800604{
605 u_int8_t in_len = lv[0];
606
607 if (in_len < 1)
608 return -EINVAL;
609
610 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800611 ccap->dtmf = lv[1] & 0x01;
612 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800613
614 return 0;
615}
616
617/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800618static int decode_called(struct gsm_mncc_number *called,
619 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800620{
621 u_int8_t in_len = lv[0];
622
623 if (in_len < 1)
624 return -EINVAL;
625
626 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800627 called->plan = lv[1] & 0x0f;
628 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800629
630 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800631 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800632
633 return 0;
634}
635
636/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800637static int encode_called(struct msgb *msg,
638 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800639{
640 u_int8_t lv[18];
641 int ret;
642
643 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800644 lv[1] = called->plan;
645 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800646
647 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800648 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800649 if (ret < 0)
650 return ret;
651
652 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
653
654 return 0;
655}
656
657/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800658static int encode_callerid(struct msgb *msg, int ie,
659 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800660{
661 u_int8_t lv[13];
662 int h_len = 1;
663 int ret;
664
665 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800666 lv[1] = callerid->plan;
667 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800668
Harald Welte4bfdfe72009-06-10 23:11:52 +0800669 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800670 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800671 lv[2] = callerid->screen;
672 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800673 lv[2] |= 0x80;
674 h_len++;
675 } else
676 lv[1] |= 0x80;
677
678 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800679 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800680 if (ret < 0)
681 return ret;
682
683 msgb_tlv_put(msg, ie, lv[0], lv+1);
684
685 return 0;
686}
687
688/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800689static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800690 const u_int8_t *lv)
691{
692 u_int8_t in_len = lv[0];
693 int i;
694
695 if (in_len < 2)
696 return -EINVAL;
697
Harald Welte4bfdfe72009-06-10 23:11:52 +0800698 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800699
700 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800701 cause->location = lv[1] & 0x0f;
702 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800703
704 i = 1;
705 if (!(lv[i] & 0x80)) {
706 i++; /* octet 3a */
707 if (in_len < i+1)
708 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800709 cause->rec = 1;
710 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800711
712 }
713 i++;
714
715 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800716 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800717 i++;
718
719 if (in_len < i) /* no diag */
720 return 0;
721
722 if (in_len - (i-1) > 32) /* maximum 32 octets */
723 return 0;
724
725 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800726 memcpy(cause->diag, lv + i, in_len - (i-1));
727 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800728
729 return 0;
730}
731
732/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800733static int encode_cause(struct msgb *msg, int lv_only,
734 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800735{
736 u_int8_t lv[32+4];
737 int i;
738
Harald Welte4bfdfe72009-06-10 23:11:52 +0800739 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800740 return -EINVAL;
741
742 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800743 lv[1] = cause->location;
744 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800745
746 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800748 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800749 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800750 }
751 lv[i] |= 0x80; /* end of octet 3 */
752
753 /* octet 4 */
754 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800755 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800756
757 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800758 if (cause->diag_len) {
759 memcpy(lv + i, cause->diag, cause->diag_len);
760 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800761 }
762
763 lv[0] = i;
764 if (lv_only)
765 msgb_lv_put(msg, lv[0], lv+1);
766 else
767 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
768
769 return 0;
770}
771
772/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800773static int encode_calling(struct msgb *msg,
774 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800775{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800776 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800777}
778
779/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800780static int encode_connected(struct msgb *msg,
781 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800782{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800783 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800784}
785
786/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800787static int encode_redirecting(struct msgb *msg,
788 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800789{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800790 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800791}
792
793/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800794static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800795 const u_int8_t *lv)
796{
797 u_int8_t in_len = lv[0];
798
799 if (in_len < 1)
800 return -EINVAL;
801
Harald Welte4bfdfe72009-06-10 23:11:52 +0800802 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800803 return -EINVAL;
804
Harald Welte4bfdfe72009-06-10 23:11:52 +0800805 memcpy(facility->info, lv+1, in_len);
806 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800807
808 return 0;
809}
810
811/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800812static int encode_facility(struct msgb *msg, int lv_only,
813 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800814{
815 u_int8_t lv[GSM_MAX_FACILITY + 1];
816
Harald Welte4bfdfe72009-06-10 23:11:52 +0800817 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800818 return -EINVAL;
819
Harald Welte4bfdfe72009-06-10 23:11:52 +0800820 memcpy(lv+1, facility->info, facility->len);
821 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800822 if (lv_only)
823 msgb_lv_put(msg, lv[0], lv+1);
824 else
825 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
826
827 return 0;
828}
829
830/* decode 'notify' */
831static int decode_notify(int *notify, const u_int8_t *v)
832{
833 *notify = v[0] & 0x7f;
834
835 return 0;
836}
837
838/* encode 'notify' */
839static int encode_notify(struct msgb *msg, int notify)
840{
841 msgb_v_put(msg, notify | 0x80);
842
843 return 0;
844}
845
846/* encode 'signal' */
847static int encode_signal(struct msgb *msg, int signal)
848{
849 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
850
851 return 0;
852}
853
854/* decode 'keypad' */
855static int decode_keypad(int *keypad, const u_int8_t *lv)
856{
857 u_int8_t in_len = lv[0];
858
859 if (in_len < 1)
860 return -EINVAL;
861
862 *keypad = lv[1] & 0x7f;
863
864 return 0;
865}
866
867/* encode 'keypad' */
868static int encode_keypad(struct msgb *msg, int keypad)
869{
870 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
871
872 return 0;
873}
874
875/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800876static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800877 const u_int8_t *lv)
878{
879 u_int8_t in_len = lv[0];
880
881 if (in_len < 2)
882 return -EINVAL;
883
Harald Welte4bfdfe72009-06-10 23:11:52 +0800884 progress->coding = (lv[1] & 0x60) >> 5;
885 progress->location = lv[1] & 0x0f;
886 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800887
888 return 0;
889}
890
891/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800892static int encode_progress(struct msgb *msg, int lv_only,
893 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800894{
895 u_int8_t lv[3];
896
897 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800898 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
899 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800900 if (lv_only)
901 msgb_lv_put(msg, lv[0], lv+1);
902 else
903 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
904
905 return 0;
906}
907
908/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800909static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800910 const u_int8_t *lv)
911{
912 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800913 char *info = uu->info;
914 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800915 int i;
916
917 if (in_len < 1)
918 return -EINVAL;
919
Harald Welte4bfdfe72009-06-10 23:11:52 +0800920 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800921
922 for (i = 2; i <= in_len; i++) {
923 info_len--;
924 if (info_len <= 1)
925 break;
926 *info++ = lv[i];
927 }
928 if (info_len >= 1)
929 *info++ = '\0';
930
931 return 0;
932}
933
934/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800935static int encode_useruser(struct msgb *msg, int lv_only,
936 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800937{
938 u_int8_t lv[GSM_MAX_USERUSER + 2];
939
Harald Welte4bfdfe72009-06-10 23:11:52 +0800940 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800941 return -EINVAL;
942
Harald Welte4bfdfe72009-06-10 23:11:52 +0800943 lv[0] = 1 + strlen(uu->info);
944 lv[1] = uu->proto;
945 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800946 if (lv_only)
947 msgb_lv_put(msg, lv[0], lv+1);
948 else
949 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
950
951 return 0;
952}
953
954/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800955static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800956 const u_int8_t *lv)
957{
958 u_int8_t in_len = lv[0];
959
Harald Welte4bfdfe72009-06-10 23:11:52 +0800960 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800961 return -EINVAL;
962
Harald Welte4bfdfe72009-06-10 23:11:52 +0800963 memcpy(ssv->info, lv + 1, in_len);
964 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800965
966 return 0;
967}
968
969/* encode 'more data' */
970static int encode_more(struct msgb *msg)
971{
972 u_int8_t *ie;
973
974 ie = msgb_put(msg, 1);
975 ie[0] = GSM48_IE_MORE_DATA;
976
977 return 0;
978}
979
Holger Freyther819dd202009-01-04 03:52:50 +0000980struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000981{
Harald Welte966636f2009-06-26 19:39:35 +0200982 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
983 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000984}
985
Harald Welte39e2ead2009-07-23 21:13:03 +0200986int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000987{
Harald Welte39e2ead2009-07-23 21:13:03 +0200988 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
989
990 /* if we get passed a transaction reference, do some common
991 * work that the caller no longer has to do */
992 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200993 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200994 msg->lchan = trans->lchan;
995 }
996
Harald Welte65e74cc2008-12-29 01:55:35 +0000997 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000998 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000999
Harald Welte4bfdfe72009-06-10 23:11:52 +08001000 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1001 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1002 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1003 msg->trx->nr, msg->lchan->ts->nr,
1004 gh->proto_discr & 0xf0,
1005 cc_msg_names[gh->msg_type & 0x3f]);
1006 else
1007 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1008 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1009 msg->trx->nr, msg->lchan->ts->nr,
1010 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001011 }
1012
Harald Welte4b634542008-12-27 01:55:51 +00001013 msg->l3h = msg->data;
1014
Harald Welte8470bf22008-12-25 23:28:35 +00001015 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001016}
1017
Holger Freyther429e7762008-12-30 13:28:30 +00001018/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001019int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001020{
Harald Welte8470bf22008-12-25 23:28:35 +00001021 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001022 struct gsm48_hdr *gh;
1023
Harald Welte8470bf22008-12-25 23:28:35 +00001024 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001025
1026 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1027 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001028 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001029 gh->data[0] = cause;
1030
Harald Weltedb253af2008-12-30 17:56:55 +00001031 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1032
Harald Welte39e2ead2009-07-23 21:13:03 +02001033 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001034}
1035
1036/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001037int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001038{
Harald Welte8470bf22008-12-25 23:28:35 +00001039 struct gsm_bts *bts = lchan->ts->trx->bts;
1040 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001041 struct gsm48_hdr *gh;
1042 struct gsm48_loc_area_id *lai;
1043 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001044 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001045
Harald Welte8470bf22008-12-25 23:28:35 +00001046 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001047
1048 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1049 gh->proto_discr = GSM48_PDISC_MM;
1050 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1051
1052 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001053 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001054 bts->network->network_code, bts->location_area_code);
1055
1056 mid = msgb_put(msg, MID_TMSI_LEN);
1057 generate_mid_from_tmsi(mid, tmsi);
1058
1059 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1060
Harald Welte39e2ead2009-07-23 21:13:03 +02001061 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001062
Harald Weltedb253af2008-12-30 17:56:55 +00001063 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001064
Holger Freyther07cc8d82008-12-29 06:23:46 +00001065 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001066}
1067
Harald Weltefc977a82008-12-27 10:19:37 +00001068static char bcd2char(u_int8_t bcd)
1069{
1070 if (bcd < 0xa)
1071 return '0' + bcd;
1072 else
1073 return 'A' + (bcd - 0xa);
1074}
1075
Harald Weltebf5e8df2009-02-03 12:59:45 +00001076/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001077static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1078{
1079 int i;
1080 u_int8_t mi_type;
1081 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001082 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001083
1084 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1085
1086 switch (mi_type) {
1087 case GSM_MI_TYPE_NONE:
1088 break;
1089 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001090 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1091 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1092 memcpy(&tmsi, &mi[1], 4);
1093 tmsi = ntohl(tmsi);
1094 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001095 }
1096 break;
1097 case GSM_MI_TYPE_IMSI:
1098 case GSM_MI_TYPE_IMEI:
1099 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001100 *str_cur++ = bcd2char(mi[0] >> 4);
1101
1102 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001103 if (str_cur + 2 >= string + str_len)
1104 return str_cur - string;
1105 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001106 /* skip last nibble in last input byte when GSM_EVEN */
1107 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1108 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001109 }
1110 break;
1111 default:
1112 break;
1113 }
Harald Weltefc977a82008-12-27 10:19:37 +00001114 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001115
Harald Weltefc977a82008-12-27 10:19:37 +00001116 return str_cur - string;
1117}
1118
Harald Weltebf5e8df2009-02-03 12:59:45 +00001119/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001120static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1121{
1122 struct msgb *msg = gsm48_msgb_alloc();
1123 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001124
Harald Welte231ad4f2008-12-27 11:15:38 +00001125 msg->lchan = lchan;
1126
1127 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1128 gh->proto_discr = GSM48_PDISC_MM;
1129 gh->msg_type = GSM48_MT_MM_ID_REQ;
1130 gh->data[0] = id_type;
1131
Harald Welte39e2ead2009-07-23 21:13:03 +02001132 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001133}
1134
1135#define MI_SIZE 32
1136
Harald Weltebf5e8df2009-02-03 12:59:45 +00001137/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001138static int mm_rx_id_resp(struct msgb *msg)
1139{
1140 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001141 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001142 struct gsm_bts *bts = lchan->ts->trx->bts;
1143 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001144 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1145 char mi_string[MI_SIZE];
1146
1147 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001148 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001149 mi_type, mi_string);
1150
Harald Welte75a983f2008-12-27 21:34:06 +00001151 switch (mi_type) {
1152 case GSM_MI_TYPE_IMSI:
1153 if (!lchan->subscr)
Harald Welte761e9442009-07-23 19:21:02 +02001154 lchan->subscr = db_create_subscriber(net, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001155 if (lchan->loc_operation)
1156 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001157 break;
1158 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001159 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001160 /* update subscribe <-> IMEI mapping */
1161 if (lchan->subscr)
1162 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001163 if (lchan->loc_operation)
1164 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001165 break;
1166 }
Holger Freyther73487a22008-12-31 18:53:57 +00001167
1168 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001169 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001170}
1171
Harald Welte255539c2008-12-28 02:26:27 +00001172
1173static void loc_upd_rej_cb(void *data)
1174{
1175 struct gsm_lchan *lchan = data;
1176
Holger Freyther73487a22008-12-31 18:53:57 +00001177 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001178 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001179 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001180}
1181
Holger Freytherb7193e42008-12-29 17:44:08 +00001182static void schedule_reject(struct gsm_lchan *lchan)
1183{
Holger Freyther73487a22008-12-31 18:53:57 +00001184 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1185 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001186 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001187}
1188
Harald Welte2a139372009-02-22 21:14:55 +00001189static const char *lupd_name(u_int8_t type)
1190{
1191 switch (type) {
1192 case GSM48_LUPD_NORMAL:
1193 return "NORMAL";
1194 case GSM48_LUPD_PERIODIC:
1195 return "PEROIDOC";
1196 case GSM48_LUPD_IMSI_ATT:
1197 return "IMSI ATTACH";
1198 default:
1199 return "UNKNOWN";
1200 }
1201}
1202
Harald Welte231ad4f2008-12-27 11:15:38 +00001203#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001204/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001205static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001206{
Harald Welte8470bf22008-12-25 23:28:35 +00001207 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001208 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001209 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001210 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001211 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001212 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001213 char mi_string[MI_SIZE];
1214 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001215
Harald Welte8470bf22008-12-25 23:28:35 +00001216 lu = (struct gsm48_loc_upd_req *) gh->data;
1217
1218 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001219
Harald Weltefc977a82008-12-27 10:19:37 +00001220 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1221
Harald Weltea0368542009-06-27 02:58:43 +02001222 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001223 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001224
Holger Freythereaf04692009-06-06 13:54:44 +00001225 /*
1226 * Pseudo Spoof detection: Just drop a second/concurrent
1227 * location updating request.
1228 */
1229 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001230 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001231 lchan->loc_operation);
1232 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1233 return 0;
1234 }
1235
Holger Freyther73487a22008-12-31 18:53:57 +00001236 allocate_loc_updating_req(lchan);
1237
Harald Welte52b1f982008-12-23 20:25:15 +00001238 switch (mi_type) {
1239 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001240 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001241 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001242 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001243 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001244
Harald Welte52b1f982008-12-23 20:25:15 +00001245 /* look up subscriber based on IMSI */
Harald Welte761e9442009-07-23 19:21:02 +02001246 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001247 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001248 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001249 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001250 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001251 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001252 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001253
Harald Welte52b1f982008-12-23 20:25:15 +00001254 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte761e9442009-07-23 19:21:02 +02001255 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001256 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001257 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001258 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001259 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001260 }
1261 break;
1262 case GSM_MI_TYPE_IMEI:
1263 case GSM_MI_TYPE_IMEISV:
1264 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001265 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001266 break;
1267 default:
Harald Weltea0368542009-06-27 02:58:43 +02001268 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001269 break;
1270 }
1271
Harald Welte24516ea2009-07-04 10:18:00 +02001272 /* schedule the reject timer */
1273 schedule_reject(lchan);
1274
Harald Welte4bfdfe72009-06-10 23:11:52 +08001275 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001276 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001277 /* FIXME: request id? close channel? */
1278 return -EINVAL;
1279 }
1280
Harald Welte255539c2008-12-28 02:26:27 +00001281 lchan->subscr = subscr;
1282
Harald Welte24516ea2009-07-04 10:18:00 +02001283 /* check if we can let the subscriber into our network immediately
1284 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001285 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001286}
1287
Harald Welte7584aea2009-02-11 11:44:12 +00001288/* 9.1.5 Channel mode modify */
1289int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1290{
1291 struct msgb *msg = gsm48_msgb_alloc();
1292 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1293 struct gsm48_chan_mode_modify *cmm =
1294 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001295 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001296
Harald Welte4a543e82009-02-28 13:17:55 +00001297 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001298
Harald Welte45b407a2009-05-23 15:51:12 +00001299 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001300 msg->lchan = lchan;
1301 gh->proto_discr = GSM48_PDISC_RR;
1302 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1303
1304 /* fill the channel information element, this code
1305 * should probably be shared with rsl_rx_chan_rqd() */
1306 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001307 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001308 cmm->chan_desc.h0.h = 0;
1309 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1310 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1311 cmm->mode = mode;
1312
Harald Welte39e2ead2009-07-23 21:13:03 +02001313 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001314}
1315
Harald Welte4bfdfe72009-06-10 23:11:52 +08001316#if 0
1317static u_int8_t to_bcd8(u_int8_t val)
1318{
1319 return ((val / 10) << 4) | (val % 10);
1320}
1321#endif
1322
Harald Weltedb253af2008-12-30 17:56:55 +00001323/* Section 9.2.15a */
1324int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1325{
1326 struct msgb *msg = gsm48_msgb_alloc();
1327 struct gsm48_hdr *gh;
1328 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001329 u_int8_t *ptr8;
1330 u_int16_t *ptr16;
1331 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001332 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001333#if 0
1334 time_t cur_t;
1335 struct tm* cur_time;
1336 int tz15min;
1337#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001338
1339 msg->lchan = lchan;
1340
1341 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1342 gh->proto_discr = GSM48_PDISC_MM;
1343 gh->msg_type = GSM48_MT_MM_INFO;
1344
1345 if (net->name_long) {
1346 name_len = strlen(net->name_long);
1347 /* 10.5.3.5a */
1348 ptr8 = msgb_put(msg, 3);
1349 ptr8[0] = GSM48_IE_NAME_LONG;
1350 ptr8[1] = name_len*2 +1;
1351 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1352
1353 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1354 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001355 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001356
1357 /* FIXME: Use Cell Broadcast, not UCS-2, since
1358 * UCS-2 is only supported by later revisions of the spec */
1359 }
1360
1361 if (net->name_short) {
1362 name_len = strlen(net->name_short);
1363 /* 10.5.3.5a */
1364 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001365 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001366 ptr8[1] = name_len*2 + 1;
1367 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1368
Harald Weltee872cb12009-01-01 00:33:37 +00001369 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001370 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001371 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001372 }
1373
1374#if 0
1375 /* Section 10.5.3.9 */
1376 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001377 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001378 ptr8 = msgb_put(msg, 8);
1379 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1380 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1381 ptr8[2] = to_bcd8(cur_time->tm_mon);
1382 ptr8[3] = to_bcd8(cur_time->tm_mday);
1383 ptr8[4] = to_bcd8(cur_time->tm_hour);
1384 ptr8[5] = to_bcd8(cur_time->tm_min);
1385 ptr8[6] = to_bcd8(cur_time->tm_sec);
1386 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1387 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001388 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001389 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001390 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001391#endif
1392
Harald Welte39e2ead2009-07-23 21:13:03 +02001393 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001394}
1395
Harald Welte4b634542008-12-27 01:55:51 +00001396static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1397{
Harald Welte4b634542008-12-27 01:55:51 +00001398 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001399 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001400}
Harald Welteba4cf162009-01-10 01:49:35 +00001401
1402/* 9.2.6 CM service reject */
1403static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1404 enum gsm48_reject_value value)
1405{
1406 struct msgb *msg = gsm48_msgb_alloc();
1407 struct gsm48_hdr *gh;
1408
1409 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1410
1411 msg->lchan = lchan;
1412 use_lchan(lchan);
1413
1414 gh->proto_discr = GSM48_PDISC_MM;
1415 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1416 gh->data[0] = value;
1417 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1418
Harald Welte39e2ead2009-07-23 21:13:03 +02001419 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001420}
1421
Harald Welte4ed0e922009-01-10 03:17:30 +00001422
1423/*
1424 * Handle CM Service Requests
1425 * a) Verify that the packet is long enough to contain the information
1426 * we require otherwsie reject with INCORRECT_MESSAGE
1427 * b) Try to parse the TMSI. If we do not have one reject
1428 * c) Check that we know the subscriber with the TMSI otherwise reject
1429 * with a HLR cause
1430 * d) Set the subscriber on the gsm_lchan and accept
1431 */
Harald Welte4b634542008-12-27 01:55:51 +00001432static int gsm48_rx_mm_serv_req(struct msgb *msg)
1433{
Harald Welteba4cf162009-01-10 01:49:35 +00001434 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001435 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001436
Harald Welte761e9442009-07-23 19:21:02 +02001437 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001438 struct gsm_subscriber *subscr;
1439 struct gsm48_hdr *gh = msgb_l3(msg);
1440 struct gsm48_service_request *req =
1441 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001442 /* unfortunately in Phase1 the classmar2 length is variable */
1443 u_int8_t classmark2_len = gh->data[1];
1444 u_int8_t *classmark2 = gh->data+2;
1445 u_int8_t mi_len = *(classmark2 + classmark2_len);
1446 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001447
Harald Weltec9e02182009-05-01 19:07:53 +00001448 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001449 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001450 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001451 return gsm48_tx_mm_serv_rej(msg->lchan,
1452 GSM48_REJECT_INCORRECT_MESSAGE);
1453 }
1454
1455 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001456 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001457 return gsm48_tx_mm_serv_rej(msg->lchan,
1458 GSM48_REJECT_INCORRECT_MESSAGE);
1459 }
1460
Harald Weltec9e02182009-05-01 19:07:53 +00001461 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001462 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001463 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001464 return gsm48_tx_mm_serv_rej(msg->lchan,
1465 GSM48_REJECT_INCORRECT_MESSAGE);
1466 }
1467
Harald Weltec9e02182009-05-01 19:07:53 +00001468 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001469 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001470 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001471
Harald Welte761e9442009-07-23 19:21:02 +02001472 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001473
Harald Welte2a139372009-02-22 21:14:55 +00001474 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001475 if (!subscr)
1476 return gsm48_tx_mm_serv_rej(msg->lchan,
1477 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1478
1479 if (!msg->lchan->subscr)
1480 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001481 else if (msg->lchan->subscr != subscr) {
1482 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1483 subscr_put(subscr);
1484 }
1485
Harald Weltec2e302d2009-07-05 14:08:13 +02001486 subscr->equipment.classmark2_len = classmark2_len;
1487 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1488 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001489
Harald Welte4b634542008-12-27 01:55:51 +00001490 return gsm48_tx_mm_serv_ack(msg->lchan);
1491}
1492
Harald Welte2a139372009-02-22 21:14:55 +00001493static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1494{
Harald Welte761e9442009-07-23 19:21:02 +02001495 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001496 struct gsm48_hdr *gh = msgb_l3(msg);
1497 struct gsm48_imsi_detach_ind *idi =
1498 (struct gsm48_imsi_detach_ind *) gh->data;
1499 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1500 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001501 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001502
1503 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1504 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1505 mi_type, mi_string);
1506
1507 switch (mi_type) {
1508 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001509 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001510 break;
1511 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001512 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001513 break;
1514 case GSM_MI_TYPE_IMEI:
1515 case GSM_MI_TYPE_IMEISV:
1516 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001517 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001518 break;
1519 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001520 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001521 break;
1522 }
1523
Holger Freyther4a49e772009-04-12 05:37:29 +00001524 if (subscr) {
1525 subscr_update(subscr, msg->trx->bts,
1526 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001527 DEBUGP(DMM, "Subscriber: %s\n",
1528 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001529 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001530 } else
Harald Welte2a139372009-02-22 21:14:55 +00001531 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1532
Harald Welte2a139372009-02-22 21:14:55 +00001533 return 0;
1534}
1535
Harald Welted2a7f5a2009-06-05 20:08:20 +00001536static int gsm48_rx_mm_status(struct msgb *msg)
1537{
1538 struct gsm48_hdr *gh = msgb_l3(msg);
1539
1540 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1541
1542 return 0;
1543}
1544
Harald Weltebf5e8df2009-02-03 12:59:45 +00001545/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001546static int gsm0408_rcv_mm(struct msgb *msg)
1547{
1548 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001549 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001550
1551 switch (gh->msg_type & 0xbf) {
1552 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001553 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001554 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001555 break;
1556 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001557 rc = mm_rx_id_resp(msg);
1558 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001559 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001560 rc = gsm48_rx_mm_serv_req(msg);
1561 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001562 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001563 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001564 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001565 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001566 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1567 msg->lchan->subscr ?
1568 msg->lchan->subscr->imsi :
1569 "unknown subscriber");
1570 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001571 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001572 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1573 break;
1574 case GSM48_MT_MM_CM_REEST_REQ:
1575 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1576 break;
1577 case GSM48_MT_MM_AUTH_RESP:
1578 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001579 break;
1580 default:
1581 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1582 gh->msg_type);
1583 break;
1584 }
1585
1586 return rc;
1587}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001588
Harald Welte2d35ae62009-02-06 12:02:13 +00001589/* Receive a PAGING RESPONSE message from the MS */
1590static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1591{
Harald Welte761e9442009-07-23 19:21:02 +02001592 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001593 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001594 u_int8_t *classmark2_lv = gh->data + 1;
1595 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1596 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001597 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001598 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001599 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001600 int rc = 0;
1601
Harald Welte61548982009-02-22 21:26:29 +00001602 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001603 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1604 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001605 switch (mi_type) {
1606 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001607 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001608 break;
1609 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001610 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001611 break;
1612 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001613
1614 if (!subscr) {
1615 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001616 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001617 return -EINVAL;
1618 }
1619 DEBUGP(DRR, "<- Channel was requested by %s\n",
1620 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001621
Harald Weltec2e302d2009-07-05 14:08:13 +02001622 subscr->equipment.classmark2_len = *classmark2_lv;
1623 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1624 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001625
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001626 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001627 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001628 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001629 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1630 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001631 return -EINVAL;
1632 } else {
1633 DEBUGP(DRR, "<- Channel already owned by us\n");
1634 subscr_put(subscr);
1635 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001636 }
1637
Harald Welte595ad7b2009-02-16 22:05:44 +00001638 sig_data.subscr = subscr;
1639 sig_data.bts = msg->lchan->ts->trx->bts;
1640 sig_data.lchan = msg->lchan;
1641
1642 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001643
1644 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001645 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001646
Harald Welte7584aea2009-02-11 11:44:12 +00001647 /* FIXME: somehow signal the completion of the PAGING to
1648 * the entity that requested the paging */
1649
Harald Welte2d35ae62009-02-06 12:02:13 +00001650 return rc;
1651}
1652
Harald Weltef7c43522009-06-09 20:24:21 +00001653static int gsm48_rx_rr_classmark(struct msgb *msg)
1654{
1655 struct gsm48_hdr *gh = msgb_l3(msg);
1656 struct gsm_subscriber *subscr = msg->lchan->subscr;
1657 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1658 u_int8_t cm2_len, cm3_len = 0;
1659 u_int8_t *cm2, *cm3 = NULL;
1660
1661 DEBUGP(DRR, "CLASSMARK CHANGE ");
1662
1663 /* classmark 2 */
1664 cm2_len = gh->data[0];
1665 cm2 = &gh->data[1];
1666 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1667
1668 if (payload_len > cm2_len + 1) {
1669 /* we must have a classmark3 */
1670 if (gh->data[cm2_len+1] != 0x20) {
1671 DEBUGPC(DRR, "ERR CM3 TAG\n");
1672 return -EINVAL;
1673 }
1674 if (cm2_len > 3) {
1675 DEBUGPC(DRR, "CM2 too long!\n");
1676 return -EINVAL;
1677 }
1678
1679 cm3_len = gh->data[cm2_len+2];
1680 cm3 = &gh->data[cm2_len+3];
1681 if (cm3_len > 14) {
1682 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1683 return -EINVAL;
1684 }
1685 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1686 }
1687 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001688 subscr->equipment.classmark2_len = cm2_len;
1689 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001690 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001691 subscr->equipment.classmark3_len = cm3_len;
1692 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001693 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001694 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001695 }
1696
Harald Weltef7c43522009-06-09 20:24:21 +00001697 return 0;
1698}
1699
Harald Weltecf5b3592009-05-01 18:28:42 +00001700static int gsm48_rx_rr_status(struct msgb *msg)
1701{
1702 struct gsm48_hdr *gh = msgb_l3(msg);
1703
1704 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1705 rr_cause_name(gh->data[0]));
1706
1707 return 0;
1708}
1709
Harald Weltef7c43522009-06-09 20:24:21 +00001710static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1711{
1712 struct gsm48_hdr *gh = msgb_l3(msg);
1713 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1714 static struct gsm_meas_rep meas_rep;
1715
Harald Welte10d0e672009-06-27 02:53:10 +02001716 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001717 parse_meas_rep(&meas_rep, gh->data, payload_len);
1718 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001719 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001720 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001721 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001722 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001723 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001724 else
Harald Welte10d0e672009-06-27 02:53:10 +02001725 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001726 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1727 meas_rep.rxqual_sub);
1728
Harald Welte10d0e672009-06-27 02:53:10 +02001729 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001730
1731 /* FIXME: put the results somwhere */
1732
1733 return 0;
1734}
1735
Harald Weltebf5e8df2009-02-03 12:59:45 +00001736/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001737static int gsm0408_rcv_rr(struct msgb *msg)
1738{
1739 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001740 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001741
1742 switch (gh->msg_type) {
1743 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001744 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001745 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001746 case GSM48_MT_RR_GPRS_SUSP_REQ:
1747 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1748 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001749 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001750 rc = gsm48_rr_rx_pag_resp(msg);
1751 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001752 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1753 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001754 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001755 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001756 case GSM48_MT_RR_STATUS:
1757 rc = gsm48_rx_rr_status(msg);
1758 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001759 case GSM48_MT_RR_MEAS_REP:
1760 rc = gsm48_rx_rr_meas_rep(msg);
1761 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001762 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001763 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001764 gh->msg_type);
1765 break;
1766 }
1767
Harald Welte2d35ae62009-02-06 12:02:13 +00001768 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001769}
1770
Holger Freythere64a7a32009-02-06 21:55:37 +00001771/* 7.1.7 and 9.1.7 Channel release*/
1772int gsm48_send_rr_release(struct gsm_lchan *lchan)
1773{
1774 struct msgb *msg = gsm48_msgb_alloc();
1775 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1776 u_int8_t *cause;
1777
1778 msg->lchan = lchan;
1779 gh->proto_discr = GSM48_PDISC_RR;
1780 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1781
1782 cause = msgb_put(msg, 1);
1783 cause[0] = GSM48_RR_CAUSE_NORMAL;
1784
1785 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1786 lchan->nr, lchan->type);
1787
Harald Welteae0f2362009-07-19 18:36:49 +02001788 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001789 gsm48_sendmsg(msg, NULL);
Harald Welteae0f2362009-07-19 18:36:49 +02001790
1791 /* Deactivate the SACCH on the BTS side */
1792 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001793}
1794
Harald Welte4bc90a12008-12-27 16:32:52 +00001795/* Call Control */
1796
Harald Welte7584aea2009-02-11 11:44:12 +00001797/* The entire call control code is written in accordance with Figure 7.10c
1798 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1799 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1800 * it for voice */
1801
Harald Welte4bfdfe72009-06-10 23:11:52 +08001802static void new_cc_state(struct gsm_trans *trans, int state)
1803{
1804 if (state > 31 || state < 0)
1805 return;
1806
1807 DEBUGP(DCC, "new state %s -> %s\n",
Harald Welteaa0b29c2009-07-23 18:56:43 +02001808 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001809
Harald Welteaa0b29c2009-07-23 18:56:43 +02001810 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001811}
1812
1813static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001814{
1815 struct msgb *msg = gsm48_msgb_alloc();
1816 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1817 u_int8_t *cause, *call_state;
1818
Harald Welte4bc90a12008-12-27 16:32:52 +00001819 gh->msg_type = GSM48_MT_CC_STATUS;
1820
1821 cause = msgb_put(msg, 3);
1822 cause[0] = 2;
1823 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1824 cause[2] = 0x80 | 30; /* response to status inquiry */
1825
1826 call_state = msgb_put(msg, 1);
1827 call_state[0] = 0xc0 | 0x00;
1828
Harald Welte39e2ead2009-07-23 21:13:03 +02001829 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001830}
1831
Harald Welte6f4b7532008-12-29 00:39:37 +00001832static int gsm48_tx_simple(struct gsm_lchan *lchan,
1833 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001834{
1835 struct msgb *msg = gsm48_msgb_alloc();
1836 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1837
1838 msg->lchan = lchan;
1839
Harald Welte6f4b7532008-12-29 00:39:37 +00001840 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001841 gh->msg_type = msg_type;
1842
Harald Welte39e2ead2009-07-23 21:13:03 +02001843 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001844}
1845
Harald Welte4bfdfe72009-06-10 23:11:52 +08001846static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1847{
Harald Welteaa0b29c2009-07-23 18:56:43 +02001848 if (bsc_timer_pending(&trans->cc.timer)) {
1849 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1850 bsc_del_timer(&trans->cc.timer);
1851 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001852 }
1853}
1854
1855static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1856 int msg_type, struct gsm_mncc *mncc)
1857{
1858 struct msgb *msg;
1859
1860 if (trans)
1861 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001862 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001863 "Sending '%s' to MNCC.\n",
1864 trans->lchan->ts->trx->bts->nr,
1865 trans->lchan->ts->trx->nr,
1866 trans->lchan->ts->nr, trans->transaction_id,
1867 (trans->subscr)?(trans->subscr->extension):"-",
1868 get_mncc_name(msg_type));
1869 else
1870 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1871 "Sending '%s' to MNCC.\n",
1872 (trans->subscr)?(trans->subscr->extension):"-",
1873 get_mncc_name(msg_type));
1874 else
1875 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1876 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1877
1878 mncc->msg_type = msg_type;
1879
Harald Welte966636f2009-06-26 19:39:35 +02001880 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001881 if (!msg)
1882 return -ENOMEM;
1883 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1884 msgb_enqueue(&net->upqueue, msg);
1885
1886 return 0;
1887}
1888
1889int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1890 u_int32_t callref, int location, int value)
1891{
1892 struct gsm_mncc rel;
1893
Harald Welte92f70c52009-06-12 01:54:08 +08001894 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001895 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001896 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001897 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1898}
1899
Harald Welteaa0b29c2009-07-23 18:56:43 +02001900/* Call Control Specific transaction release.
1901 * gets called by trans_free, DO NOT CALL YOURSELF! */
1902void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001903{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001904 gsm48_stop_cc_timer(trans);
1905
1906 /* send release to L4, if callref still exists */
1907 if (trans->callref) {
1908 /* Ressource unavailable */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001909 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001910 GSM48_CAUSE_LOC_PRN_S_LU,
1911 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001912 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02001913 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001914 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Welteaa0b29c2009-07-23 18:56:43 +02001915 if (trans->lchan)
1916 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001917}
1918
1919static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1920
Harald Welte09e38af2009-02-16 22:52:23 +00001921/* call-back from paging the B-end of the connection */
1922static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001923 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001924{
Harald Welte7ccf7782009-02-17 01:43:01 +00001925 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001926 struct gsm_subscriber *subscr = param;
1927 struct gsm_trans *transt, *tmp;
1928 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001929
Harald Welte09e38af2009-02-16 22:52:23 +00001930 if (hooknum != GSM_HOOK_RR_PAGING)
1931 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001932
1933 if (!subscr)
1934 return -EINVAL;
1935 net = subscr->net;
1936 if (!net) {
1937 DEBUGP(DCC, "Error Network not set!\n");
1938 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001939 }
Harald Welte7584aea2009-02-11 11:44:12 +00001940
Harald Welte4bfdfe72009-06-10 23:11:52 +08001941 /* check all tranactions (without lchan) for subscriber */
1942 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1943 if (transt->subscr != subscr || transt->lchan)
1944 continue;
1945 switch (event) {
1946 case GSM_PAGING_SUCCEEDED:
1947 if (!lchan) // paranoid
1948 break;
1949 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1950 subscr->extension);
1951 /* Assign lchan */
1952 if (!transt->lchan) {
1953 transt->lchan = lchan;
1954 use_lchan(lchan);
1955 }
1956 /* send SETUP request to called party */
Harald Welteaa0b29c2009-07-23 18:56:43 +02001957 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001958 if (is_ipaccess_bts(lchan->ts->trx->bts))
1959 rsl_ipacc_bind(lchan);
1960 break;
1961 case GSM_PAGING_EXPIRED:
1962 DEBUGP(DCC, "Paging subscr %s expired!\n",
1963 subscr->extension);
1964 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001965 mncc_release_ind(transt->subscr->net, transt,
1966 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001967 GSM48_CAUSE_LOC_PRN_S_LU,
1968 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001969 transt->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02001970 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001971 break;
1972 }
1973 }
Harald Welte09e38af2009-02-16 22:52:23 +00001974 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001975}
Harald Welte7584aea2009-02-11 11:44:12 +00001976
Harald Welte49f48b82009-02-17 15:29:33 +00001977/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001978static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001979{
Harald Welte11fa29c2009-02-19 17:24:39 +00001980 struct gsm_bts *bts = lchan->ts->trx->bts;
1981 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001982 struct gsm_bts_trx_ts *ts;
1983
Harald Welte11fa29c2009-02-19 17:24:39 +00001984 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1985 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1986 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1987
1988 if (bts->type != remote_bts->type) {
1989 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1990 return -EINVAL;
1991 }
Harald Welte49f48b82009-02-17 15:29:33 +00001992
Harald Welte11fa29c2009-02-19 17:24:39 +00001993 switch (bts->type) {
1994 case GSM_BTS_TYPE_NANOBTS_900:
1995 case GSM_BTS_TYPE_NANOBTS_1800:
1996 ts = remote_lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02001997 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
1998 ts->abis_ip.bound_port,
1999 lchan->ts->abis_ip.conn_id,
2000 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002001
2002 ts = lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002003 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2004 ts->abis_ip.bound_port,
2005 remote_lchan->ts->abis_ip.conn_id,
2006 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002007 break;
2008 case GSM_BTS_TYPE_BS11:
2009 trau_mux_map_lchan(lchan, remote_lchan);
2010 break;
2011 default:
2012 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2013 break;
2014 }
Harald Welte49f48b82009-02-17 15:29:33 +00002015
2016 return 0;
2017}
2018
Harald Welte4bfdfe72009-06-10 23:11:52 +08002019/* bridge channels of two transactions */
2020static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002021{
Harald Welteaa0b29c2009-07-23 18:56:43 +02002022 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2023 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002024
Harald Welte4bfdfe72009-06-10 23:11:52 +08002025 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002026 return -EIO;
2027
Harald Welte4bfdfe72009-06-10 23:11:52 +08002028 if (!trans1->lchan || !trans2->lchan)
2029 return -EIO;
2030
2031 /* through-connect channel */
2032 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002033}
2034
Harald Welte4bfdfe72009-06-10 23:11:52 +08002035/* enable receive of channels to upqueue */
2036static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2037{
2038 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002039
Harald Welte4bfdfe72009-06-10 23:11:52 +08002040 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002041 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002042 if (!trans)
2043 return -EIO;
2044 if (!trans->lchan)
2045 return 0;
2046
2047 // todo IPACCESS
2048 if (enable)
2049 return trau_recv_lchan(trans->lchan, data->callref);
2050 return trau_mux_unmap(NULL, data->callref);
2051}
2052
2053/* send a frame to channel */
2054static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2055{
2056 struct gsm_trans *trans;
2057
2058 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002059 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002060 if (!trans)
2061 return -EIO;
2062 if (!trans->lchan)
2063 return 0;
2064 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2065 trans->lchan->type != GSM_LCHAN_TCH_H)
2066 return 0;
2067
2068 // todo IPACCESS
2069 return trau_send_lchan(trans->lchan,
2070 (struct decoded_trau_frame *)frame->data);
2071}
2072
2073
2074static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2075{
2076 DEBUGP(DCC, "-> STATUS ENQ\n");
2077 return gsm48_cc_tx_status(trans, msg);
2078}
2079
2080static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2081static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2082
2083static void gsm48_cc_timeout(void *arg)
2084{
2085 struct gsm_trans *trans = arg;
2086 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002087 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2088 int mo_location = GSM48_CAUSE_LOC_USER;
2089 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2090 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002091 struct gsm_mncc mo_rel, l4_rel;
2092
2093 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2094 mo_rel.callref = trans->callref;
2095 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2096 l4_rel.callref = trans->callref;
2097
Harald Welteaa0b29c2009-07-23 18:56:43 +02002098 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002099 case 0x303:
2100 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002101 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002102 break;
2103 case 0x310:
2104 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002105 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002106 break;
2107 case 0x313:
2108 disconnect = 1;
2109 /* unknown, did not find it in the specs */
2110 break;
2111 case 0x301:
2112 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002113 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002114 break;
2115 case 0x308:
Harald Welteaa0b29c2009-07-23 18:56:43 +02002116 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002117 /* restart T308 a second time */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002118 gsm48_cc_tx_release(trans, &trans->cc.msg);
2119 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002120 break; /* stay in release state */
2121 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02002122 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002123 return;
2124// release = 1;
2125// l4_cause = 14;
2126// break;
2127 case 0x306:
2128 release = 1;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002129 mo_cause = trans->cc.msg.cause.value;
2130 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002131 break;
2132 case 0x323:
2133 disconnect = 1;
2134 break;
2135 default:
2136 release = 1;
2137 }
2138
2139 if (release && trans->callref) {
2140 /* process release towards layer 4 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002141 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002142 l4_location, l4_cause);
2143 trans->callref = 0;
2144 }
2145
2146 if (disconnect && trans->callref) {
2147 /* process disconnect towards layer 4 */
2148 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welteb3c3fae2009-07-23 19:06:52 +02002149 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002150 }
2151
2152 /* process disconnect towards mobile station */
2153 if (disconnect || release) {
2154 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002155 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2156 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2157 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002158 mo_rel.cause.diag_len = 3;
2159
2160 if (disconnect)
2161 gsm48_cc_tx_disconnect(trans, &mo_rel);
2162 if (release)
2163 gsm48_cc_tx_release(trans, &mo_rel);
2164 }
2165
2166}
2167
2168static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2169 int sec, int micro)
2170{
2171 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002172 trans->cc.timer.cb = gsm48_cc_timeout;
2173 trans->cc.timer.data = trans;
2174 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2175 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002176}
2177
2178static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2179{
2180 struct gsm48_hdr *gh = msgb_l3(msg);
2181 u_int8_t msg_type = gh->msg_type & 0xbf;
2182 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2183 struct tlv_parsed tp;
2184 struct gsm_mncc setup;
2185
2186 memset(&setup, 0, sizeof(struct gsm_mncc));
2187 setup.callref = trans->callref;
2188 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2189 /* emergency setup is identified by msg_type */
2190 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2191 setup.emergency = 1;
2192
2193 /* use subscriber as calling party number */
2194 if (trans->subscr) {
2195 setup.fields |= MNCC_F_CALLING;
2196 strncpy(setup.calling.number, trans->subscr->extension,
2197 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002198 strncpy(setup.imsi, trans->subscr->imsi,
2199 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002200 }
2201 /* bearer capability */
2202 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2203 setup.fields |= MNCC_F_BEARER_CAP;
2204 decode_bearer_cap(&setup.bearer_cap,
2205 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2206 }
2207 /* facility */
2208 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2209 setup.fields |= MNCC_F_FACILITY;
2210 decode_facility(&setup.facility,
2211 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2212 }
2213 /* called party bcd number */
2214 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2215 setup.fields |= MNCC_F_CALLED;
2216 decode_called(&setup.called,
2217 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2218 }
2219 /* user-user */
2220 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2221 setup.fields |= MNCC_F_USERUSER;
2222 decode_useruser(&setup.useruser,
2223 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2224 }
2225 /* ss-version */
2226 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2227 setup.fields |= MNCC_F_SSVERSION;
2228 decode_ssversion(&setup.ssversion,
2229 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2230 }
2231 /* CLIR suppression */
2232 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2233 setup.clir.sup = 1;
2234 /* CLIR invocation */
2235 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2236 setup.clir.inv = 1;
2237 /* cc cap */
2238 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2239 setup.fields |= MNCC_F_CCCAP;
2240 decode_cccap(&setup.cccap,
2241 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2242 }
2243
2244 if (is_ipaccess_bts(msg->trx->bts))
2245 rsl_ipacc_bind(msg->lchan);
2246
2247 new_cc_state(trans, GSM_CSTATE_INITIATED);
2248
2249 /* indicate setup to MNCC */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002250 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002251
2252 return 0;
2253}
2254
2255static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002256{
2257 struct msgb *msg = gsm48_msgb_alloc();
2258 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002259 struct gsm_mncc *setup = arg;
2260 struct gsm_trans *transt;
2261 u_int16_t trans_id_mask = 0;
2262 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002263
Harald Welte7ccf7782009-02-17 01:43:01 +00002264 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002265
Harald Welte4bfdfe72009-06-10 23:11:52 +08002266 /* transaction id must not be assigned */
2267 if (trans->transaction_id != 0xff) { /* unasssigned */
2268 DEBUGP(DCC, "TX Setup with assigned transaction. "
2269 "This is not allowed!\n");
2270 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002271 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002272 GSM48_CAUSE_LOC_PRN_S_LU,
2273 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002274 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002275 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002276 return rc;
2277 }
2278
2279 /* Get free transaction_id */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002280 llist_for_each_entry(transt, &trans->subscr->net->trans_list, entry) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002281 /* Transaction of our lchan? */
2282 if (transt->lchan == trans->lchan &&
2283 transt->transaction_id != 0xff)
Harald Welte6f5aee02009-07-23 21:21:14 +02002284 trans_id_mask |= (1 << transt->transaction_id);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002285 }
2286 /* Assign free transaction ID */
2287 if ((trans_id_mask & 0x007f) == 0x7f) {
2288 /* no free transaction ID */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002289 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002290 GSM48_CAUSE_LOC_PRN_S_LU,
2291 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002292 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002293 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002294 return rc;
2295 }
2296 for (i = 0; i < 7; i++) {
2297 if ((trans_id_mask & (1 << i)) == 0) {
Harald Welte6f5aee02009-07-23 21:21:14 +02002298 trans->transaction_id = i; /* flag = 0 */
Harald Welte4bfdfe72009-06-10 23:11:52 +08002299 break;
2300 }
2301 }
Harald Welte49f48b82009-02-17 15:29:33 +00002302
Harald Welte65e74cc2008-12-29 01:55:35 +00002303 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002304
Harald Welte4bfdfe72009-06-10 23:11:52 +08002305 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002306
Harald Welte4bfdfe72009-06-10 23:11:52 +08002307 /* bearer capability */
2308 if (setup->fields & MNCC_F_BEARER_CAP)
2309 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2310 /* facility */
2311 if (setup->fields & MNCC_F_FACILITY)
2312 encode_facility(msg, 0, &setup->facility);
2313 /* progress */
2314 if (setup->fields & MNCC_F_PROGRESS)
2315 encode_progress(msg, 0, &setup->progress);
2316 /* calling party BCD number */
2317 if (setup->fields & MNCC_F_CALLING)
2318 encode_calling(msg, &setup->calling);
2319 /* called party BCD number */
2320 if (setup->fields & MNCC_F_CALLED)
2321 encode_called(msg, &setup->called);
2322 /* user-user */
2323 if (setup->fields & MNCC_F_USERUSER)
2324 encode_useruser(msg, 0, &setup->useruser);
2325 /* redirecting party BCD number */
2326 if (setup->fields & MNCC_F_REDIRECTING)
2327 encode_redirecting(msg, &setup->redirecting);
2328 /* signal */
2329 if (setup->fields & MNCC_F_SIGNAL)
2330 encode_signal(msg, setup->signal);
2331
2332 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002333
Harald Welte39e2ead2009-07-23 21:13:03 +02002334 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002335}
2336
Harald Welte4bfdfe72009-06-10 23:11:52 +08002337static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2338{
2339 struct gsm48_hdr *gh = msgb_l3(msg);
2340 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2341 struct tlv_parsed tp;
2342 struct gsm_mncc call_conf;
2343
2344 gsm48_stop_cc_timer(trans);
2345 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2346
2347 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2348 call_conf.callref = trans->callref;
2349 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2350#if 0
2351 /* repeat */
2352 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2353 call_conf.repeat = 1;
2354 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2355 call_conf.repeat = 2;
2356#endif
2357 /* bearer capability */
2358 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2359 call_conf.fields |= MNCC_F_BEARER_CAP;
2360 decode_bearer_cap(&call_conf.bearer_cap,
2361 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2362 }
2363 /* cause */
2364 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2365 call_conf.fields |= MNCC_F_CAUSE;
2366 decode_cause(&call_conf.cause,
2367 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2368 }
2369 /* cc cap */
2370 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2371 call_conf.fields |= MNCC_F_CCCAP;
2372 decode_cccap(&call_conf.cccap,
2373 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2374 }
2375
2376 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2377
Harald Welteb3c3fae2009-07-23 19:06:52 +02002378 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2379 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002380}
2381
2382static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2383{
2384 struct gsm_mncc *proceeding = arg;
2385 struct msgb *msg = gsm48_msgb_alloc();
2386 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2387
Harald Welte4bfdfe72009-06-10 23:11:52 +08002388 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2389
2390 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2391
2392 /* bearer capability */
2393 if (proceeding->fields & MNCC_F_BEARER_CAP)
2394 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2395 /* facility */
2396 if (proceeding->fields & MNCC_F_FACILITY)
2397 encode_facility(msg, 0, &proceeding->facility);
2398 /* progress */
2399 if (proceeding->fields & MNCC_F_PROGRESS)
2400 encode_progress(msg, 0, &proceeding->progress);
2401
Harald Welte39e2ead2009-07-23 21:13:03 +02002402 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002403}
2404
2405static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2406{
2407 struct gsm48_hdr *gh = msgb_l3(msg);
2408 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2409 struct tlv_parsed tp;
2410 struct gsm_mncc alerting;
2411
2412 gsm48_stop_cc_timer(trans);
2413 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2414
2415 memset(&alerting, 0, sizeof(struct gsm_mncc));
2416 alerting.callref = trans->callref;
2417 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2418 /* facility */
2419 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2420 alerting.fields |= MNCC_F_FACILITY;
2421 decode_facility(&alerting.facility,
2422 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2423 }
2424
2425 /* progress */
2426 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2427 alerting.fields |= MNCC_F_PROGRESS;
2428 decode_progress(&alerting.progress,
2429 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2430 }
2431 /* ss-version */
2432 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2433 alerting.fields |= MNCC_F_SSVERSION;
2434 decode_ssversion(&alerting.ssversion,
2435 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2436 }
2437
2438 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2439
Harald Welteb3c3fae2009-07-23 19:06:52 +02002440 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2441 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002442}
2443
2444static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2445{
2446 struct gsm_mncc *alerting = arg;
2447 struct msgb *msg = gsm48_msgb_alloc();
2448 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2449
Harald Welte4bfdfe72009-06-10 23:11:52 +08002450 gh->msg_type = GSM48_MT_CC_ALERTING;
2451
2452 /* facility */
2453 if (alerting->fields & MNCC_F_FACILITY)
2454 encode_facility(msg, 0, &alerting->facility);
2455 /* progress */
2456 if (alerting->fields & MNCC_F_PROGRESS)
2457 encode_progress(msg, 0, &alerting->progress);
2458 /* user-user */
2459 if (alerting->fields & MNCC_F_USERUSER)
2460 encode_useruser(msg, 0, &alerting->useruser);
2461
2462 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2463
Harald Welte39e2ead2009-07-23 21:13:03 +02002464 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002465}
2466
2467static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2468{
2469 struct gsm_mncc *progress = arg;
2470 struct msgb *msg = gsm48_msgb_alloc();
2471 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2472
Harald Welte4bfdfe72009-06-10 23:11:52 +08002473 gh->msg_type = GSM48_MT_CC_PROGRESS;
2474
2475 /* progress */
2476 encode_progress(msg, 1, &progress->progress);
2477 /* user-user */
2478 if (progress->fields & MNCC_F_USERUSER)
2479 encode_useruser(msg, 0, &progress->useruser);
2480
Harald Welte39e2ead2009-07-23 21:13:03 +02002481 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002482}
2483
2484static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2485{
2486 struct gsm_mncc *connect = arg;
2487 struct msgb *msg = gsm48_msgb_alloc();
2488 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2489
Harald Welte4bfdfe72009-06-10 23:11:52 +08002490 gh->msg_type = GSM48_MT_CC_CONNECT;
2491
2492 gsm48_stop_cc_timer(trans);
2493 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2494
2495 /* facility */
2496 if (connect->fields & MNCC_F_FACILITY)
2497 encode_facility(msg, 0, &connect->facility);
2498 /* progress */
2499 if (connect->fields & MNCC_F_PROGRESS)
2500 encode_progress(msg, 0, &connect->progress);
2501 /* connected number */
2502 if (connect->fields & MNCC_F_CONNECTED)
2503 encode_connected(msg, &connect->connected);
2504 /* user-user */
2505 if (connect->fields & MNCC_F_USERUSER)
2506 encode_useruser(msg, 0, &connect->useruser);
2507
2508 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2509
Harald Welte39e2ead2009-07-23 21:13:03 +02002510 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002511}
2512
2513static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2514{
2515 struct gsm48_hdr *gh = msgb_l3(msg);
2516 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2517 struct tlv_parsed tp;
2518 struct gsm_mncc connect;
2519
2520 gsm48_stop_cc_timer(trans);
2521
2522 memset(&connect, 0, sizeof(struct gsm_mncc));
2523 connect.callref = trans->callref;
2524 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2525 /* use subscriber as connected party number */
2526 if (trans->subscr) {
2527 connect.fields |= MNCC_F_CONNECTED;
2528 strncpy(connect.connected.number, trans->subscr->extension,
2529 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002530 strncpy(connect.imsi, trans->subscr->imsi,
2531 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002532 }
2533 /* facility */
2534 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2535 connect.fields |= MNCC_F_FACILITY;
2536 decode_facility(&connect.facility,
2537 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2538 }
2539 /* user-user */
2540 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2541 connect.fields |= MNCC_F_USERUSER;
2542 decode_useruser(&connect.useruser,
2543 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2544 }
2545 /* ss-version */
2546 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2547 connect.fields |= MNCC_F_SSVERSION;
2548 decode_ssversion(&connect.ssversion,
2549 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2550 }
2551
2552 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2553
Harald Welteb3c3fae2009-07-23 19:06:52 +02002554 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002555}
2556
2557
2558static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2559{
2560 struct gsm_mncc connect_ack;
2561
2562 gsm48_stop_cc_timer(trans);
2563
2564 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2565
2566 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2567 connect_ack.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002568 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002569 &connect_ack);
2570}
2571
2572static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2573{
2574 struct msgb *msg = gsm48_msgb_alloc();
2575 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2576
Harald Welte4bfdfe72009-06-10 23:11:52 +08002577 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2578
2579 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2580
Harald Welte39e2ead2009-07-23 21:13:03 +02002581 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002582}
2583
2584static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2585{
2586 struct gsm48_hdr *gh = msgb_l3(msg);
2587 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2588 struct tlv_parsed tp;
2589 struct gsm_mncc disc;
2590
2591 gsm48_stop_cc_timer(trans);
2592
2593 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2594
2595 memset(&disc, 0, sizeof(struct gsm_mncc));
2596 disc.callref = trans->callref;
2597 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2598 /* cause */
2599 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2600 disc.fields |= MNCC_F_CAUSE;
2601 decode_cause(&disc.cause,
2602 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2603 }
2604 /* facility */
2605 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2606 disc.fields |= MNCC_F_FACILITY;
2607 decode_facility(&disc.facility,
2608 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2609 }
2610 /* user-user */
2611 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2612 disc.fields |= MNCC_F_USERUSER;
2613 decode_useruser(&disc.useruser,
2614 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2615 }
2616 /* ss-version */
2617 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2618 disc.fields |= MNCC_F_SSVERSION;
2619 decode_ssversion(&disc.ssversion,
2620 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2621 }
2622
Harald Welteb3c3fae2009-07-23 19:06:52 +02002623 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002624
2625}
2626
Harald Weltec66b71c2009-06-11 14:23:20 +08002627static struct gsm_mncc_cause default_cause = {
2628 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2629 .coding = 0,
2630 .rec = 0,
2631 .rec_val = 0,
2632 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2633 .diag_len = 0,
2634 .diag = { 0 },
2635};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002636
2637static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2638{
2639 struct gsm_mncc *disc = arg;
2640 struct msgb *msg = gsm48_msgb_alloc();
2641 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2642
Harald Welte4bfdfe72009-06-10 23:11:52 +08002643 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2644
2645 gsm48_stop_cc_timer(trans);
2646 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2647
2648 /* cause */
2649 if (disc->fields & MNCC_F_CAUSE)
2650 encode_cause(msg, 1, &disc->cause);
2651 else
2652 encode_cause(msg, 1, &default_cause);
2653
2654 /* facility */
2655 if (disc->fields & MNCC_F_FACILITY)
2656 encode_facility(msg, 0, &disc->facility);
2657 /* progress */
2658 if (disc->fields & MNCC_F_PROGRESS)
2659 encode_progress(msg, 0, &disc->progress);
2660 /* user-user */
2661 if (disc->fields & MNCC_F_USERUSER)
2662 encode_useruser(msg, 0, &disc->useruser);
2663
2664 /* store disconnect cause for T306 expiry */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002665 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002666
2667 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2668
Harald Welte39e2ead2009-07-23 21:13:03 +02002669 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002670}
2671
2672static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2673{
2674 struct gsm48_hdr *gh = msgb_l3(msg);
2675 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2676 struct tlv_parsed tp;
2677 struct gsm_mncc rel;
2678 int rc;
2679
2680 gsm48_stop_cc_timer(trans);
2681
2682 memset(&rel, 0, sizeof(struct gsm_mncc));
2683 rel.callref = trans->callref;
2684 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2685 /* cause */
2686 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2687 rel.fields |= MNCC_F_CAUSE;
2688 decode_cause(&rel.cause,
2689 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2690 }
2691 /* facility */
2692 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2693 rel.fields |= MNCC_F_FACILITY;
2694 decode_facility(&rel.facility,
2695 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2696 }
2697 /* user-user */
2698 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2699 rel.fields |= MNCC_F_USERUSER;
2700 decode_useruser(&rel.useruser,
2701 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2702 }
2703 /* ss-version */
2704 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2705 rel.fields |= MNCC_F_SSVERSION;
2706 decode_ssversion(&rel.ssversion,
2707 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2708 }
2709
Harald Welteaa0b29c2009-07-23 18:56:43 +02002710 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002711 /* release collision 5.4.5 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002712 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002713 } else {
Harald Welteb3c3fae2009-07-23 19:06:52 +02002714 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002715 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welteb3c3fae2009-07-23 19:06:52 +02002716 GSM48_MT_CC_RELEASE_COMPL);
2717 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002718 }
2719
2720 new_cc_state(trans, GSM_CSTATE_NULL);
2721
2722 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002723 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002724
2725 return rc;
2726}
2727
2728static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2729{
2730 struct gsm_mncc *rel = arg;
2731 struct msgb *msg = gsm48_msgb_alloc();
2732 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2733
Harald Welte4bfdfe72009-06-10 23:11:52 +08002734 gh->msg_type = GSM48_MT_CC_RELEASE;
2735
2736 trans->callref = 0;
2737
2738 gsm48_stop_cc_timer(trans);
2739 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2740
2741 /* cause */
2742 if (rel->fields & MNCC_F_CAUSE)
2743 encode_cause(msg, 0, &rel->cause);
2744 /* facility */
2745 if (rel->fields & MNCC_F_FACILITY)
2746 encode_facility(msg, 0, &rel->facility);
2747 /* user-user */
2748 if (rel->fields & MNCC_F_USERUSER)
2749 encode_useruser(msg, 0, &rel->useruser);
2750
Harald Welteaa0b29c2009-07-23 18:56:43 +02002751 trans->cc.T308_second = 0;
2752 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002753
Harald Welteaa0b29c2009-07-23 18:56:43 +02002754 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002755 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2756
Harald Welte39e2ead2009-07-23 21:13:03 +02002757 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002758}
2759
2760static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2761{
2762 struct gsm48_hdr *gh = msgb_l3(msg);
2763 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2764 struct tlv_parsed tp;
2765 struct gsm_mncc rel;
2766 int rc = 0;
2767
2768 gsm48_stop_cc_timer(trans);
2769
2770 memset(&rel, 0, sizeof(struct gsm_mncc));
2771 rel.callref = trans->callref;
2772 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2773 /* cause */
2774 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2775 rel.fields |= MNCC_F_CAUSE;
2776 decode_cause(&rel.cause,
2777 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2778 }
2779 /* facility */
2780 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2781 rel.fields |= MNCC_F_FACILITY;
2782 decode_facility(&rel.facility,
2783 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2784 }
2785 /* user-user */
2786 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2787 rel.fields |= MNCC_F_USERUSER;
2788 decode_useruser(&rel.useruser,
2789 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2790 }
2791 /* ss-version */
2792 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2793 rel.fields |= MNCC_F_SSVERSION;
2794 decode_ssversion(&rel.ssversion,
2795 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2796 }
2797
2798 if (trans->callref) {
Harald Welteaa0b29c2009-07-23 18:56:43 +02002799 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002800 case GSM_CSTATE_CALL_PRESENT:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002801 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002802 MNCC_REJ_IND, &rel);
2803 break;
2804 case GSM_CSTATE_RELEASE_REQ:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002805 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002806 MNCC_REL_CNF, &rel);
2807 break;
2808 default:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002809 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002810 MNCC_REL_IND, &rel);
2811 }
2812 }
2813
2814 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002815 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002816
2817 return rc;
2818}
2819
2820static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2821{
2822 struct gsm_mncc *rel = arg;
2823 struct msgb *msg = gsm48_msgb_alloc();
2824 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2825
Harald Welte4bfdfe72009-06-10 23:11:52 +08002826 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2827
2828 trans->callref = 0;
2829
2830 gsm48_stop_cc_timer(trans);
2831
2832 /* cause */
2833 if (rel->fields & MNCC_F_CAUSE)
2834 encode_cause(msg, 0, &rel->cause);
2835 /* facility */
2836 if (rel->fields & MNCC_F_FACILITY)
2837 encode_facility(msg, 0, &rel->facility);
2838 /* user-user */
2839 if (rel->fields & MNCC_F_USERUSER)
2840 encode_useruser(msg, 0, &rel->useruser);
2841
Harald Welteaa0b29c2009-07-23 18:56:43 +02002842 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002843
Harald Welte39e2ead2009-07-23 21:13:03 +02002844 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002845}
2846
2847static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2848{
2849 struct gsm48_hdr *gh = msgb_l3(msg);
2850 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2851 struct tlv_parsed tp;
2852 struct gsm_mncc fac;
2853
2854 memset(&fac, 0, sizeof(struct gsm_mncc));
2855 fac.callref = trans->callref;
2856 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2857 /* facility */
2858 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2859 fac.fields |= MNCC_F_FACILITY;
2860 decode_facility(&fac.facility,
2861 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2862 }
2863 /* ss-version */
2864 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2865 fac.fields |= MNCC_F_SSVERSION;
2866 decode_ssversion(&fac.ssversion,
2867 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2868 }
2869
Harald Welteb3c3fae2009-07-23 19:06:52 +02002870 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002871}
2872
2873static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2874{
2875 struct gsm_mncc *fac = arg;
2876 struct msgb *msg = gsm48_msgb_alloc();
2877 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2878
Harald Welte4bfdfe72009-06-10 23:11:52 +08002879 gh->msg_type = GSM48_MT_CC_FACILITY;
2880
2881 /* facility */
2882 encode_facility(msg, 1, &fac->facility);
2883
Harald Welte39e2ead2009-07-23 21:13:03 +02002884 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002885}
2886
2887static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2888{
2889 struct gsm_mncc hold;
2890
2891 memset(&hold, 0, sizeof(struct gsm_mncc));
2892 hold.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002893 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002894}
2895
2896static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2897{
2898 struct msgb *msg = gsm48_msgb_alloc();
2899 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2900
Harald Welte4bfdfe72009-06-10 23:11:52 +08002901 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2902
Harald Welte39e2ead2009-07-23 21:13:03 +02002903 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002904}
2905
2906static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2907{
2908 struct gsm_mncc *hold_rej = arg;
2909 struct msgb *msg = gsm48_msgb_alloc();
2910 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2911
Harald Welte4bfdfe72009-06-10 23:11:52 +08002912 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2913
2914 /* cause */
2915 if (hold_rej->fields & MNCC_F_CAUSE)
2916 encode_cause(msg, 1, &hold_rej->cause);
2917 else
2918 encode_cause(msg, 1, &default_cause);
2919
Harald Welte39e2ead2009-07-23 21:13:03 +02002920 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002921}
2922
2923static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2924{
2925 struct gsm_mncc retrieve;
2926
2927 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2928 retrieve.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002929 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2930 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002931}
2932
2933static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2934{
2935 struct msgb *msg = gsm48_msgb_alloc();
2936 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2937
Harald Welte4bfdfe72009-06-10 23:11:52 +08002938 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2939
Harald Welte39e2ead2009-07-23 21:13:03 +02002940 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002941}
2942
2943static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2944{
2945 struct gsm_mncc *retrieve_rej = arg;
2946 struct msgb *msg = gsm48_msgb_alloc();
2947 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2948
Harald Welte4bfdfe72009-06-10 23:11:52 +08002949 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2950
2951 /* cause */
2952 if (retrieve_rej->fields & MNCC_F_CAUSE)
2953 encode_cause(msg, 1, &retrieve_rej->cause);
2954 else
2955 encode_cause(msg, 1, &default_cause);
2956
Harald Welte39e2ead2009-07-23 21:13:03 +02002957 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002958}
2959
2960static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2961{
2962 struct gsm48_hdr *gh = msgb_l3(msg);
2963 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2964 struct tlv_parsed tp;
2965 struct gsm_mncc dtmf;
2966
2967 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2968 dtmf.callref = trans->callref;
2969 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2970 /* keypad facility */
2971 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
2972 dtmf.fields |= MNCC_F_KEYPAD;
2973 decode_keypad(&dtmf.keypad,
2974 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
2975 }
2976
Harald Welteb3c3fae2009-07-23 19:06:52 +02002977 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002978}
2979
2980static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
2981{
2982 struct gsm_mncc *dtmf = arg;
2983 struct msgb *msg = gsm48_msgb_alloc();
2984 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2985
Harald Welte4bfdfe72009-06-10 23:11:52 +08002986 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
2987
2988 /* keypad */
2989 if (dtmf->fields & MNCC_F_KEYPAD)
2990 encode_keypad(msg, dtmf->keypad);
2991
Harald Welte39e2ead2009-07-23 21:13:03 +02002992 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002993}
2994
2995static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
2996{
2997 struct gsm_mncc *dtmf = arg;
2998 struct msgb *msg = gsm48_msgb_alloc();
2999 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3000
Harald Welte4bfdfe72009-06-10 23:11:52 +08003001 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3002
3003 /* cause */
3004 if (dtmf->fields & MNCC_F_CAUSE)
3005 encode_cause(msg, 1, &dtmf->cause);
3006 else
3007 encode_cause(msg, 1, &default_cause);
3008
Harald Welte39e2ead2009-07-23 21:13:03 +02003009 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003010}
3011
3012static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3013{
3014 struct msgb *msg = gsm48_msgb_alloc();
3015 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3016
Harald Welte4bfdfe72009-06-10 23:11:52 +08003017 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3018
Harald Welte39e2ead2009-07-23 21:13:03 +02003019 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003020}
3021
3022static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3023{
3024 struct gsm_mncc dtmf;
3025
3026 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3027 dtmf.callref = trans->callref;
3028
Harald Welteb3c3fae2009-07-23 19:06:52 +02003029 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003030}
3031
3032static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3033{
3034 struct gsm48_hdr *gh = msgb_l3(msg);
3035 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3036 struct tlv_parsed tp;
3037 struct gsm_mncc modify;
3038
3039 memset(&modify, 0, sizeof(struct gsm_mncc));
3040 modify.callref = trans->callref;
3041 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3042 /* bearer capability */
3043 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3044 modify.fields |= MNCC_F_BEARER_CAP;
3045 decode_bearer_cap(&modify.bearer_cap,
3046 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3047 }
3048
3049 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3050
Harald Welteb3c3fae2009-07-23 19:06:52 +02003051 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003052}
3053
3054static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3055{
3056 struct gsm_mncc *modify = arg;
3057 struct msgb *msg = gsm48_msgb_alloc();
3058 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3059
Harald Welte4bfdfe72009-06-10 23:11:52 +08003060 gh->msg_type = GSM48_MT_CC_MODIFY;
3061
3062 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3063
3064 /* bearer capability */
3065 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3066
3067 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3068
Harald Welte39e2ead2009-07-23 21:13:03 +02003069 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003070}
3071
3072static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3073{
3074 struct gsm48_hdr *gh = msgb_l3(msg);
3075 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3076 struct tlv_parsed tp;
3077 struct gsm_mncc modify;
3078
3079 gsm48_stop_cc_timer(trans);
3080
3081 memset(&modify, 0, sizeof(struct gsm_mncc));
3082 modify.callref = trans->callref;
3083 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3084 /* bearer capability */
3085 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3086 modify.fields |= MNCC_F_BEARER_CAP;
3087 decode_bearer_cap(&modify.bearer_cap,
3088 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3089 }
3090
3091 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3092
Harald Welteb3c3fae2009-07-23 19:06:52 +02003093 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003094}
3095
3096static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3097{
3098 struct gsm_mncc *modify = arg;
3099 struct msgb *msg = gsm48_msgb_alloc();
3100 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3101
Harald Welte4bfdfe72009-06-10 23:11:52 +08003102 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3103
3104 /* bearer capability */
3105 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3106
3107 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3108
Harald Welte39e2ead2009-07-23 21:13:03 +02003109 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003110}
3111
3112static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3113{
3114 struct gsm48_hdr *gh = msgb_l3(msg);
3115 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3116 struct tlv_parsed tp;
3117 struct gsm_mncc modify;
3118
3119 gsm48_stop_cc_timer(trans);
3120
3121 memset(&modify, 0, sizeof(struct gsm_mncc));
3122 modify.callref = trans->callref;
3123 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3124 /* bearer capability */
3125 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3126 modify.fields |= GSM48_IE_BEARER_CAP;
3127 decode_bearer_cap(&modify.bearer_cap,
3128 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3129 }
3130 /* cause */
3131 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3132 modify.fields |= MNCC_F_CAUSE;
3133 decode_cause(&modify.cause,
3134 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3135 }
3136
3137 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3138
Harald Welteb3c3fae2009-07-23 19:06:52 +02003139 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003140}
3141
3142static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3143{
3144 struct gsm_mncc *modify = arg;
3145 struct msgb *msg = gsm48_msgb_alloc();
3146 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3147
Harald Welte4bfdfe72009-06-10 23:11:52 +08003148 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3149
3150 /* bearer capability */
3151 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3152 /* cause */
3153 encode_cause(msg, 1, &modify->cause);
3154
3155 new_cc_state(trans, GSM_CSTATE_ACTIVE);
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_tx_notify(struct gsm_trans *trans, void *arg)
3161{
3162 struct gsm_mncc *notify = arg;
3163 struct msgb *msg = gsm48_msgb_alloc();
3164 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3165
Harald Welte4bfdfe72009-06-10 23:11:52 +08003166 gh->msg_type = GSM48_MT_CC_NOTIFY;
3167
3168 /* notify */
3169 encode_notify(msg, notify->notify);
3170
Harald Welte39e2ead2009-07-23 21:13:03 +02003171 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003172}
3173
3174static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3175{
3176 struct gsm48_hdr *gh = msgb_l3(msg);
3177 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3178// struct tlv_parsed tp;
3179 struct gsm_mncc notify;
3180
3181 memset(&notify, 0, sizeof(struct gsm_mncc));
3182 notify.callref = trans->callref;
3183// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3184 if (payload_len >= 1)
3185 decode_notify(&notify.notify, gh->data);
3186
Harald Welteb3c3fae2009-07-23 19:06:52 +02003187 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003188}
3189
3190static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3191{
3192 struct gsm_mncc *user = arg;
3193 struct msgb *msg = gsm48_msgb_alloc();
3194 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3195
Harald Welte4bfdfe72009-06-10 23:11:52 +08003196 gh->msg_type = GSM48_MT_CC_USER_INFO;
3197
3198 /* user-user */
3199 if (user->fields & MNCC_F_USERUSER)
3200 encode_useruser(msg, 1, &user->useruser);
3201 /* more data */
3202 if (user->more)
3203 encode_more(msg);
3204
Harald Welte39e2ead2009-07-23 21:13:03 +02003205 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003206}
3207
3208static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3209{
3210 struct gsm48_hdr *gh = msgb_l3(msg);
3211 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3212 struct tlv_parsed tp;
3213 struct gsm_mncc user;
3214
3215 memset(&user, 0, sizeof(struct gsm_mncc));
3216 user.callref = trans->callref;
3217 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3218 /* user-user */
3219 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3220 user.fields |= MNCC_F_USERUSER;
3221 decode_useruser(&user.useruser,
3222 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3223 }
3224 /* more data */
3225 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3226 user.more = 1;
3227
Harald Welteb3c3fae2009-07-23 19:06:52 +02003228 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003229}
3230
3231static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3232{
3233 struct gsm_mncc *mode = arg;
3234
3235 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3236}
3237
3238static struct downstate {
3239 u_int32_t states;
3240 int type;
3241 int (*rout) (struct gsm_trans *trans, void *arg);
3242} downstatelist[] = {
3243 /* mobile originating call establishment */
3244 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3245 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3246 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3247 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3248 {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 */
3249 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3250 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3251 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3252 /* mobile terminating call establishment */
3253 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3254 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3255 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3256 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3257 /* signalling during call */
3258 {SBIT(GSM_CSTATE_ACTIVE),
3259 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3260 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3261 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3262 {ALL_STATES,
3263 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3264 {ALL_STATES,
3265 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3266 {ALL_STATES,
3267 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3268 {SBIT(GSM_CSTATE_ACTIVE),
3269 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3270 {SBIT(GSM_CSTATE_ACTIVE),
3271 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3272 {SBIT(GSM_CSTATE_ACTIVE),
3273 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3274 {SBIT(GSM_CSTATE_ACTIVE),
3275 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3276 {SBIT(GSM_CSTATE_ACTIVE),
3277 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3278 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3279 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3280 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3281 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3282 {SBIT(GSM_CSTATE_ACTIVE),
3283 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3284 /* clearing */
3285 {SBIT(GSM_CSTATE_INITIATED),
3286 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3287 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3288 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3289 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3290 MNCC_REL_REQ, gsm48_cc_tx_release},
3291 /* special */
3292 {ALL_STATES,
3293 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3294};
3295
3296#define DOWNSLLEN \
3297 (sizeof(downstatelist) / sizeof(struct downstate))
3298
3299
3300int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3301{
3302 int i, j, k, l, rc = 0;
3303 struct gsm_trans *trans = NULL, *transt;
3304 struct gsm_subscriber *subscr;
3305 struct gsm_lchan *lchan = NULL, *lchant;
3306 struct gsm_bts *bts = NULL;
3307 struct gsm_bts_trx *trx;
3308 struct gsm_bts_trx_ts *ts;
3309 struct gsm_mncc *data = arg, rel;
3310
3311 /* handle special messages */
3312 switch(msg_type) {
3313 case MNCC_BRIDGE:
3314 return tch_bridge(net, arg);
3315 case MNCC_FRAME_DROP:
3316 return tch_recv(net, arg, 0);
3317 case MNCC_FRAME_RECV:
3318 return tch_recv(net, arg, 1);
3319 case GSM_TRAU_FRAME:
3320 return tch_frame(net, arg);
3321 }
3322
3323 memset(&rel, 0, sizeof(struct gsm_mncc));
3324 rel.callref = data->callref;
3325
3326 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003327 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003328
3329 /* Callref unknown */
3330 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003331 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003332 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3333 "Received '%s' from MNCC with "
3334 "unknown callref %d\n", data->called.number,
3335 get_mncc_name(msg_type), data->callref);
3336 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003337 return mncc_release_ind(net, NULL, data->callref,
3338 GSM48_CAUSE_LOC_PRN_S_LU,
3339 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003340 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003341 if (!data->called.number[0] && !data->imsi[0]) {
3342 DEBUGP(DCC, "(bts - trx - ts - ti) "
3343 "Received '%s' from MNCC with "
3344 "no number or IMSI\n", get_mncc_name(msg_type));
3345 /* Invalid number */
3346 return mncc_release_ind(net, NULL, data->callref,
3347 GSM48_CAUSE_LOC_PRN_S_LU,
3348 GSM48_CC_CAUSE_INV_NR_FORMAT);
3349 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003350 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003351 if (data->called.number[0])
Harald Welte761e9442009-07-23 19:21:02 +02003352 subscr = subscr_get_by_extension(net,
3353 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003354 else
Harald Welte761e9442009-07-23 19:21:02 +02003355 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003356 /* If subscriber is not found */
3357 if (!subscr) {
3358 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3359 "Received '%s' from MNCC with "
3360 "unknown subscriber %s\n", data->called.number,
3361 get_mncc_name(msg_type), data->called.number);
3362 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003363 return mncc_release_ind(net, NULL, data->callref,
3364 GSM48_CAUSE_LOC_PRN_S_LU,
3365 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003366 }
3367 /* If subscriber is not "attached" */
3368 if (!subscr->lac) {
3369 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3370 "Received '%s' from MNCC with "
3371 "detached subscriber %s\n", data->called.number,
3372 get_mncc_name(msg_type), data->called.number);
3373 subscr_put(subscr);
3374 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003375 return mncc_release_ind(net, NULL, data->callref,
3376 GSM48_CAUSE_LOC_PRN_S_LU,
3377 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003378 }
3379 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003380 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3381 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003382 DEBUGP(DCC, "No memory for trans.\n");
3383 subscr_put(subscr);
3384 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003385 mncc_release_ind(net, NULL, data->callref,
3386 GSM48_CAUSE_LOC_PRN_S_LU,
3387 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003388 return -ENOMEM;
3389 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003390 /* Find lchan */
3391 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003392 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003393 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003394 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003395 for (k = 0; k < TRX_NR_TS; k++) {
3396 ts = &trx->ts[k];
3397 for (l = 0; l < TS_MAX_LCHAN; l++) {
3398 lchant = &ts->lchan[l];
3399 if (lchant->subscr == subscr) {
3400 lchan = lchant;
3401 break;
3402 }
3403 }
3404 }
3405 }
3406 }
3407
3408 /* If subscriber has no lchan */
3409 if (!lchan) {
3410 /* find transaction with this subscriber already paging */
3411 llist_for_each_entry(transt, &net->trans_list, entry) {
3412 /* Transaction of our lchan? */
3413 if (transt == trans ||
3414 transt->subscr != subscr)
3415 continue;
3416 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3417 "Received '%s' from MNCC with "
3418 "unallocated channel, paging already "
3419 "started.\n", bts->nr,
3420 data->called.number,
3421 get_mncc_name(msg_type));
3422 return 0;
3423 }
3424 /* store setup informations until paging was successfull */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003425 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08003426 /* start paging subscriber on all BTS with her location */
3427 subscr->net = net;
3428 bts = NULL;
3429 do {
3430 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3431 if (!bts)
3432 break;
3433 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3434 "Received '%s' from MNCC with "
3435 "unallocated channel, paging.\n",
3436 bts->nr, data->called.number,
3437 get_mncc_name(msg_type));
3438 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003439 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003440 setup_trig_pag_evt, subscr);
3441 } while (1);
3442 return 0;
3443 }
3444 /* Assign lchan */
3445 trans->lchan = lchan;
3446 use_lchan(lchan);
3447 }
3448 lchan = trans->lchan;
3449
3450 /* if paging did not respond yet */
3451 if (!lchan) {
3452 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3453 "Received '%s' from MNCC in paging state\n",
3454 (trans->subscr)?(trans->subscr->extension):"-",
3455 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003456 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3457 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003458 if (msg_type == MNCC_REL_REQ)
3459 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3460 else
3461 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3462 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003463 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003464 return rc;
3465 }
3466
3467 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3468 "Received '%s' from MNCC in state %d (%s)\n",
3469 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3470 trans->transaction_id,
3471 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003472 get_mncc_name(msg_type), trans->cc.state,
3473 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003474
3475 /* Find function for current state and message */
3476 for (i = 0; i < DOWNSLLEN; i++)
3477 if ((msg_type == downstatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003478 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003479 break;
3480 if (i == DOWNSLLEN) {
3481 DEBUGP(DCC, "Message unhandled at this state.\n");
3482 return 0;
3483 }
3484
3485 rc = downstatelist[i].rout(trans, arg);
3486
3487 return rc;
3488}
3489
3490
3491static struct datastate {
3492 u_int32_t states;
3493 int type;
3494 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3495} datastatelist[] = {
3496 /* mobile originating call establishment */
3497 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3498 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3499 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3500 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3501 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3502 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3503 /* mobile terminating call establishment */
3504 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3505 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3506 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3507 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3508 {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 */
3509 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3510 /* signalling during call */
3511 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3512 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3513 {SBIT(GSM_CSTATE_ACTIVE),
3514 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3515 {ALL_STATES,
3516 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3517 {ALL_STATES,
3518 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3519 {ALL_STATES,
3520 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3521 {SBIT(GSM_CSTATE_ACTIVE),
3522 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3523 {SBIT(GSM_CSTATE_ACTIVE),
3524 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3525 {SBIT(GSM_CSTATE_ACTIVE),
3526 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3527 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3528 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3529 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3530 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3531 {SBIT(GSM_CSTATE_ACTIVE),
3532 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3533 /* clearing */
3534 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3535 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3536 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3537 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3538 {ALL_STATES, /* 5.4.3.4 */
3539 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3540};
3541
3542#define DATASLLEN \
3543 (sizeof(datastatelist) / sizeof(struct datastate))
3544
Harald Welte4bc90a12008-12-27 16:32:52 +00003545static int gsm0408_rcv_cc(struct msgb *msg)
3546{
3547 struct gsm48_hdr *gh = msgb_l3(msg);
3548 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003549 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003550 struct gsm_lchan *lchan = msg->lchan;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003551 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003552 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003553
Harald Welte4bfdfe72009-06-10 23:11:52 +08003554 if (msg_type & 0x80) {
3555 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3556 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003557 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003558
3559 /* Find transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003560 trans = trans_find_by_id(lchan, transaction_id);
3561
Harald Welte6f5aee02009-07-23 21:21:14 +02003562 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003563 "Received '%s' from MS in state %d (%s)\n",
3564 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3565 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003566 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3567 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003568
3569 /* Create transaction */
3570 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003571 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003572 "creating new trans.\n", transaction_id);
3573 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003574 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3575 transaction_id, new_callref++);
3576 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003577 DEBUGP(DCC, "No memory for trans.\n");
3578 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003579 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003580 GSM48_MT_CC_RELEASE_COMPL);
3581 return -ENOMEM;
3582 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003583 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003584 trans->lchan = lchan;
3585 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003586 }
3587
3588 /* find function for current state and message */
3589 for (i = 0; i < DATASLLEN; i++)
3590 if ((msg_type == datastatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003591 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003592 break;
3593 if (i == DATASLLEN) {
3594 DEBUGP(DCC, "Message unhandled at this state.\n");
3595 return 0;
3596 }
3597
3598 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003599
3600 return rc;
3601}
3602
Harald Welte52b1f982008-12-23 20:25:15 +00003603/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3604int gsm0408_rcvmsg(struct msgb *msg)
3605{
3606 struct gsm48_hdr *gh = msgb_l3(msg);
3607 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003608 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003609
3610 switch (pdisc) {
3611 case GSM48_PDISC_CC:
3612 rc = gsm0408_rcv_cc(msg);
3613 break;
3614 case GSM48_PDISC_MM:
3615 rc = gsm0408_rcv_mm(msg);
3616 break;
3617 case GSM48_PDISC_RR:
3618 rc = gsm0408_rcv_rr(msg);
3619 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003620 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003621 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003622 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003623 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003624 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003625 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3626 pdisc);
3627 break;
3628 default:
3629 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3630 pdisc);
3631 break;
3632 }
3633
3634 return rc;
3635}
Harald Welte8470bf22008-12-25 23:28:35 +00003636
Harald Welte8470bf22008-12-25 23:28:35 +00003637/* Section 9.1.8 / Table 9.9 */
3638struct chreq {
3639 u_int8_t val;
3640 u_int8_t mask;
3641 enum chreq_type type;
3642};
3643
3644/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3645static const struct chreq chreq_type_neci1[] = {
3646 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3647 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3648 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3649 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3650 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3651 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3652 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3653 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3654 { 0x10, 0xf0, CHREQ_T_SDCCH },
3655 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3656 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3657 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3658};
3659
3660/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3661static const struct chreq chreq_type_neci0[] = {
3662 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3663 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3664 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3665 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3666 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3667 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3668 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3669 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3670};
3671
3672static const enum gsm_chan_t ctype_by_chreq[] = {
3673 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3674 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3675 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3676 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3677 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3678 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3679 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3680 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3681 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3682 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3683 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3684 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3685};
3686
Harald Weltee14a57c2008-12-29 04:08:28 +00003687static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3688 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3689 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3690 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3691 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3692 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3693 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3694 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3695 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3696 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3697 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3698 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3699 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3700};
3701
Harald Welte8470bf22008-12-25 23:28:35 +00003702enum gsm_chan_t get_ctype_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 ctype_by_chreq[chr->type];
3711 }
3712 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3713 return GSM_LCHAN_SDCCH;
3714}
Harald Weltee14a57c2008-12-29 04:08:28 +00003715
3716enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3717{
3718 int i;
3719 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3720
3721 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3722 const struct chreq *chr = &chreq_type_neci0[i];
3723 if ((ra & chr->mask) == chr->val)
3724 return reason_by_chreq[chr->type];
3725 }
3726 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3727 return GSM_CHREQ_REASON_OTHER;
3728}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003729
3730/* dequeue messages to layer 4 */
3731int bsc_upqueue(struct gsm_network *net)
3732{
3733 struct gsm_mncc *mncc;
3734 struct msgb *msg;
3735 int work = 0;
3736
3737 if (net)
3738 while ((msg = msgb_dequeue(&net->upqueue))) {
3739 mncc = (struct gsm_mncc *)msg->data;
3740 if (net->mncc_recv)
3741 net->mncc_recv(net, mncc->msg_type, mncc);
3742 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003743 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003744 }
3745
3746 return work;
3747}
Harald Welteaa0b29c2009-07-23 18:56:43 +02003748