blob: 507daf99803f2be152919c438b62bc1a82c8bb8c [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
Holger Freyther3e2c3232009-01-04 03:55:31 +0000986int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000987{
Harald Welte65e74cc2008-12-29 01:55:35 +0000988 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800989 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000990 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000991
Harald Welte4bfdfe72009-06-10 23:11:52 +0800992 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
993 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
994 "Sending '%s' to MS.\n", msg->trx->bts->nr,
995 msg->trx->nr, msg->lchan->ts->nr,
996 gh->proto_discr & 0xf0,
997 cc_msg_names[gh->msg_type & 0x3f]);
998 else
999 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1000 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1001 msg->trx->nr, msg->lchan->ts->nr,
1002 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001003 }
1004
Harald Welte4b634542008-12-27 01:55:51 +00001005 msg->l3h = msg->data;
1006
Harald Welte8470bf22008-12-25 23:28:35 +00001007 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001008}
1009
Holger Freyther429e7762008-12-30 13:28:30 +00001010/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001011int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001012{
Harald Welte8470bf22008-12-25 23:28:35 +00001013 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001014 struct gsm48_hdr *gh;
1015
Harald Welte8470bf22008-12-25 23:28:35 +00001016 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001017
1018 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1019 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001020 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001021 gh->data[0] = cause;
1022
Harald Weltedb253af2008-12-30 17:56:55 +00001023 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1024
Harald Welte65e74cc2008-12-29 01:55:35 +00001025 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001026}
1027
1028/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001029int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001030{
Harald Welte8470bf22008-12-25 23:28:35 +00001031 struct gsm_bts *bts = lchan->ts->trx->bts;
1032 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001033 struct gsm48_hdr *gh;
1034 struct gsm48_loc_area_id *lai;
1035 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001036 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001037
Harald Welte8470bf22008-12-25 23:28:35 +00001038 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001039
1040 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1041 gh->proto_discr = GSM48_PDISC_MM;
1042 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1043
1044 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001045 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001046 bts->network->network_code, bts->location_area_code);
1047
1048 mid = msgb_put(msg, MID_TMSI_LEN);
1049 generate_mid_from_tmsi(mid, tmsi);
1050
1051 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1052
Harald Weltedb253af2008-12-30 17:56:55 +00001053 ret = gsm48_sendmsg(msg);
1054
Harald Weltedb253af2008-12-30 17:56:55 +00001055 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001056
Holger Freyther07cc8d82008-12-29 06:23:46 +00001057 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001058}
1059
Harald Weltefc977a82008-12-27 10:19:37 +00001060static char bcd2char(u_int8_t bcd)
1061{
1062 if (bcd < 0xa)
1063 return '0' + bcd;
1064 else
1065 return 'A' + (bcd - 0xa);
1066}
1067
Harald Weltebf5e8df2009-02-03 12:59:45 +00001068/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001069static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1070{
1071 int i;
1072 u_int8_t mi_type;
1073 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001074 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001075
1076 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1077
1078 switch (mi_type) {
1079 case GSM_MI_TYPE_NONE:
1080 break;
1081 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001082 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1083 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1084 memcpy(&tmsi, &mi[1], 4);
1085 tmsi = ntohl(tmsi);
1086 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001087 }
1088 break;
1089 case GSM_MI_TYPE_IMSI:
1090 case GSM_MI_TYPE_IMEI:
1091 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001092 *str_cur++ = bcd2char(mi[0] >> 4);
1093
1094 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001095 if (str_cur + 2 >= string + str_len)
1096 return str_cur - string;
1097 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001098 /* skip last nibble in last input byte when GSM_EVEN */
1099 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1100 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001101 }
1102 break;
1103 default:
1104 break;
1105 }
Harald Weltefc977a82008-12-27 10:19:37 +00001106 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001107
Harald Weltefc977a82008-12-27 10:19:37 +00001108 return str_cur - string;
1109}
1110
Harald Weltebf5e8df2009-02-03 12:59:45 +00001111/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001112static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1113{
1114 struct msgb *msg = gsm48_msgb_alloc();
1115 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001116
Harald Welte231ad4f2008-12-27 11:15:38 +00001117 msg->lchan = lchan;
1118
1119 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1120 gh->proto_discr = GSM48_PDISC_MM;
1121 gh->msg_type = GSM48_MT_MM_ID_REQ;
1122 gh->data[0] = id_type;
1123
Harald Welte65e74cc2008-12-29 01:55:35 +00001124 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001125}
1126
1127#define MI_SIZE 32
1128
Harald Weltebf5e8df2009-02-03 12:59:45 +00001129/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001130static int mm_rx_id_resp(struct msgb *msg)
1131{
1132 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001133 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001134 struct gsm_bts *bts = lchan->ts->trx->bts;
1135 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001136 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1137 char mi_string[MI_SIZE];
1138
1139 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001140 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001141 mi_type, mi_string);
1142
Harald Welte75a983f2008-12-27 21:34:06 +00001143 switch (mi_type) {
1144 case GSM_MI_TYPE_IMSI:
1145 if (!lchan->subscr)
Harald Welte761e9442009-07-23 19:21:02 +02001146 lchan->subscr = db_create_subscriber(net, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001147 if (lchan->loc_operation)
1148 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001149 break;
1150 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001151 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001152 /* update subscribe <-> IMEI mapping */
1153 if (lchan->subscr)
1154 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001155 if (lchan->loc_operation)
1156 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001157 break;
1158 }
Holger Freyther73487a22008-12-31 18:53:57 +00001159
1160 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001161 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001162}
1163
Harald Welte255539c2008-12-28 02:26:27 +00001164
1165static void loc_upd_rej_cb(void *data)
1166{
1167 struct gsm_lchan *lchan = data;
1168
Holger Freyther73487a22008-12-31 18:53:57 +00001169 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001170 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001171 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001172}
1173
Holger Freytherb7193e42008-12-29 17:44:08 +00001174static void schedule_reject(struct gsm_lchan *lchan)
1175{
Holger Freyther73487a22008-12-31 18:53:57 +00001176 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1177 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001178 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001179}
1180
Harald Welte2a139372009-02-22 21:14:55 +00001181static const char *lupd_name(u_int8_t type)
1182{
1183 switch (type) {
1184 case GSM48_LUPD_NORMAL:
1185 return "NORMAL";
1186 case GSM48_LUPD_PERIODIC:
1187 return "PEROIDOC";
1188 case GSM48_LUPD_IMSI_ATT:
1189 return "IMSI ATTACH";
1190 default:
1191 return "UNKNOWN";
1192 }
1193}
1194
Harald Welte231ad4f2008-12-27 11:15:38 +00001195#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001196/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001197static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001198{
Harald Welte8470bf22008-12-25 23:28:35 +00001199 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001200 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001201 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001202 struct gsm_lchan *lchan = msg->lchan;
Harald Welte761e9442009-07-23 19:21:02 +02001203 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001204 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001205 char mi_string[MI_SIZE];
1206 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001207
Harald Welte8470bf22008-12-25 23:28:35 +00001208 lu = (struct gsm48_loc_upd_req *) gh->data;
1209
1210 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001211
Harald Weltefc977a82008-12-27 10:19:37 +00001212 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1213
Harald Weltea0368542009-06-27 02:58:43 +02001214 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001215 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001216
Holger Freythereaf04692009-06-06 13:54:44 +00001217 /*
1218 * Pseudo Spoof detection: Just drop a second/concurrent
1219 * location updating request.
1220 */
1221 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001222 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001223 lchan->loc_operation);
1224 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1225 return 0;
1226 }
1227
Holger Freyther73487a22008-12-31 18:53:57 +00001228 allocate_loc_updating_req(lchan);
1229
Harald Welte52b1f982008-12-23 20:25:15 +00001230 switch (mi_type) {
1231 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001232 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001233 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001234 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001235 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001236
Harald Welte52b1f982008-12-23 20:25:15 +00001237 /* look up subscriber based on IMSI */
Harald Welte761e9442009-07-23 19:21:02 +02001238 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001239 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001240 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001241 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001242 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001243 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001244 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001245
Harald Welte52b1f982008-12-23 20:25:15 +00001246 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte761e9442009-07-23 19:21:02 +02001247 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001248 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001249 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001250 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001251 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001252 }
1253 break;
1254 case GSM_MI_TYPE_IMEI:
1255 case GSM_MI_TYPE_IMEISV:
1256 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001257 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001258 break;
1259 default:
Harald Weltea0368542009-06-27 02:58:43 +02001260 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001261 break;
1262 }
1263
Harald Welte24516ea2009-07-04 10:18:00 +02001264 /* schedule the reject timer */
1265 schedule_reject(lchan);
1266
Harald Welte4bfdfe72009-06-10 23:11:52 +08001267 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001268 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001269 /* FIXME: request id? close channel? */
1270 return -EINVAL;
1271 }
1272
Harald Welte255539c2008-12-28 02:26:27 +00001273 lchan->subscr = subscr;
1274
Harald Welte24516ea2009-07-04 10:18:00 +02001275 /* check if we can let the subscriber into our network immediately
1276 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001277 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001278}
1279
Harald Welte7584aea2009-02-11 11:44:12 +00001280/* 9.1.5 Channel mode modify */
1281int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1282{
1283 struct msgb *msg = gsm48_msgb_alloc();
1284 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1285 struct gsm48_chan_mode_modify *cmm =
1286 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001287 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001288
Harald Welte4a543e82009-02-28 13:17:55 +00001289 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001290
Harald Welte45b407a2009-05-23 15:51:12 +00001291 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001292 msg->lchan = lchan;
1293 gh->proto_discr = GSM48_PDISC_RR;
1294 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1295
1296 /* fill the channel information element, this code
1297 * should probably be shared with rsl_rx_chan_rqd() */
1298 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001299 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001300 cmm->chan_desc.h0.h = 0;
1301 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1302 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1303 cmm->mode = mode;
1304
1305 return gsm48_sendmsg(msg);
1306}
1307
Harald Welte4bfdfe72009-06-10 23:11:52 +08001308#if 0
1309static u_int8_t to_bcd8(u_int8_t val)
1310{
1311 return ((val / 10) << 4) | (val % 10);
1312}
1313#endif
1314
Harald Weltedb253af2008-12-30 17:56:55 +00001315/* Section 9.2.15a */
1316int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1317{
1318 struct msgb *msg = gsm48_msgb_alloc();
1319 struct gsm48_hdr *gh;
1320 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001321 u_int8_t *ptr8;
1322 u_int16_t *ptr16;
1323 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001324 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001325#if 0
1326 time_t cur_t;
1327 struct tm* cur_time;
1328 int tz15min;
1329#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001330
1331 msg->lchan = lchan;
1332
1333 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1334 gh->proto_discr = GSM48_PDISC_MM;
1335 gh->msg_type = GSM48_MT_MM_INFO;
1336
1337 if (net->name_long) {
1338 name_len = strlen(net->name_long);
1339 /* 10.5.3.5a */
1340 ptr8 = msgb_put(msg, 3);
1341 ptr8[0] = GSM48_IE_NAME_LONG;
1342 ptr8[1] = name_len*2 +1;
1343 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1344
1345 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1346 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001347 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001348
1349 /* FIXME: Use Cell Broadcast, not UCS-2, since
1350 * UCS-2 is only supported by later revisions of the spec */
1351 }
1352
1353 if (net->name_short) {
1354 name_len = strlen(net->name_short);
1355 /* 10.5.3.5a */
1356 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001357 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001358 ptr8[1] = name_len*2 + 1;
1359 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1360
Harald Weltee872cb12009-01-01 00:33:37 +00001361 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001362 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001363 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001364 }
1365
1366#if 0
1367 /* Section 10.5.3.9 */
1368 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001369 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001370 ptr8 = msgb_put(msg, 8);
1371 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1372 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1373 ptr8[2] = to_bcd8(cur_time->tm_mon);
1374 ptr8[3] = to_bcd8(cur_time->tm_mday);
1375 ptr8[4] = to_bcd8(cur_time->tm_hour);
1376 ptr8[5] = to_bcd8(cur_time->tm_min);
1377 ptr8[6] = to_bcd8(cur_time->tm_sec);
1378 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1379 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001380 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001381 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001382 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001383#endif
1384
1385 return gsm48_sendmsg(msg);
1386}
1387
Harald Welte4b634542008-12-27 01:55:51 +00001388static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1389{
Harald Welte4b634542008-12-27 01:55:51 +00001390 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001391 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001392}
Harald Welteba4cf162009-01-10 01:49:35 +00001393
1394/* 9.2.6 CM service reject */
1395static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1396 enum gsm48_reject_value value)
1397{
1398 struct msgb *msg = gsm48_msgb_alloc();
1399 struct gsm48_hdr *gh;
1400
1401 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1402
1403 msg->lchan = lchan;
1404 use_lchan(lchan);
1405
1406 gh->proto_discr = GSM48_PDISC_MM;
1407 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1408 gh->data[0] = value;
1409 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1410
1411 return gsm48_sendmsg(msg);
1412}
1413
Harald Welte4ed0e922009-01-10 03:17:30 +00001414
1415/*
1416 * Handle CM Service Requests
1417 * a) Verify that the packet is long enough to contain the information
1418 * we require otherwsie reject with INCORRECT_MESSAGE
1419 * b) Try to parse the TMSI. If we do not have one reject
1420 * c) Check that we know the subscriber with the TMSI otherwise reject
1421 * with a HLR cause
1422 * d) Set the subscriber on the gsm_lchan and accept
1423 */
Harald Welte4b634542008-12-27 01:55:51 +00001424static int gsm48_rx_mm_serv_req(struct msgb *msg)
1425{
Harald Welteba4cf162009-01-10 01:49:35 +00001426 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001427 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001428
Harald Welte761e9442009-07-23 19:21:02 +02001429 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001430 struct gsm_subscriber *subscr;
1431 struct gsm48_hdr *gh = msgb_l3(msg);
1432 struct gsm48_service_request *req =
1433 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001434 /* unfortunately in Phase1 the classmar2 length is variable */
1435 u_int8_t classmark2_len = gh->data[1];
1436 u_int8_t *classmark2 = gh->data+2;
1437 u_int8_t mi_len = *(classmark2 + classmark2_len);
1438 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001439
Harald Weltec9e02182009-05-01 19:07:53 +00001440 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001441 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001442 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001443 return gsm48_tx_mm_serv_rej(msg->lchan,
1444 GSM48_REJECT_INCORRECT_MESSAGE);
1445 }
1446
1447 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001448 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001449 return gsm48_tx_mm_serv_rej(msg->lchan,
1450 GSM48_REJECT_INCORRECT_MESSAGE);
1451 }
1452
Harald Weltec9e02182009-05-01 19:07:53 +00001453 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001454 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001455 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001456 return gsm48_tx_mm_serv_rej(msg->lchan,
1457 GSM48_REJECT_INCORRECT_MESSAGE);
1458 }
1459
Harald Weltec9e02182009-05-01 19:07:53 +00001460 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001461 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001462 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001463
Harald Welte761e9442009-07-23 19:21:02 +02001464 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001465
Harald Welte2a139372009-02-22 21:14:55 +00001466 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001467 if (!subscr)
1468 return gsm48_tx_mm_serv_rej(msg->lchan,
1469 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1470
1471 if (!msg->lchan->subscr)
1472 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001473 else if (msg->lchan->subscr != subscr) {
1474 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1475 subscr_put(subscr);
1476 }
1477
Harald Weltec2e302d2009-07-05 14:08:13 +02001478 subscr->equipment.classmark2_len = classmark2_len;
1479 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1480 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001481
Harald Welte4b634542008-12-27 01:55:51 +00001482 return gsm48_tx_mm_serv_ack(msg->lchan);
1483}
1484
Harald Welte2a139372009-02-22 21:14:55 +00001485static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1486{
Harald Welte761e9442009-07-23 19:21:02 +02001487 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001488 struct gsm48_hdr *gh = msgb_l3(msg);
1489 struct gsm48_imsi_detach_ind *idi =
1490 (struct gsm48_imsi_detach_ind *) gh->data;
1491 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1492 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001493 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001494
1495 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1496 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1497 mi_type, mi_string);
1498
1499 switch (mi_type) {
1500 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001501 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001502 break;
1503 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001504 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001505 break;
1506 case GSM_MI_TYPE_IMEI:
1507 case GSM_MI_TYPE_IMEISV:
1508 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001509 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001510 break;
1511 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001512 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001513 break;
1514 }
1515
Holger Freyther4a49e772009-04-12 05:37:29 +00001516 if (subscr) {
1517 subscr_update(subscr, msg->trx->bts,
1518 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001519 DEBUGP(DMM, "Subscriber: %s\n",
1520 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001521 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001522 } else
Harald Welte2a139372009-02-22 21:14:55 +00001523 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1524
Harald Welte2a139372009-02-22 21:14:55 +00001525 return 0;
1526}
1527
Harald Welted2a7f5a2009-06-05 20:08:20 +00001528static int gsm48_rx_mm_status(struct msgb *msg)
1529{
1530 struct gsm48_hdr *gh = msgb_l3(msg);
1531
1532 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1533
1534 return 0;
1535}
1536
Harald Weltebf5e8df2009-02-03 12:59:45 +00001537/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001538static int gsm0408_rcv_mm(struct msgb *msg)
1539{
1540 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001541 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001542
1543 switch (gh->msg_type & 0xbf) {
1544 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001545 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001546 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001547 break;
1548 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001549 rc = mm_rx_id_resp(msg);
1550 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001551 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001552 rc = gsm48_rx_mm_serv_req(msg);
1553 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001554 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001555 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001556 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001557 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001558 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1559 msg->lchan->subscr ?
1560 msg->lchan->subscr->imsi :
1561 "unknown subscriber");
1562 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001563 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001564 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1565 break;
1566 case GSM48_MT_MM_CM_REEST_REQ:
1567 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1568 break;
1569 case GSM48_MT_MM_AUTH_RESP:
1570 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001571 break;
1572 default:
1573 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1574 gh->msg_type);
1575 break;
1576 }
1577
1578 return rc;
1579}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001580
Harald Welte2d35ae62009-02-06 12:02:13 +00001581/* Receive a PAGING RESPONSE message from the MS */
1582static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1583{
Harald Welte761e9442009-07-23 19:21:02 +02001584 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001585 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001586 u_int8_t *classmark2_lv = gh->data + 1;
1587 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1588 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001589 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001590 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001591 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001592 int rc = 0;
1593
Harald Welte61548982009-02-22 21:26:29 +00001594 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001595 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1596 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001597 switch (mi_type) {
1598 case GSM_MI_TYPE_TMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001599 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001600 break;
1601 case GSM_MI_TYPE_IMSI:
Harald Welte761e9442009-07-23 19:21:02 +02001602 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001603 break;
1604 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001605
1606 if (!subscr) {
1607 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001608 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001609 return -EINVAL;
1610 }
1611 DEBUGP(DRR, "<- Channel was requested by %s\n",
1612 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001613
Harald Weltec2e302d2009-07-05 14:08:13 +02001614 subscr->equipment.classmark2_len = *classmark2_lv;
1615 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1616 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001617
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001618 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001619 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001620 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001621 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1622 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001623 return -EINVAL;
1624 } else {
1625 DEBUGP(DRR, "<- Channel already owned by us\n");
1626 subscr_put(subscr);
1627 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001628 }
1629
Harald Welte595ad7b2009-02-16 22:05:44 +00001630 sig_data.subscr = subscr;
1631 sig_data.bts = msg->lchan->ts->trx->bts;
1632 sig_data.lchan = msg->lchan;
1633
1634 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001635
1636 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001637 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001638
Harald Welte7584aea2009-02-11 11:44:12 +00001639 /* FIXME: somehow signal the completion of the PAGING to
1640 * the entity that requested the paging */
1641
Harald Welte2d35ae62009-02-06 12:02:13 +00001642 return rc;
1643}
1644
Harald Weltef7c43522009-06-09 20:24:21 +00001645static int gsm48_rx_rr_classmark(struct msgb *msg)
1646{
1647 struct gsm48_hdr *gh = msgb_l3(msg);
1648 struct gsm_subscriber *subscr = msg->lchan->subscr;
1649 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1650 u_int8_t cm2_len, cm3_len = 0;
1651 u_int8_t *cm2, *cm3 = NULL;
1652
1653 DEBUGP(DRR, "CLASSMARK CHANGE ");
1654
1655 /* classmark 2 */
1656 cm2_len = gh->data[0];
1657 cm2 = &gh->data[1];
1658 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1659
1660 if (payload_len > cm2_len + 1) {
1661 /* we must have a classmark3 */
1662 if (gh->data[cm2_len+1] != 0x20) {
1663 DEBUGPC(DRR, "ERR CM3 TAG\n");
1664 return -EINVAL;
1665 }
1666 if (cm2_len > 3) {
1667 DEBUGPC(DRR, "CM2 too long!\n");
1668 return -EINVAL;
1669 }
1670
1671 cm3_len = gh->data[cm2_len+2];
1672 cm3 = &gh->data[cm2_len+3];
1673 if (cm3_len > 14) {
1674 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1675 return -EINVAL;
1676 }
1677 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1678 }
1679 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001680 subscr->equipment.classmark2_len = cm2_len;
1681 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001682 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001683 subscr->equipment.classmark3_len = cm3_len;
1684 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001685 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001686 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001687 }
1688
Harald Weltef7c43522009-06-09 20:24:21 +00001689 return 0;
1690}
1691
Harald Weltecf5b3592009-05-01 18:28:42 +00001692static int gsm48_rx_rr_status(struct msgb *msg)
1693{
1694 struct gsm48_hdr *gh = msgb_l3(msg);
1695
1696 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1697 rr_cause_name(gh->data[0]));
1698
1699 return 0;
1700}
1701
Harald Weltef7c43522009-06-09 20:24:21 +00001702static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1703{
1704 struct gsm48_hdr *gh = msgb_l3(msg);
1705 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1706 static struct gsm_meas_rep meas_rep;
1707
Harald Welte10d0e672009-06-27 02:53:10 +02001708 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001709 parse_meas_rep(&meas_rep, gh->data, payload_len);
1710 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001711 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001712 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001713 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001714 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001715 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001716 else
Harald Welte10d0e672009-06-27 02:53:10 +02001717 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001718 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1719 meas_rep.rxqual_sub);
1720
Harald Welte10d0e672009-06-27 02:53:10 +02001721 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001722
1723 /* FIXME: put the results somwhere */
1724
1725 return 0;
1726}
1727
Harald Weltebf5e8df2009-02-03 12:59:45 +00001728/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001729static int gsm0408_rcv_rr(struct msgb *msg)
1730{
1731 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001732 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001733
1734 switch (gh->msg_type) {
1735 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001736 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001737 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001738 case GSM48_MT_RR_GPRS_SUSP_REQ:
1739 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1740 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001741 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001742 rc = gsm48_rr_rx_pag_resp(msg);
1743 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001744 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1745 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001746 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001747 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001748 case GSM48_MT_RR_STATUS:
1749 rc = gsm48_rx_rr_status(msg);
1750 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001751 case GSM48_MT_RR_MEAS_REP:
1752 rc = gsm48_rx_rr_meas_rep(msg);
1753 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001754 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001755 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001756 gh->msg_type);
1757 break;
1758 }
1759
Harald Welte2d35ae62009-02-06 12:02:13 +00001760 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001761}
1762
Holger Freythere64a7a32009-02-06 21:55:37 +00001763/* 7.1.7 and 9.1.7 Channel release*/
1764int gsm48_send_rr_release(struct gsm_lchan *lchan)
1765{
1766 struct msgb *msg = gsm48_msgb_alloc();
1767 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1768 u_int8_t *cause;
1769
1770 msg->lchan = lchan;
1771 gh->proto_discr = GSM48_PDISC_RR;
1772 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1773
1774 cause = msgb_put(msg, 1);
1775 cause[0] = GSM48_RR_CAUSE_NORMAL;
1776
1777 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1778 lchan->nr, lchan->type);
1779
Harald Welteae0f2362009-07-19 18:36:49 +02001780 /* Send actual release request to MS */
1781 gsm48_sendmsg(msg);
1782
1783 /* Deactivate the SACCH on the BTS side */
1784 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001785}
1786
Harald Welte4bc90a12008-12-27 16:32:52 +00001787/* Call Control */
1788
Harald Welte7584aea2009-02-11 11:44:12 +00001789/* The entire call control code is written in accordance with Figure 7.10c
1790 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1791 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1792 * it for voice */
1793
Harald Welte4bfdfe72009-06-10 23:11:52 +08001794static void new_cc_state(struct gsm_trans *trans, int state)
1795{
1796 if (state > 31 || state < 0)
1797 return;
1798
1799 DEBUGP(DCC, "new state %s -> %s\n",
Harald Welteaa0b29c2009-07-23 18:56:43 +02001800 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001801
Harald Welteaa0b29c2009-07-23 18:56:43 +02001802 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001803}
1804
1805static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001806{
1807 struct msgb *msg = gsm48_msgb_alloc();
1808 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1809 u_int8_t *cause, *call_state;
1810
Harald Welte4bfdfe72009-06-10 23:11:52 +08001811 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1812 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001813 gh->msg_type = GSM48_MT_CC_STATUS;
1814
1815 cause = msgb_put(msg, 3);
1816 cause[0] = 2;
1817 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1818 cause[2] = 0x80 | 30; /* response to status inquiry */
1819
1820 call_state = msgb_put(msg, 1);
1821 call_state[0] = 0xc0 | 0x00;
1822
Harald Welte65e74cc2008-12-29 01:55:35 +00001823 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001824}
1825
Harald Welte6f4b7532008-12-29 00:39:37 +00001826static int gsm48_tx_simple(struct gsm_lchan *lchan,
1827 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001828{
1829 struct msgb *msg = gsm48_msgb_alloc();
1830 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1831
1832 msg->lchan = lchan;
1833
Harald Welte6f4b7532008-12-29 00:39:37 +00001834 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001835 gh->msg_type = msg_type;
1836
Harald Welte65e74cc2008-12-29 01:55:35 +00001837 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001838}
1839
Harald Welte4bfdfe72009-06-10 23:11:52 +08001840static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1841{
Harald Welteaa0b29c2009-07-23 18:56:43 +02001842 if (bsc_timer_pending(&trans->cc.timer)) {
1843 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1844 bsc_del_timer(&trans->cc.timer);
1845 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001846 }
1847}
1848
1849static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1850 int msg_type, struct gsm_mncc *mncc)
1851{
1852 struct msgb *msg;
1853
1854 if (trans)
1855 if (trans->lchan)
1856 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1857 "Sending '%s' to MNCC.\n",
1858 trans->lchan->ts->trx->bts->nr,
1859 trans->lchan->ts->trx->nr,
1860 trans->lchan->ts->nr, trans->transaction_id,
1861 (trans->subscr)?(trans->subscr->extension):"-",
1862 get_mncc_name(msg_type));
1863 else
1864 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1865 "Sending '%s' to MNCC.\n",
1866 (trans->subscr)?(trans->subscr->extension):"-",
1867 get_mncc_name(msg_type));
1868 else
1869 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1870 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1871
1872 mncc->msg_type = msg_type;
1873
Harald Welte966636f2009-06-26 19:39:35 +02001874 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001875 if (!msg)
1876 return -ENOMEM;
1877 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1878 msgb_enqueue(&net->upqueue, msg);
1879
1880 return 0;
1881}
1882
1883int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1884 u_int32_t callref, int location, int value)
1885{
1886 struct gsm_mncc rel;
1887
Harald Welte92f70c52009-06-12 01:54:08 +08001888 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001889 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001890 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001891 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1892}
1893
Harald Welteaa0b29c2009-07-23 18:56:43 +02001894/* Call Control Specific transaction release.
1895 * gets called by trans_free, DO NOT CALL YOURSELF! */
1896void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001897{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001898 gsm48_stop_cc_timer(trans);
1899
1900 /* send release to L4, if callref still exists */
1901 if (trans->callref) {
1902 /* Ressource unavailable */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001903 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001904 GSM48_CAUSE_LOC_PRN_S_LU,
1905 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001906 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02001907 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001908 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Welteaa0b29c2009-07-23 18:56:43 +02001909 if (trans->lchan)
1910 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001911}
1912
1913static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1914
Harald Welte09e38af2009-02-16 22:52:23 +00001915/* call-back from paging the B-end of the connection */
1916static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001917 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001918{
Harald Welte7ccf7782009-02-17 01:43:01 +00001919 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001920 struct gsm_subscriber *subscr = param;
1921 struct gsm_trans *transt, *tmp;
1922 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001923
Harald Welte09e38af2009-02-16 22:52:23 +00001924 if (hooknum != GSM_HOOK_RR_PAGING)
1925 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001926
1927 if (!subscr)
1928 return -EINVAL;
1929 net = subscr->net;
1930 if (!net) {
1931 DEBUGP(DCC, "Error Network not set!\n");
1932 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001933 }
Harald Welte7584aea2009-02-11 11:44:12 +00001934
Harald Welte4bfdfe72009-06-10 23:11:52 +08001935 /* check all tranactions (without lchan) for subscriber */
1936 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1937 if (transt->subscr != subscr || transt->lchan)
1938 continue;
1939 switch (event) {
1940 case GSM_PAGING_SUCCEEDED:
1941 if (!lchan) // paranoid
1942 break;
1943 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1944 subscr->extension);
1945 /* Assign lchan */
1946 if (!transt->lchan) {
1947 transt->lchan = lchan;
1948 use_lchan(lchan);
1949 }
1950 /* send SETUP request to called party */
Harald Welteaa0b29c2009-07-23 18:56:43 +02001951 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001952 if (is_ipaccess_bts(lchan->ts->trx->bts))
1953 rsl_ipacc_bind(lchan);
1954 break;
1955 case GSM_PAGING_EXPIRED:
1956 DEBUGP(DCC, "Paging subscr %s expired!\n",
1957 subscr->extension);
1958 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02001959 mncc_release_ind(transt->subscr->net, transt,
1960 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001961 GSM48_CAUSE_LOC_PRN_S_LU,
1962 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001963 transt->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02001964 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001965 break;
1966 }
1967 }
Harald Welte09e38af2009-02-16 22:52:23 +00001968 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001969}
Harald Welte7584aea2009-02-11 11:44:12 +00001970
Harald Welte49f48b82009-02-17 15:29:33 +00001971/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001972static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001973{
Harald Welte11fa29c2009-02-19 17:24:39 +00001974 struct gsm_bts *bts = lchan->ts->trx->bts;
1975 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001976 struct gsm_bts_trx_ts *ts;
1977
Harald Welte11fa29c2009-02-19 17:24:39 +00001978 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1979 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1980 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1981
1982 if (bts->type != remote_bts->type) {
1983 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1984 return -EINVAL;
1985 }
Harald Welte49f48b82009-02-17 15:29:33 +00001986
Harald Welte11fa29c2009-02-19 17:24:39 +00001987 switch (bts->type) {
1988 case GSM_BTS_TYPE_NANOBTS_900:
1989 case GSM_BTS_TYPE_NANOBTS_1800:
1990 ts = remote_lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02001991 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
1992 ts->abis_ip.bound_port,
1993 lchan->ts->abis_ip.conn_id,
1994 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00001995
1996 ts = lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02001997 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
1998 ts->abis_ip.bound_port,
1999 remote_lchan->ts->abis_ip.conn_id,
2000 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002001 break;
2002 case GSM_BTS_TYPE_BS11:
2003 trau_mux_map_lchan(lchan, remote_lchan);
2004 break;
2005 default:
2006 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2007 break;
2008 }
Harald Welte49f48b82009-02-17 15:29:33 +00002009
2010 return 0;
2011}
2012
Harald Welte4bfdfe72009-06-10 23:11:52 +08002013/* bridge channels of two transactions */
2014static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002015{
Harald Welteaa0b29c2009-07-23 18:56:43 +02002016 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2017 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002018
Harald Welte4bfdfe72009-06-10 23:11:52 +08002019 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002020 return -EIO;
2021
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022 if (!trans1->lchan || !trans2->lchan)
2023 return -EIO;
2024
2025 /* through-connect channel */
2026 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002027}
2028
Harald Welte4bfdfe72009-06-10 23:11:52 +08002029/* enable receive of channels to upqueue */
2030static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2031{
2032 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002033
Harald Welte4bfdfe72009-06-10 23:11:52 +08002034 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002035 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002036 if (!trans)
2037 return -EIO;
2038 if (!trans->lchan)
2039 return 0;
2040
2041 // todo IPACCESS
2042 if (enable)
2043 return trau_recv_lchan(trans->lchan, data->callref);
2044 return trau_mux_unmap(NULL, data->callref);
2045}
2046
2047/* send a frame to channel */
2048static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2049{
2050 struct gsm_trans *trans;
2051
2052 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002053 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002054 if (!trans)
2055 return -EIO;
2056 if (!trans->lchan)
2057 return 0;
2058 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2059 trans->lchan->type != GSM_LCHAN_TCH_H)
2060 return 0;
2061
2062 // todo IPACCESS
2063 return trau_send_lchan(trans->lchan,
2064 (struct decoded_trau_frame *)frame->data);
2065}
2066
2067
2068static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2069{
2070 DEBUGP(DCC, "-> STATUS ENQ\n");
2071 return gsm48_cc_tx_status(trans, msg);
2072}
2073
2074static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2075static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2076
2077static void gsm48_cc_timeout(void *arg)
2078{
2079 struct gsm_trans *trans = arg;
2080 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002081 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2082 int mo_location = GSM48_CAUSE_LOC_USER;
2083 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2084 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002085 struct gsm_mncc mo_rel, l4_rel;
2086
2087 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2088 mo_rel.callref = trans->callref;
2089 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2090 l4_rel.callref = trans->callref;
2091
Harald Welteaa0b29c2009-07-23 18:56:43 +02002092 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002093 case 0x303:
2094 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002095 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002096 break;
2097 case 0x310:
2098 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002099 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002100 break;
2101 case 0x313:
2102 disconnect = 1;
2103 /* unknown, did not find it in the specs */
2104 break;
2105 case 0x301:
2106 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002107 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002108 break;
2109 case 0x308:
Harald Welteaa0b29c2009-07-23 18:56:43 +02002110 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002111 /* restart T308 a second time */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002112 gsm48_cc_tx_release(trans, &trans->cc.msg);
2113 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002114 break; /* stay in release state */
2115 }
Harald Welteaa0b29c2009-07-23 18:56:43 +02002116 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002117 return;
2118// release = 1;
2119// l4_cause = 14;
2120// break;
2121 case 0x306:
2122 release = 1;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002123 mo_cause = trans->cc.msg.cause.value;
2124 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002125 break;
2126 case 0x323:
2127 disconnect = 1;
2128 break;
2129 default:
2130 release = 1;
2131 }
2132
2133 if (release && trans->callref) {
2134 /* process release towards layer 4 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002135 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002136 l4_location, l4_cause);
2137 trans->callref = 0;
2138 }
2139
2140 if (disconnect && trans->callref) {
2141 /* process disconnect towards layer 4 */
2142 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welteb3c3fae2009-07-23 19:06:52 +02002143 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002144 }
2145
2146 /* process disconnect towards mobile station */
2147 if (disconnect || release) {
2148 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002149 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2150 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2151 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002152 mo_rel.cause.diag_len = 3;
2153
2154 if (disconnect)
2155 gsm48_cc_tx_disconnect(trans, &mo_rel);
2156 if (release)
2157 gsm48_cc_tx_release(trans, &mo_rel);
2158 }
2159
2160}
2161
2162static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2163 int sec, int micro)
2164{
2165 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Welteaa0b29c2009-07-23 18:56:43 +02002166 trans->cc.timer.cb = gsm48_cc_timeout;
2167 trans->cc.timer.data = trans;
2168 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2169 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002170}
2171
2172static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2173{
2174 struct gsm48_hdr *gh = msgb_l3(msg);
2175 u_int8_t msg_type = gh->msg_type & 0xbf;
2176 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2177 struct tlv_parsed tp;
2178 struct gsm_mncc setup;
2179
2180 memset(&setup, 0, sizeof(struct gsm_mncc));
2181 setup.callref = trans->callref;
2182 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2183 /* emergency setup is identified by msg_type */
2184 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2185 setup.emergency = 1;
2186
2187 /* use subscriber as calling party number */
2188 if (trans->subscr) {
2189 setup.fields |= MNCC_F_CALLING;
2190 strncpy(setup.calling.number, trans->subscr->extension,
2191 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002192 strncpy(setup.imsi, trans->subscr->imsi,
2193 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002194 }
2195 /* bearer capability */
2196 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2197 setup.fields |= MNCC_F_BEARER_CAP;
2198 decode_bearer_cap(&setup.bearer_cap,
2199 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2200 }
2201 /* facility */
2202 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2203 setup.fields |= MNCC_F_FACILITY;
2204 decode_facility(&setup.facility,
2205 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2206 }
2207 /* called party bcd number */
2208 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2209 setup.fields |= MNCC_F_CALLED;
2210 decode_called(&setup.called,
2211 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2212 }
2213 /* user-user */
2214 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2215 setup.fields |= MNCC_F_USERUSER;
2216 decode_useruser(&setup.useruser,
2217 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2218 }
2219 /* ss-version */
2220 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2221 setup.fields |= MNCC_F_SSVERSION;
2222 decode_ssversion(&setup.ssversion,
2223 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2224 }
2225 /* CLIR suppression */
2226 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2227 setup.clir.sup = 1;
2228 /* CLIR invocation */
2229 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2230 setup.clir.inv = 1;
2231 /* cc cap */
2232 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2233 setup.fields |= MNCC_F_CCCAP;
2234 decode_cccap(&setup.cccap,
2235 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2236 }
2237
2238 if (is_ipaccess_bts(msg->trx->bts))
2239 rsl_ipacc_bind(msg->lchan);
2240
2241 new_cc_state(trans, GSM_CSTATE_INITIATED);
2242
2243 /* indicate setup to MNCC */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002244 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002245
2246 return 0;
2247}
2248
2249static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002250{
2251 struct msgb *msg = gsm48_msgb_alloc();
2252 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002253 struct gsm_mncc *setup = arg;
2254 struct gsm_trans *transt;
2255 u_int16_t trans_id_mask = 0;
2256 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002257
Harald Welte7ccf7782009-02-17 01:43:01 +00002258 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002259
Harald Welte4bfdfe72009-06-10 23:11:52 +08002260 /* transaction id must not be assigned */
2261 if (trans->transaction_id != 0xff) { /* unasssigned */
2262 DEBUGP(DCC, "TX Setup with assigned transaction. "
2263 "This is not allowed!\n");
2264 /* Temporarily out of order */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002265 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002266 GSM48_CAUSE_LOC_PRN_S_LU,
2267 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002268 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002269 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002270 return rc;
2271 }
2272
2273 /* Get free transaction_id */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002274 llist_for_each_entry(transt, &trans->subscr->net->trans_list, entry) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002275 /* Transaction of our lchan? */
2276 if (transt->lchan == trans->lchan &&
2277 transt->transaction_id != 0xff)
2278 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2279 }
2280 /* Assign free transaction ID */
2281 if ((trans_id_mask & 0x007f) == 0x7f) {
2282 /* no free transaction ID */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002283 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002284 GSM48_CAUSE_LOC_PRN_S_LU,
2285 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002286 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002287 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002288 return rc;
2289 }
2290 for (i = 0; i < 7; i++) {
2291 if ((trans_id_mask & (1 << i)) == 0) {
2292 trans->transaction_id = i << 4; /* flag = 0 */
2293 break;
2294 }
2295 }
Harald Welte49f48b82009-02-17 15:29:33 +00002296
Harald Welte4bfdfe72009-06-10 23:11:52 +08002297 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2298 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002299 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002300
Harald Welte4bfdfe72009-06-10 23:11:52 +08002301 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002302
Harald Welte4bfdfe72009-06-10 23:11:52 +08002303 /* bearer capability */
2304 if (setup->fields & MNCC_F_BEARER_CAP)
2305 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2306 /* facility */
2307 if (setup->fields & MNCC_F_FACILITY)
2308 encode_facility(msg, 0, &setup->facility);
2309 /* progress */
2310 if (setup->fields & MNCC_F_PROGRESS)
2311 encode_progress(msg, 0, &setup->progress);
2312 /* calling party BCD number */
2313 if (setup->fields & MNCC_F_CALLING)
2314 encode_calling(msg, &setup->calling);
2315 /* called party BCD number */
2316 if (setup->fields & MNCC_F_CALLED)
2317 encode_called(msg, &setup->called);
2318 /* user-user */
2319 if (setup->fields & MNCC_F_USERUSER)
2320 encode_useruser(msg, 0, &setup->useruser);
2321 /* redirecting party BCD number */
2322 if (setup->fields & MNCC_F_REDIRECTING)
2323 encode_redirecting(msg, &setup->redirecting);
2324 /* signal */
2325 if (setup->fields & MNCC_F_SIGNAL)
2326 encode_signal(msg, setup->signal);
2327
2328 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002329
2330 return gsm48_sendmsg(msg);
2331}
2332
Harald Welte4bfdfe72009-06-10 23:11:52 +08002333static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2334{
2335 struct gsm48_hdr *gh = msgb_l3(msg);
2336 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2337 struct tlv_parsed tp;
2338 struct gsm_mncc call_conf;
2339
2340 gsm48_stop_cc_timer(trans);
2341 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2342
2343 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2344 call_conf.callref = trans->callref;
2345 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2346#if 0
2347 /* repeat */
2348 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2349 call_conf.repeat = 1;
2350 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2351 call_conf.repeat = 2;
2352#endif
2353 /* bearer capability */
2354 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2355 call_conf.fields |= MNCC_F_BEARER_CAP;
2356 decode_bearer_cap(&call_conf.bearer_cap,
2357 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2358 }
2359 /* cause */
2360 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2361 call_conf.fields |= MNCC_F_CAUSE;
2362 decode_cause(&call_conf.cause,
2363 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2364 }
2365 /* cc cap */
2366 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2367 call_conf.fields |= MNCC_F_CCCAP;
2368 decode_cccap(&call_conf.cccap,
2369 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2370 }
2371
2372 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2373
Harald Welteb3c3fae2009-07-23 19:06:52 +02002374 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2375 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002376}
2377
2378static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2379{
2380 struct gsm_mncc *proceeding = arg;
2381 struct msgb *msg = gsm48_msgb_alloc();
2382 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2383
2384 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2385 msg->lchan = trans->lchan;
2386 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2387
2388 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2389
2390 /* bearer capability */
2391 if (proceeding->fields & MNCC_F_BEARER_CAP)
2392 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2393 /* facility */
2394 if (proceeding->fields & MNCC_F_FACILITY)
2395 encode_facility(msg, 0, &proceeding->facility);
2396 /* progress */
2397 if (proceeding->fields & MNCC_F_PROGRESS)
2398 encode_progress(msg, 0, &proceeding->progress);
2399
2400 return gsm48_sendmsg(msg);
2401}
2402
2403static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2404{
2405 struct gsm48_hdr *gh = msgb_l3(msg);
2406 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2407 struct tlv_parsed tp;
2408 struct gsm_mncc alerting;
2409
2410 gsm48_stop_cc_timer(trans);
2411 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2412
2413 memset(&alerting, 0, sizeof(struct gsm_mncc));
2414 alerting.callref = trans->callref;
2415 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2416 /* facility */
2417 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2418 alerting.fields |= MNCC_F_FACILITY;
2419 decode_facility(&alerting.facility,
2420 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2421 }
2422
2423 /* progress */
2424 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2425 alerting.fields |= MNCC_F_PROGRESS;
2426 decode_progress(&alerting.progress,
2427 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2428 }
2429 /* ss-version */
2430 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2431 alerting.fields |= MNCC_F_SSVERSION;
2432 decode_ssversion(&alerting.ssversion,
2433 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2434 }
2435
2436 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2437
Harald Welteb3c3fae2009-07-23 19:06:52 +02002438 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2439 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002440}
2441
2442static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2443{
2444 struct gsm_mncc *alerting = arg;
2445 struct msgb *msg = gsm48_msgb_alloc();
2446 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2447
2448 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2449 msg->lchan = trans->lchan;
2450 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
2464 return gsm48_sendmsg(msg);
2465}
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
2473 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2474 msg->lchan = trans->lchan;
2475 gh->msg_type = GSM48_MT_CC_PROGRESS;
2476
2477 /* progress */
2478 encode_progress(msg, 1, &progress->progress);
2479 /* user-user */
2480 if (progress->fields & MNCC_F_USERUSER)
2481 encode_useruser(msg, 0, &progress->useruser);
2482
2483 return gsm48_sendmsg(msg);
2484}
2485
2486static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2487{
2488 struct gsm_mncc *connect = arg;
2489 struct msgb *msg = gsm48_msgb_alloc();
2490 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2491
2492 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2493 msg->lchan = trans->lchan;
2494 gh->msg_type = GSM48_MT_CC_CONNECT;
2495
2496 gsm48_stop_cc_timer(trans);
2497 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2498
2499 /* facility */
2500 if (connect->fields & MNCC_F_FACILITY)
2501 encode_facility(msg, 0, &connect->facility);
2502 /* progress */
2503 if (connect->fields & MNCC_F_PROGRESS)
2504 encode_progress(msg, 0, &connect->progress);
2505 /* connected number */
2506 if (connect->fields & MNCC_F_CONNECTED)
2507 encode_connected(msg, &connect->connected);
2508 /* user-user */
2509 if (connect->fields & MNCC_F_USERUSER)
2510 encode_useruser(msg, 0, &connect->useruser);
2511
2512 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2513
2514 return gsm48_sendmsg(msg);
2515}
2516
2517static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2518{
2519 struct gsm48_hdr *gh = msgb_l3(msg);
2520 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2521 struct tlv_parsed tp;
2522 struct gsm_mncc connect;
2523
2524 gsm48_stop_cc_timer(trans);
2525
2526 memset(&connect, 0, sizeof(struct gsm_mncc));
2527 connect.callref = trans->callref;
2528 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2529 /* use subscriber as connected party number */
2530 if (trans->subscr) {
2531 connect.fields |= MNCC_F_CONNECTED;
2532 strncpy(connect.connected.number, trans->subscr->extension,
2533 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002534 strncpy(connect.imsi, trans->subscr->imsi,
2535 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002536 }
2537 /* facility */
2538 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2539 connect.fields |= MNCC_F_FACILITY;
2540 decode_facility(&connect.facility,
2541 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2542 }
2543 /* user-user */
2544 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2545 connect.fields |= MNCC_F_USERUSER;
2546 decode_useruser(&connect.useruser,
2547 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2548 }
2549 /* ss-version */
2550 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2551 connect.fields |= MNCC_F_SSVERSION;
2552 decode_ssversion(&connect.ssversion,
2553 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2554 }
2555
2556 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2557
Harald Welteb3c3fae2009-07-23 19:06:52 +02002558 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002559}
2560
2561
2562static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2563{
2564 struct gsm_mncc connect_ack;
2565
2566 gsm48_stop_cc_timer(trans);
2567
2568 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2569
2570 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2571 connect_ack.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002572 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002573 &connect_ack);
2574}
2575
2576static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2577{
2578 struct msgb *msg = gsm48_msgb_alloc();
2579 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2580
2581 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2582 msg->lchan = trans->lchan;
2583 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2584
2585 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2586
2587 return gsm48_sendmsg(msg);
2588}
2589
2590static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2591{
2592 struct gsm48_hdr *gh = msgb_l3(msg);
2593 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2594 struct tlv_parsed tp;
2595 struct gsm_mncc disc;
2596
2597 gsm48_stop_cc_timer(trans);
2598
2599 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2600
2601 memset(&disc, 0, sizeof(struct gsm_mncc));
2602 disc.callref = trans->callref;
2603 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2604 /* cause */
2605 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2606 disc.fields |= MNCC_F_CAUSE;
2607 decode_cause(&disc.cause,
2608 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2609 }
2610 /* facility */
2611 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2612 disc.fields |= MNCC_F_FACILITY;
2613 decode_facility(&disc.facility,
2614 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2615 }
2616 /* user-user */
2617 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2618 disc.fields |= MNCC_F_USERUSER;
2619 decode_useruser(&disc.useruser,
2620 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2621 }
2622 /* ss-version */
2623 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2624 disc.fields |= MNCC_F_SSVERSION;
2625 decode_ssversion(&disc.ssversion,
2626 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2627 }
2628
Harald Welteb3c3fae2009-07-23 19:06:52 +02002629 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002630
2631}
2632
Harald Weltec66b71c2009-06-11 14:23:20 +08002633static struct gsm_mncc_cause default_cause = {
2634 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2635 .coding = 0,
2636 .rec = 0,
2637 .rec_val = 0,
2638 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2639 .diag_len = 0,
2640 .diag = { 0 },
2641};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002642
2643static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2644{
2645 struct gsm_mncc *disc = arg;
2646 struct msgb *msg = gsm48_msgb_alloc();
2647 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2648
2649 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2650 msg->lchan = trans->lchan;
2651 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2652
2653 gsm48_stop_cc_timer(trans);
2654 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2655
2656 /* cause */
2657 if (disc->fields & MNCC_F_CAUSE)
2658 encode_cause(msg, 1, &disc->cause);
2659 else
2660 encode_cause(msg, 1, &default_cause);
2661
2662 /* facility */
2663 if (disc->fields & MNCC_F_FACILITY)
2664 encode_facility(msg, 0, &disc->facility);
2665 /* progress */
2666 if (disc->fields & MNCC_F_PROGRESS)
2667 encode_progress(msg, 0, &disc->progress);
2668 /* user-user */
2669 if (disc->fields & MNCC_F_USERUSER)
2670 encode_useruser(msg, 0, &disc->useruser);
2671
2672 /* store disconnect cause for T306 expiry */
Harald Welteaa0b29c2009-07-23 18:56:43 +02002673 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002674
2675 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2676
2677 return gsm48_sendmsg(msg);
2678}
2679
2680static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2681{
2682 struct gsm48_hdr *gh = msgb_l3(msg);
2683 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2684 struct tlv_parsed tp;
2685 struct gsm_mncc rel;
2686 int rc;
2687
2688 gsm48_stop_cc_timer(trans);
2689
2690 memset(&rel, 0, sizeof(struct gsm_mncc));
2691 rel.callref = trans->callref;
2692 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2693 /* cause */
2694 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2695 rel.fields |= MNCC_F_CAUSE;
2696 decode_cause(&rel.cause,
2697 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2698 }
2699 /* facility */
2700 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2701 rel.fields |= MNCC_F_FACILITY;
2702 decode_facility(&rel.facility,
2703 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2704 }
2705 /* user-user */
2706 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2707 rel.fields |= MNCC_F_USERUSER;
2708 decode_useruser(&rel.useruser,
2709 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2710 }
2711 /* ss-version */
2712 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2713 rel.fields |= MNCC_F_SSVERSION;
2714 decode_ssversion(&rel.ssversion,
2715 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2716 }
2717
Harald Welteaa0b29c2009-07-23 18:56:43 +02002718 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002719 /* release collision 5.4.5 */
Harald Welteb3c3fae2009-07-23 19:06:52 +02002720 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002721 } else {
Harald Welteb3c3fae2009-07-23 19:06:52 +02002722 rc = gsm48_tx_simple(msg->lchan,
2723 GSM48_PDISC_CC | trans->transaction_id,
2724 GSM48_MT_CC_RELEASE_COMPL);
2725 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002726 }
2727
2728 new_cc_state(trans, GSM_CSTATE_NULL);
2729
2730 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002731 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002732
2733 return rc;
2734}
2735
2736static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2737{
2738 struct gsm_mncc *rel = arg;
2739 struct msgb *msg = gsm48_msgb_alloc();
2740 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2741
2742 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2743 msg->lchan = trans->lchan;
2744 gh->msg_type = GSM48_MT_CC_RELEASE;
2745
2746 trans->callref = 0;
2747
2748 gsm48_stop_cc_timer(trans);
2749 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2750
2751 /* cause */
2752 if (rel->fields & MNCC_F_CAUSE)
2753 encode_cause(msg, 0, &rel->cause);
2754 /* facility */
2755 if (rel->fields & MNCC_F_FACILITY)
2756 encode_facility(msg, 0, &rel->facility);
2757 /* user-user */
2758 if (rel->fields & MNCC_F_USERUSER)
2759 encode_useruser(msg, 0, &rel->useruser);
2760
Harald Welteaa0b29c2009-07-23 18:56:43 +02002761 trans->cc.T308_second = 0;
2762 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002763
Harald Welteaa0b29c2009-07-23 18:56:43 +02002764 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002765 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2766
2767 return gsm48_sendmsg(msg);
2768}
2769
2770static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2771{
2772 struct gsm48_hdr *gh = msgb_l3(msg);
2773 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2774 struct tlv_parsed tp;
2775 struct gsm_mncc rel;
2776 int rc = 0;
2777
2778 gsm48_stop_cc_timer(trans);
2779
2780 memset(&rel, 0, sizeof(struct gsm_mncc));
2781 rel.callref = trans->callref;
2782 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2783 /* cause */
2784 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2785 rel.fields |= MNCC_F_CAUSE;
2786 decode_cause(&rel.cause,
2787 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2788 }
2789 /* facility */
2790 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2791 rel.fields |= MNCC_F_FACILITY;
2792 decode_facility(&rel.facility,
2793 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2794 }
2795 /* user-user */
2796 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2797 rel.fields |= MNCC_F_USERUSER;
2798 decode_useruser(&rel.useruser,
2799 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2800 }
2801 /* ss-version */
2802 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2803 rel.fields |= MNCC_F_SSVERSION;
2804 decode_ssversion(&rel.ssversion,
2805 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2806 }
2807
2808 if (trans->callref) {
Harald Welteaa0b29c2009-07-23 18:56:43 +02002809 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002810 case GSM_CSTATE_CALL_PRESENT:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002811 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002812 MNCC_REJ_IND, &rel);
2813 break;
2814 case GSM_CSTATE_RELEASE_REQ:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002815 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002816 MNCC_REL_CNF, &rel);
2817 break;
2818 default:
Harald Welteb3c3fae2009-07-23 19:06:52 +02002819 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002820 MNCC_REL_IND, &rel);
2821 }
2822 }
2823
2824 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02002825 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002826
2827 return rc;
2828}
2829
2830static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2831{
2832 struct gsm_mncc *rel = arg;
2833 struct msgb *msg = gsm48_msgb_alloc();
2834 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2835
2836 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2837 msg->lchan = trans->lchan;
2838 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2839
2840 trans->callref = 0;
2841
2842 gsm48_stop_cc_timer(trans);
2843
2844 /* cause */
2845 if (rel->fields & MNCC_F_CAUSE)
2846 encode_cause(msg, 0, &rel->cause);
2847 /* facility */
2848 if (rel->fields & MNCC_F_FACILITY)
2849 encode_facility(msg, 0, &rel->facility);
2850 /* user-user */
2851 if (rel->fields & MNCC_F_USERUSER)
2852 encode_useruser(msg, 0, &rel->useruser);
2853
Harald Welteaa0b29c2009-07-23 18:56:43 +02002854 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002855
2856 return gsm48_sendmsg(msg);
2857}
2858
2859static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2860{
2861 struct gsm48_hdr *gh = msgb_l3(msg);
2862 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2863 struct tlv_parsed tp;
2864 struct gsm_mncc fac;
2865
2866 memset(&fac, 0, sizeof(struct gsm_mncc));
2867 fac.callref = trans->callref;
2868 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2869 /* facility */
2870 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2871 fac.fields |= MNCC_F_FACILITY;
2872 decode_facility(&fac.facility,
2873 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2874 }
2875 /* ss-version */
2876 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2877 fac.fields |= MNCC_F_SSVERSION;
2878 decode_ssversion(&fac.ssversion,
2879 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2880 }
2881
Harald Welteb3c3fae2009-07-23 19:06:52 +02002882 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002883}
2884
2885static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2886{
2887 struct gsm_mncc *fac = arg;
2888 struct msgb *msg = gsm48_msgb_alloc();
2889 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2890
2891 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2892 msg->lchan = trans->lchan;
2893 gh->msg_type = GSM48_MT_CC_FACILITY;
2894
2895 /* facility */
2896 encode_facility(msg, 1, &fac->facility);
2897
2898 return gsm48_sendmsg(msg);
2899}
2900
2901static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2902{
2903 struct gsm_mncc hold;
2904
2905 memset(&hold, 0, sizeof(struct gsm_mncc));
2906 hold.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002907 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002908}
2909
2910static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2911{
2912 struct msgb *msg = gsm48_msgb_alloc();
2913 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2914
2915 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2916 msg->lchan = trans->lchan;
2917 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2918
2919 return gsm48_sendmsg(msg);
2920}
2921
2922static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2923{
2924 struct gsm_mncc *hold_rej = arg;
2925 struct msgb *msg = gsm48_msgb_alloc();
2926 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2927
2928 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2929 msg->lchan = trans->lchan;
2930 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2931
2932 /* cause */
2933 if (hold_rej->fields & MNCC_F_CAUSE)
2934 encode_cause(msg, 1, &hold_rej->cause);
2935 else
2936 encode_cause(msg, 1, &default_cause);
2937
2938 return gsm48_sendmsg(msg);
2939}
2940
2941static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2942{
2943 struct gsm_mncc retrieve;
2944
2945 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2946 retrieve.callref = trans->callref;
Harald Welteb3c3fae2009-07-23 19:06:52 +02002947 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2948 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002949}
2950
2951static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2952{
2953 struct msgb *msg = gsm48_msgb_alloc();
2954 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2955
2956 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2957 msg->lchan = trans->lchan;
2958 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2959
2960 return gsm48_sendmsg(msg);
2961}
2962
2963static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2964{
2965 struct gsm_mncc *retrieve_rej = arg;
2966 struct msgb *msg = gsm48_msgb_alloc();
2967 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2968
2969 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2970 msg->lchan = trans->lchan;
2971 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2972
2973 /* cause */
2974 if (retrieve_rej->fields & MNCC_F_CAUSE)
2975 encode_cause(msg, 1, &retrieve_rej->cause);
2976 else
2977 encode_cause(msg, 1, &default_cause);
2978
2979 return gsm48_sendmsg(msg);
2980}
2981
2982static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2983{
2984 struct gsm48_hdr *gh = msgb_l3(msg);
2985 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2986 struct tlv_parsed tp;
2987 struct gsm_mncc dtmf;
2988
2989 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2990 dtmf.callref = trans->callref;
2991 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2992 /* keypad facility */
2993 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
2994 dtmf.fields |= MNCC_F_KEYPAD;
2995 decode_keypad(&dtmf.keypad,
2996 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
2997 }
2998
Harald Welteb3c3fae2009-07-23 19:06:52 +02002999 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003000}
3001
3002static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3003{
3004 struct gsm_mncc *dtmf = arg;
3005 struct msgb *msg = gsm48_msgb_alloc();
3006 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3007
3008 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3009 msg->lchan = trans->lchan;
3010 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3011
3012 /* keypad */
3013 if (dtmf->fields & MNCC_F_KEYPAD)
3014 encode_keypad(msg, dtmf->keypad);
3015
3016 return gsm48_sendmsg(msg);
3017}
3018
3019static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3020{
3021 struct gsm_mncc *dtmf = arg;
3022 struct msgb *msg = gsm48_msgb_alloc();
3023 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3024
3025 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3026 msg->lchan = trans->lchan;
3027 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3028
3029 /* cause */
3030 if (dtmf->fields & MNCC_F_CAUSE)
3031 encode_cause(msg, 1, &dtmf->cause);
3032 else
3033 encode_cause(msg, 1, &default_cause);
3034
3035 return gsm48_sendmsg(msg);
3036}
3037
3038static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3039{
3040 struct msgb *msg = gsm48_msgb_alloc();
3041 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3042
3043 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3044 msg->lchan = trans->lchan;
3045 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3046
3047 return gsm48_sendmsg(msg);
3048}
3049
3050static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3051{
3052 struct gsm_mncc dtmf;
3053
3054 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3055 dtmf.callref = trans->callref;
3056
Harald Welteb3c3fae2009-07-23 19:06:52 +02003057 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003058}
3059
3060static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3061{
3062 struct gsm48_hdr *gh = msgb_l3(msg);
3063 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3064 struct tlv_parsed tp;
3065 struct gsm_mncc modify;
3066
3067 memset(&modify, 0, sizeof(struct gsm_mncc));
3068 modify.callref = trans->callref;
3069 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3070 /* bearer capability */
3071 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3072 modify.fields |= MNCC_F_BEARER_CAP;
3073 decode_bearer_cap(&modify.bearer_cap,
3074 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3075 }
3076
3077 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3078
Harald Welteb3c3fae2009-07-23 19:06:52 +02003079 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003080}
3081
3082static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3083{
3084 struct gsm_mncc *modify = arg;
3085 struct msgb *msg = gsm48_msgb_alloc();
3086 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3087
3088 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3089 msg->lchan = trans->lchan;
3090 gh->msg_type = GSM48_MT_CC_MODIFY;
3091
3092 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3093
3094 /* bearer capability */
3095 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3096
3097 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3098
3099 return gsm48_sendmsg(msg);
3100}
3101
3102static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3103{
3104 struct gsm48_hdr *gh = msgb_l3(msg);
3105 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3106 struct tlv_parsed tp;
3107 struct gsm_mncc modify;
3108
3109 gsm48_stop_cc_timer(trans);
3110
3111 memset(&modify, 0, sizeof(struct gsm_mncc));
3112 modify.callref = trans->callref;
3113 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3114 /* bearer capability */
3115 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3116 modify.fields |= MNCC_F_BEARER_CAP;
3117 decode_bearer_cap(&modify.bearer_cap,
3118 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3119 }
3120
3121 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3122
Harald Welteb3c3fae2009-07-23 19:06:52 +02003123 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003124}
3125
3126static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3127{
3128 struct gsm_mncc *modify = arg;
3129 struct msgb *msg = gsm48_msgb_alloc();
3130 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3131
3132 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3133 msg->lchan = trans->lchan;
3134 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3135
3136 /* bearer capability */
3137 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3138
3139 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3140
3141 return gsm48_sendmsg(msg);
3142}
3143
3144static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3145{
3146 struct gsm48_hdr *gh = msgb_l3(msg);
3147 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3148 struct tlv_parsed tp;
3149 struct gsm_mncc modify;
3150
3151 gsm48_stop_cc_timer(trans);
3152
3153 memset(&modify, 0, sizeof(struct gsm_mncc));
3154 modify.callref = trans->callref;
3155 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3156 /* bearer capability */
3157 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3158 modify.fields |= GSM48_IE_BEARER_CAP;
3159 decode_bearer_cap(&modify.bearer_cap,
3160 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3161 }
3162 /* cause */
3163 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3164 modify.fields |= MNCC_F_CAUSE;
3165 decode_cause(&modify.cause,
3166 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3167 }
3168
3169 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3170
Harald Welteb3c3fae2009-07-23 19:06:52 +02003171 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003172}
3173
3174static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3175{
3176 struct gsm_mncc *modify = arg;
3177 struct msgb *msg = gsm48_msgb_alloc();
3178 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3179
3180 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3181 msg->lchan = trans->lchan;
3182 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3183
3184 /* bearer capability */
3185 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3186 /* cause */
3187 encode_cause(msg, 1, &modify->cause);
3188
3189 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3190
3191 return gsm48_sendmsg(msg);
3192}
3193
3194static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3195{
3196 struct gsm_mncc *notify = arg;
3197 struct msgb *msg = gsm48_msgb_alloc();
3198 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3199
3200 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3201 msg->lchan = trans->lchan;
3202 gh->msg_type = GSM48_MT_CC_NOTIFY;
3203
3204 /* notify */
3205 encode_notify(msg, notify->notify);
3206
3207 return gsm48_sendmsg(msg);
3208}
3209
3210static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3211{
3212 struct gsm48_hdr *gh = msgb_l3(msg);
3213 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3214// struct tlv_parsed tp;
3215 struct gsm_mncc notify;
3216
3217 memset(&notify, 0, sizeof(struct gsm_mncc));
3218 notify.callref = trans->callref;
3219// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3220 if (payload_len >= 1)
3221 decode_notify(&notify.notify, gh->data);
3222
Harald Welteb3c3fae2009-07-23 19:06:52 +02003223 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003224}
3225
3226static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3227{
3228 struct gsm_mncc *user = arg;
3229 struct msgb *msg = gsm48_msgb_alloc();
3230 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3231
3232 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3233 msg->lchan = trans->lchan;
3234 gh->msg_type = GSM48_MT_CC_USER_INFO;
3235
3236 /* user-user */
3237 if (user->fields & MNCC_F_USERUSER)
3238 encode_useruser(msg, 1, &user->useruser);
3239 /* more data */
3240 if (user->more)
3241 encode_more(msg);
3242
3243 return gsm48_sendmsg(msg);
3244}
3245
3246static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3247{
3248 struct gsm48_hdr *gh = msgb_l3(msg);
3249 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3250 struct tlv_parsed tp;
3251 struct gsm_mncc user;
3252
3253 memset(&user, 0, sizeof(struct gsm_mncc));
3254 user.callref = trans->callref;
3255 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3256 /* user-user */
3257 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3258 user.fields |= MNCC_F_USERUSER;
3259 decode_useruser(&user.useruser,
3260 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3261 }
3262 /* more data */
3263 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3264 user.more = 1;
3265
Harald Welteb3c3fae2009-07-23 19:06:52 +02003266 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003267}
3268
3269static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3270{
3271 struct gsm_mncc *mode = arg;
3272
3273 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3274}
3275
3276static struct downstate {
3277 u_int32_t states;
3278 int type;
3279 int (*rout) (struct gsm_trans *trans, void *arg);
3280} downstatelist[] = {
3281 /* mobile originating call establishment */
3282 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3283 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3284 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3285 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3286 {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 */
3287 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3288 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3289 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3290 /* mobile terminating call establishment */
3291 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3292 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3293 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3294 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3295 /* signalling during call */
3296 {SBIT(GSM_CSTATE_ACTIVE),
3297 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3298 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3299 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3300 {ALL_STATES,
3301 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3302 {ALL_STATES,
3303 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3304 {ALL_STATES,
3305 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3306 {SBIT(GSM_CSTATE_ACTIVE),
3307 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3308 {SBIT(GSM_CSTATE_ACTIVE),
3309 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3310 {SBIT(GSM_CSTATE_ACTIVE),
3311 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3312 {SBIT(GSM_CSTATE_ACTIVE),
3313 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3314 {SBIT(GSM_CSTATE_ACTIVE),
3315 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3316 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3317 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3318 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3319 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3320 {SBIT(GSM_CSTATE_ACTIVE),
3321 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3322 /* clearing */
3323 {SBIT(GSM_CSTATE_INITIATED),
3324 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3325 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3326 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3327 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3328 MNCC_REL_REQ, gsm48_cc_tx_release},
3329 /* special */
3330 {ALL_STATES,
3331 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3332};
3333
3334#define DOWNSLLEN \
3335 (sizeof(downstatelist) / sizeof(struct downstate))
3336
3337
3338int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3339{
3340 int i, j, k, l, rc = 0;
3341 struct gsm_trans *trans = NULL, *transt;
3342 struct gsm_subscriber *subscr;
3343 struct gsm_lchan *lchan = NULL, *lchant;
3344 struct gsm_bts *bts = NULL;
3345 struct gsm_bts_trx *trx;
3346 struct gsm_bts_trx_ts *ts;
3347 struct gsm_mncc *data = arg, rel;
3348
3349 /* handle special messages */
3350 switch(msg_type) {
3351 case MNCC_BRIDGE:
3352 return tch_bridge(net, arg);
3353 case MNCC_FRAME_DROP:
3354 return tch_recv(net, arg, 0);
3355 case MNCC_FRAME_RECV:
3356 return tch_recv(net, arg, 1);
3357 case GSM_TRAU_FRAME:
3358 return tch_frame(net, arg);
3359 }
3360
3361 memset(&rel, 0, sizeof(struct gsm_mncc));
3362 rel.callref = data->callref;
3363
3364 /* Find callref */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003365 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003366
3367 /* Callref unknown */
3368 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003369 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003370 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3371 "Received '%s' from MNCC with "
3372 "unknown callref %d\n", data->called.number,
3373 get_mncc_name(msg_type), data->callref);
3374 /* Invalid call reference */
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_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003378 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003379 if (!data->called.number[0] && !data->imsi[0]) {
3380 DEBUGP(DCC, "(bts - trx - ts - ti) "
3381 "Received '%s' from MNCC with "
3382 "no number or IMSI\n", get_mncc_name(msg_type));
3383 /* Invalid number */
3384 return mncc_release_ind(net, NULL, data->callref,
3385 GSM48_CAUSE_LOC_PRN_S_LU,
3386 GSM48_CC_CAUSE_INV_NR_FORMAT);
3387 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003388 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003389 if (data->called.number[0])
Harald Welte761e9442009-07-23 19:21:02 +02003390 subscr = subscr_get_by_extension(net,
3391 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003392 else
Harald Welte761e9442009-07-23 19:21:02 +02003393 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003394 /* If subscriber is not found */
3395 if (!subscr) {
3396 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3397 "Received '%s' from MNCC with "
3398 "unknown subscriber %s\n", data->called.number,
3399 get_mncc_name(msg_type), data->called.number);
3400 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003401 return mncc_release_ind(net, NULL, data->callref,
3402 GSM48_CAUSE_LOC_PRN_S_LU,
3403 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003404 }
3405 /* If subscriber is not "attached" */
3406 if (!subscr->lac) {
3407 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3408 "Received '%s' from MNCC with "
3409 "detached subscriber %s\n", data->called.number,
3410 get_mncc_name(msg_type), data->called.number);
3411 subscr_put(subscr);
3412 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003413 return mncc_release_ind(net, NULL, data->callref,
3414 GSM48_CAUSE_LOC_PRN_S_LU,
3415 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003416 }
3417 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003418 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3419 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003420 DEBUGP(DCC, "No memory for trans.\n");
3421 subscr_put(subscr);
3422 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003423 mncc_release_ind(net, NULL, data->callref,
3424 GSM48_CAUSE_LOC_PRN_S_LU,
3425 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003426 return -ENOMEM;
3427 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003428 /* Find lchan */
3429 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003430 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003431 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003432 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003433 for (k = 0; k < TRX_NR_TS; k++) {
3434 ts = &trx->ts[k];
3435 for (l = 0; l < TS_MAX_LCHAN; l++) {
3436 lchant = &ts->lchan[l];
3437 if (lchant->subscr == subscr) {
3438 lchan = lchant;
3439 break;
3440 }
3441 }
3442 }
3443 }
3444 }
3445
3446 /* If subscriber has no lchan */
3447 if (!lchan) {
3448 /* find transaction with this subscriber already paging */
3449 llist_for_each_entry(transt, &net->trans_list, entry) {
3450 /* Transaction of our lchan? */
3451 if (transt == trans ||
3452 transt->subscr != subscr)
3453 continue;
3454 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3455 "Received '%s' from MNCC with "
3456 "unallocated channel, paging already "
3457 "started.\n", bts->nr,
3458 data->called.number,
3459 get_mncc_name(msg_type));
3460 return 0;
3461 }
3462 /* store setup informations until paging was successfull */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003463 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08003464 /* start paging subscriber on all BTS with her location */
3465 subscr->net = net;
3466 bts = NULL;
3467 do {
3468 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3469 if (!bts)
3470 break;
3471 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3472 "Received '%s' from MNCC with "
3473 "unallocated channel, paging.\n",
3474 bts->nr, data->called.number,
3475 get_mncc_name(msg_type));
3476 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003477 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003478 setup_trig_pag_evt, subscr);
3479 } while (1);
3480 return 0;
3481 }
3482 /* Assign lchan */
3483 trans->lchan = lchan;
3484 use_lchan(lchan);
3485 }
3486 lchan = trans->lchan;
3487
3488 /* if paging did not respond yet */
3489 if (!lchan) {
3490 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3491 "Received '%s' from MNCC in paging state\n",
3492 (trans->subscr)?(trans->subscr->extension):"-",
3493 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003494 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3495 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003496 if (msg_type == MNCC_REL_REQ)
3497 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3498 else
3499 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3500 trans->callref = 0;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003501 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003502 return rc;
3503 }
3504
3505 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3506 "Received '%s' from MNCC in state %d (%s)\n",
3507 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3508 trans->transaction_id,
3509 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003510 get_mncc_name(msg_type), trans->cc.state,
3511 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003512
3513 /* Find function for current state and message */
3514 for (i = 0; i < DOWNSLLEN; i++)
3515 if ((msg_type == downstatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003516 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003517 break;
3518 if (i == DOWNSLLEN) {
3519 DEBUGP(DCC, "Message unhandled at this state.\n");
3520 return 0;
3521 }
3522
3523 rc = downstatelist[i].rout(trans, arg);
3524
3525 return rc;
3526}
3527
3528
3529static struct datastate {
3530 u_int32_t states;
3531 int type;
3532 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3533} datastatelist[] = {
3534 /* mobile originating call establishment */
3535 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3536 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3537 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3538 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3539 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3540 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3541 /* mobile terminating call establishment */
3542 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3543 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3544 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3545 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3546 {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 */
3547 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3548 /* signalling during call */
3549 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3550 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3551 {SBIT(GSM_CSTATE_ACTIVE),
3552 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3553 {ALL_STATES,
3554 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3555 {ALL_STATES,
3556 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3557 {ALL_STATES,
3558 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3559 {SBIT(GSM_CSTATE_ACTIVE),
3560 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3561 {SBIT(GSM_CSTATE_ACTIVE),
3562 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3563 {SBIT(GSM_CSTATE_ACTIVE),
3564 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3565 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3566 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3567 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3568 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3569 {SBIT(GSM_CSTATE_ACTIVE),
3570 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3571 /* clearing */
3572 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3573 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3574 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3575 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3576 {ALL_STATES, /* 5.4.3.4 */
3577 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3578};
3579
3580#define DATASLLEN \
3581 (sizeof(datastatelist) / sizeof(struct datastate))
3582
Harald Welte4bc90a12008-12-27 16:32:52 +00003583static int gsm0408_rcv_cc(struct msgb *msg)
3584{
3585 struct gsm48_hdr *gh = msgb_l3(msg);
3586 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003587 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3588 struct gsm_lchan *lchan = msg->lchan;
Harald Welteaa0b29c2009-07-23 18:56:43 +02003589 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003590 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003591
Harald Welte4bfdfe72009-06-10 23:11:52 +08003592 if (msg_type & 0x80) {
3593 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3594 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003595 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003596
3597 /* Find transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003598 trans = trans_find_by_id(lchan, transaction_id);
3599
Harald Welte4bfdfe72009-06-10 23:11:52 +08003600 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3601 "Received '%s' from MS in state %d (%s)\n",
3602 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3603 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Welteaa0b29c2009-07-23 18:56:43 +02003604 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3605 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003606
3607 /* Create transaction */
3608 if (!trans) {
3609 DEBUGP(DCC, "Unknown transaction ID %02x, "
3610 "creating new trans.\n", transaction_id);
3611 /* Create transaction */
Harald Welteaa0b29c2009-07-23 18:56:43 +02003612 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3613 transaction_id, new_callref++);
3614 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003615 DEBUGP(DCC, "No memory for trans.\n");
3616 rc = gsm48_tx_simple(msg->lchan,
3617 GSM48_PDISC_CC | transaction_id,
3618 GSM48_MT_CC_RELEASE_COMPL);
3619 return -ENOMEM;
3620 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003621 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003622 trans->lchan = lchan;
3623 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003624 }
3625
3626 /* find function for current state and message */
3627 for (i = 0; i < DATASLLEN; i++)
3628 if ((msg_type == datastatelist[i].type)
Harald Welteaa0b29c2009-07-23 18:56:43 +02003629 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003630 break;
3631 if (i == DATASLLEN) {
3632 DEBUGP(DCC, "Message unhandled at this state.\n");
3633 return 0;
3634 }
3635
3636 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003637
3638 return rc;
3639}
3640
Harald Welte52b1f982008-12-23 20:25:15 +00003641/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3642int gsm0408_rcvmsg(struct msgb *msg)
3643{
3644 struct gsm48_hdr *gh = msgb_l3(msg);
3645 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003646 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003647
3648 switch (pdisc) {
3649 case GSM48_PDISC_CC:
3650 rc = gsm0408_rcv_cc(msg);
3651 break;
3652 case GSM48_PDISC_MM:
3653 rc = gsm0408_rcv_mm(msg);
3654 break;
3655 case GSM48_PDISC_RR:
3656 rc = gsm0408_rcv_rr(msg);
3657 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003658 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003659 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003660 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003661 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003662 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003663 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3664 pdisc);
3665 break;
3666 default:
3667 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3668 pdisc);
3669 break;
3670 }
3671
3672 return rc;
3673}
Harald Welte8470bf22008-12-25 23:28:35 +00003674
Harald Welte8470bf22008-12-25 23:28:35 +00003675/* Section 9.1.8 / Table 9.9 */
3676struct chreq {
3677 u_int8_t val;
3678 u_int8_t mask;
3679 enum chreq_type type;
3680};
3681
3682/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3683static const struct chreq chreq_type_neci1[] = {
3684 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3685 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3686 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3687 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3688 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3689 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3690 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3691 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3692 { 0x10, 0xf0, CHREQ_T_SDCCH },
3693 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3694 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3695 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3696};
3697
3698/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3699static const struct chreq chreq_type_neci0[] = {
3700 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3701 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3702 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3703 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3704 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3705 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3706 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3707 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3708};
3709
3710static const enum gsm_chan_t ctype_by_chreq[] = {
3711 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3712 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3713 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3714 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3715 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3716 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3717 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3718 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3719 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3720 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3721 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3722 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3723};
3724
Harald Weltee14a57c2008-12-29 04:08:28 +00003725static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3726 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3727 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3728 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3729 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3730 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3731 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3732 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3733 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3734 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3735 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3736 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3737 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3738};
3739
Harald Welte8470bf22008-12-25 23:28:35 +00003740enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3741{
3742 int i;
3743 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3744
3745 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3746 const struct chreq *chr = &chreq_type_neci0[i];
3747 if ((ra & chr->mask) == chr->val)
3748 return ctype_by_chreq[chr->type];
3749 }
3750 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3751 return GSM_LCHAN_SDCCH;
3752}
Harald Weltee14a57c2008-12-29 04:08:28 +00003753
3754enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3755{
3756 int i;
3757 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3758
3759 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3760 const struct chreq *chr = &chreq_type_neci0[i];
3761 if ((ra & chr->mask) == chr->val)
3762 return reason_by_chreq[chr->type];
3763 }
3764 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3765 return GSM_CHREQ_REASON_OTHER;
3766}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003767
3768/* dequeue messages to layer 4 */
3769int bsc_upqueue(struct gsm_network *net)
3770{
3771 struct gsm_mncc *mncc;
3772 struct msgb *msg;
3773 int work = 0;
3774
3775 if (net)
3776 while ((msg = msgb_dequeue(&net->upqueue))) {
3777 mncc = (struct gsm_mncc *)msg->data;
3778 if (net->mncc_recv)
3779 net->mncc_recv(net, mncc->msg_type, mncc);
3780 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003781 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003782 }
3783
3784 return work;
3785}
Harald Welteaa0b29c2009-07-23 18:56:43 +02003786