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