blob: 03fe01058a7e9363db4500cf6fed852087ca1144 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* 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
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
6 *
7 * 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>
30#include <time.h>
31#include <netinet/in.h>
32
33#include <openbsc/db.h>
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
Daniel Willmannc8188202009-08-13 03:42:07 +020038#include <openbsc/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080039#include <openbsc/gsm_subscriber.h>
40#include <openbsc/gsm_04_11.h>
41#include <openbsc/gsm_04_08.h>
42#include <openbsc/abis_rsl.h>
43#include <openbsc/chan_alloc.h>
44#include <openbsc/paging.h>
45#include <openbsc/signal.h>
46#include <openbsc/trau_frame.h>
47#include <openbsc/trau_mux.h>
Harald Welte3c062072009-07-28 18:25:29 +020048#include <openbsc/rtp_proxy.h>
Harald Weltea8379772009-06-20 22:36:41 +020049#include <openbsc/talloc.h>
Harald Weltec2189a62009-07-23 18:56:43 +020050#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080051
52#define GSM48_ALLOC_SIZE 1024
53#define GSM48_ALLOC_HEADROOM 128
54
Harald Welteb8a18b52009-06-10 12:08:54 +080055#define GSM_MAX_FACILITY 128
56#define GSM_MAX_SSVERSION 128
57#define GSM_MAX_USERUSER 128
58
Harald Weltea8379772009-06-20 22:36:41 +020059static void *tall_locop_ctx;
Harald Weltea8379772009-06-20 22:36:41 +020060
Harald Welte3c062072009-07-28 18:25:29 +020061/* should ip.access BTS use direct RTP streams between each other (1),
62 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
63int ipacc_rtp_direct = 1;
64
Harald Welte59b04682009-06-10 05:40:52 +080065static const struct tlv_definition rsl_att_tlvdef = {
66 .def = {
67 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
69 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
70 [GSM48_IE_UTC] = { TLV_TYPE_TV },
71 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
72 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
73
74 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
75 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
76 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
77 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
78 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
79 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
80 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welteb8a18b52009-06-10 12:08:54 +080081 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte59b04682009-06-10 05:40:52 +080082 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
83 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welteb8a18b52009-06-10 12:08:54 +080084 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte59b04682009-06-10 05:40:52 +080086 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
89 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
91 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
92 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
94 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
95 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
96 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
98 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
99 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welteb8a18b52009-06-10 12:08:54 +0800100 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
101 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte59b04682009-06-10 05:40:52 +0800102 /* FIXME: more elements */
103 },
104};
105
106static const char *rr_cause_names[] = {
107 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
108 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
109 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
110 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
111 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
112 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
113 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
114 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
115 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
116 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
117 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
118 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
119 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
120 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
121 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
122 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
123 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
124};
125
Harald Welte03740842009-06-10 23:11:52 +0800126static const char *cc_state_names[] = {
127 "NULL",
128 "INITIATED",
129 "illegal state 2",
130 "MO_CALL_PROC",
131 "CALL_DELIVERED",
132 "illegal state 5",
133 "CALL_PRESENT",
134 "CALL_RECEIVED",
135 "CONNECT_REQUEST",
136 "MO_TERM_CALL_CONF",
137 "ACTIVE",
138 "DISCONNECT_REQ",
139 "DISCONNECT_IND",
140 "illegal state 13",
141 "illegal state 14",
142 "illegal state 15",
143 "illegal state 16",
144 "illegal state 17",
145 "illegal state 18",
146 "RELEASE_REQ",
147 "illegal state 20",
148 "illegal state 21",
149 "illegal state 22",
150 "illegal state 23",
151 "illegal state 24",
152 "illegal state 25",
153 "MO_ORIG_MODIFY",
154 "MO_TERM_MODIFY",
155 "CONNECT_IND",
156 "illegal state 29",
157 "illegal state 30",
158 "illegal state 31",
159};
160
161static const char *cc_msg_names[] = {
162 "unknown 0x00",
163 "ALERTING",
164 "CALL_PROC",
165 "PROGRESS",
166 "ESTAB",
167 "SETUP",
168 "ESTAB_CONF",
169 "CONNECT",
170 "CALL_CONF",
171 "START_CC",
172 "unknown 0x0a",
173 "RECALL",
174 "unknown 0x0c",
175 "unknown 0x0d",
176 "EMERG_SETUP",
177 "CONNECT_ACK",
178 "USER_INFO",
179 "unknown 0x11",
180 "unknown 0x12",
181 "MODIFY_REJECT",
182 "unknown 0x14",
183 "unknown 0x15",
184 "unknown 0x16",
185 "MODIFY",
186 "HOLD",
187 "HOLD_ACK",
188 "HOLD_REJ",
189 "unknown 0x1b",
190 "RETR",
191 "RETR_ACK",
192 "RETR_REJ",
193 "MODIFY_COMPL",
194 "unknown 0x20",
195 "unknown 0x21",
196 "unknown 0x22",
197 "unknown 0x23",
198 "unknown 0x24",
199 "DISCONNECT",
200 "unknown 0x26",
201 "unknown 0x27",
202 "unknown 0x28",
203 "unknown 0x29",
204 "RELEASE_COMPL",
205 "unknown 0x2b",
206 "unknown 0x2c",
207 "RELEASE",
208 "unknown 0x2e",
209 "unknown 0x2f",
210 "unknown 0x30",
211 "STOP_DTMF",
212 "STOP_DTMF_ACK",
213 "unknown 0x33",
214 "STATUS_ENQ",
215 "START_DTMF",
216 "START_DTMF_ACK",
217 "START_DTMF_REJ",
218 "unknown 0x38",
219 "CONG_CTRL",
220 "FACILITY",
221 "unknown 0x3b",
222 "STATUS",
223 "unknown 0x3c",
224 "NOTIFY",
225 "unknown 0x3f",
226};
227
Harald Welte59b04682009-06-10 05:40:52 +0800228static char strbuf[64];
229
230static const char *rr_cause_name(u_int8_t cause)
231{
232 if (cause < ARRAY_SIZE(rr_cause_names) &&
233 rr_cause_names[cause])
234 return rr_cause_names[cause];
235
236 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
237 return strbuf;
238}
239
240static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
241 int len)
242{
243 memset(rep, 0, sizeof(*rep));
244
245 if (data[0] & 0x80)
246 rep->flags |= MEAS_REP_F_BA1;
247 if (data[0] & 0x40)
248 rep->flags |= MEAS_REP_F_DTX;
Harald Welteba6589d2009-07-05 04:05:44 +0200249 if ((data[1] & 0x40) == 0x00)
Harald Welte59b04682009-06-10 05:40:52 +0800250 rep->flags |= MEAS_REP_F_VALID;
251
252 rep->rxlev_full = data[0] & 0x3f;
253 rep->rxlev_sub = data[1] & 0x3f;
254 rep->rxqual_full = (data[3] >> 4) & 0x7;
255 rep->rxqual_sub = (data[3] >> 1) & 0x7;
256 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
257 if (rep->num_cell < 1)
258 return;
259
260 /* an encoding nightmare in perfection */
261
262 rep->cell[0].rxlev = data[4] & 0x3f;
263 rep->cell[0].bcch_freq = data[5] >> 2;
264 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
265 if (rep->num_cell < 2)
266 return;
267
268 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
269 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
270 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
271 if (rep->num_cell < 3)
272 return;
273
274 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
275 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
276 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
277 if (rep->num_cell < 4)
278 return;
279
280 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
281 rep->cell[3].bcch_freq = data[11] & 0x1f;
282 rep->cell[3].bsic = data[12] >> 2;
283 if (rep->num_cell < 5)
284 return;
285
286 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
287 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
288 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
289 if (rep->num_cell < 6)
290 return;
291
292 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
293 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
294 rep->cell[5].bsic = data[16] & 0x3f;
295}
296
297int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
298static int gsm48_tx_simple(struct gsm_lchan *lchan,
299 u_int8_t pdisc, u_int8_t msg_type);
300static void schedule_reject(struct gsm_lchan *lchan);
301
302struct gsm_lai {
303 u_int16_t mcc;
304 u_int16_t mnc;
305 u_int16_t lac;
306};
307
Harald Welte59b04682009-06-10 05:40:52 +0800308static int reject_cause = 0;
309void gsm0408_set_reject_cause(int cause)
310{
311 reject_cause = cause;
312}
313
Harald Welte03740842009-06-10 23:11:52 +0800314static u_int32_t new_callref = 0x80000001;
315
Harald Welte59b04682009-06-10 05:40:52 +0800316static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
317 struct gsm_subscriber *subscriber)
318{
319 if (!subscriber)
320 return 0;
321
322 /*
323 * Do not send accept yet as more information should arrive. Some
324 * phones will not send us the information and we will have to check
325 * what we want to do with that.
326 */
327 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
328 return 0;
329
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200330 switch (subscriber->net->auth_policy) {
331 case GSM_AUTH_POLICY_CLOSED:
332 return subscriber->authorized;
Harald Welte (local)16480eb2009-08-13 13:49:51 +0200333 case GSM_AUTH_POLICY_TOKEN:
334 return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT);
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200335 case GSM_AUTH_POLICY_ACCEPT_ALL:
Harald Welte59b04682009-06-10 05:40:52 +0800336 return 1;
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200337 default:
338 return 0;
339 }
Harald Welte59b04682009-06-10 05:40:52 +0800340}
341
342static void release_loc_updating_req(struct gsm_lchan *lchan)
343{
344 if (!lchan->loc_operation)
345 return;
346
347 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Weltea8379772009-06-20 22:36:41 +0200348 talloc_free(lchan->loc_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800349 lchan->loc_operation = 0;
350 put_lchan(lchan);
351}
352
353static void allocate_loc_updating_req(struct gsm_lchan *lchan)
354{
355 use_lchan(lchan);
356 release_loc_updating_req(lchan);
357
Harald Welte857e00d2009-06-26 20:25:23 +0200358 lchan->loc_operation = talloc_zero(tall_locop_ctx,
359 struct gsm_loc_updating_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800360}
361
362static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
363{
364 u_int32_t tmsi;
365
366 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welte5070e942009-08-09 19:07:00 +0200367 int rc;
368
Harald Welte59b04682009-06-10 05:40:52 +0800369 db_subscriber_alloc_tmsi(lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800370 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
371 release_loc_updating_req(lchan);
Harald Welte5070e942009-08-09 19:07:00 +0200372 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
373 /* call subscr_update after putting the loc_upd_acc
374 * in the transmit queue, since S_SUBSCR_ATTACHED might
375 * trigger further action like SMS delivery */
376 subscr_update(lchan->subscr, msg->trx->bts,
377 GSM_SUBSCRIBER_UPDATE_ATTACHED);
378 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800379 }
380
381 return 0;
382}
383
384static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
385 void *handler_data, void *signal_data)
386{
Harald Welte03740842009-06-10 23:11:52 +0800387 struct gsm_trans *trans, *temp;
388
Harald Welte59b04682009-06-10 05:40:52 +0800389 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
390 return 0;
391
392 /*
393 * Cancel any outstanding location updating request
394 * operation taking place on the lchan.
395 */
Harald Welte12560da2009-07-04 09:35:21 +0200396 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Welte1ff81b52009-06-26 20:17:06 +0200397 if (!lchan)
398 return 0;
399
Harald Welte59b04682009-06-10 05:40:52 +0800400 release_loc_updating_req(lchan);
401
Harald Welte03740842009-06-10 23:11:52 +0800402 /* Free all transactions that are associated with the released lchan */
Harald Weltec2189a62009-07-23 18:56:43 +0200403 /* FIXME: this is not neccessarily the right thing to do, we should
404 * only set trans->lchan to NULL and wait for another lchan to be
405 * established to the same MM entity (phone/subscriber) */
Harald Welte03740842009-06-10 23:11:52 +0800406 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
407 if (trans->lchan == lchan)
Harald Weltec2189a62009-07-23 18:56:43 +0200408 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +0800409 }
410
Harald Welte59b04682009-06-10 05:40:52 +0800411 return 0;
412}
413
Harald Welte59b04682009-06-10 05:40:52 +0800414static void to_bcd(u_int8_t *bcd, u_int16_t val)
415{
416 bcd[2] = val % 10;
417 val = val / 10;
418 bcd[1] = val % 10;
419 val = val / 10;
420 bcd[0] = val % 10;
421 val = val / 10;
422}
423
424void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
425 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);
434 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
435#if 0
436 lai48->digits[1] |= bcd[2] << 4;
437 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
438#else
439 lai48->digits[1] |= 0xf << 4;
440 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
441#endif
442
443 lai48->lac = htons(lac);
444}
445
446#define TMSI_LEN 5
447#define MID_TMSI_LEN (TMSI_LEN + 2)
448
449int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
450{
451 u_int32_t *tptr = (u_int32_t *) &buf[3];
452
453 buf[0] = GSM48_IE_MOBILE_ID;
454 buf[1] = TMSI_LEN;
455 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
456 *tptr = htonl(tmsi);
457
458 return 7;
459}
460
461static const char bcd_num_digits[] = {
462 '0', '1', '2', '3', '4', '5', '6', '7',
463 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
464};
465
Harald Welteb8a18b52009-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 Welte59b04682009-06-10 05:40:52 +0800469{
470 u_int8_t in_len = bcd_lv[0];
471 int i;
472
Harald Welteb8a18b52009-06-10 12:08:54 +0800473 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte59b04682009-06-10 05:40:52 +0800474 /* 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 Welteb8a18b52009-06-10 12:08:54 +0800489 return 0;
Harald Welte59b04682009-06-10 05:40:52 +0800490}
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 Welteb8a18b52009-06-10 12:08:54 +0800504/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte59b04682009-06-10 05:40:52 +0800505int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welteb8a18b52009-06-10 12:08:54 +0800506 int h_len, const char *input)
Harald Welte59b04682009-06-10 05:40:52 +0800507{
508 int in_len = strlen(input);
509 int i;
Harald Welteb8a18b52009-06-10 12:08:54 +0800510 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800511
512 /* two digits per byte, plus type byte */
Harald Welteb8a18b52009-06-10 12:08:54 +0800513 bcd_lv[0] = in_len/2 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800514 if (in_len % 2)
515 bcd_lv[0]++;
516
Harald Welteb8a18b52009-06-10 12:08:54 +0800517 if (bcd_lv[0] > max_len)
518 return -EIO;
Harald Welte59b04682009-06-10 05:40:52 +0800519
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 Welteb8a18b52009-06-10 12:08:54 +0800537/* decode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800538static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800547 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welteb8a18b52009-06-10 12:08:54 +0800548
549 /* octet 3 */
Harald Welte03740842009-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 Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800561 bcap->speech_ver[s++] = lv[i] & 0x0f;
562 bcap->speech_ver[s] = -1; /* end of list */
Harald Welteb8a18b52009-06-10 12:08:54 +0800563 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800564 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welteb8a18b52009-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 Welte03740842009-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 Welteb8a18b52009-06-10 12:08:54 +0800575{
576 u_int8_t lv[32 + 1];
577 int i, s;
578
Harald Welte03740842009-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 Welteb8a18b52009-06-10 12:08:54 +0800583
584 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800585 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800586 i++; /* octet 3a etc */
Harald Welte03740842009-06-10 23:11:52 +0800587 lv[i] = bcap->speech_ver[s];
Harald Welteb8a18b52009-06-10 12:08:54 +0800588 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800589 lv[i] |= bcap->speech_ctm << 5;
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800603static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800611 ccap->dtmf = lv[1] & 0x01;
612 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welteb8a18b52009-06-10 12:08:54 +0800613
614 return 0;
615}
616
617/* decode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800618static int decode_called(struct gsm_mncc_number *called,
619 const u_int8_t *lv)
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800627 called->plan = lv[1] & 0x0f;
628 called->type = (lv[1] & 0x70) >> 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800629
630 /* octet 4..N */
Harald Welte03740842009-06-10 23:11:52 +0800631 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800632
633 return 0;
634}
635
636/* encode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800637static int encode_called(struct msgb *msg,
638 const struct gsm_mncc_number *called)
Harald Welteb8a18b52009-06-10 12:08:54 +0800639{
640 u_int8_t lv[18];
641 int ret;
642
643 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800644 lv[1] = called->plan;
645 lv[1] |= called->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800646
647 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800648 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800658static int encode_callerid(struct msgb *msg, int ie,
659 const struct gsm_mncc_number *callerid)
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800666 lv[1] = callerid->plan;
667 lv[1] |= callerid->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800668
Harald Welte03740842009-06-10 23:11:52 +0800669 if (callerid->present || callerid->screen) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800670 /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800671 lv[2] = callerid->screen;
672 lv[2] |= callerid->present << 5;
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800679 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800689static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800698 cause->diag_len = 0;
Harald Welteb8a18b52009-06-10 12:08:54 +0800699
700 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800701 cause->location = lv[1] & 0x0f;
702 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800709 cause->rec = 1;
710 cause->rec_val = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800711
712 }
713 i++;
714
715 /* octet 4 */
Harald Welte03740842009-06-10 23:11:52 +0800716 cause->value = lv[i] & 0x7f;
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800726 memcpy(cause->diag, lv + i, in_len - (i-1));
727 cause->diag_len = in_len - (i-1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800728
729 return 0;
730}
731
732/* encode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800733static int encode_cause(struct msgb *msg, int lv_only,
734 const struct gsm_mncc_cause *cause)
Harald Welteb8a18b52009-06-10 12:08:54 +0800735{
736 u_int8_t lv[32+4];
737 int i;
738
Harald Welte03740842009-06-10 23:11:52 +0800739 if (cause->diag_len > 32)
Harald Welteb8a18b52009-06-10 12:08:54 +0800740 return -EINVAL;
741
742 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800743 lv[1] = cause->location;
744 lv[1] |= cause->coding << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800745
746 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800747 if (cause->rec) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800748 i++; /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800749 lv[i] = cause->rec_val;
Harald Welteb8a18b52009-06-10 12:08:54 +0800750 }
751 lv[i] |= 0x80; /* end of octet 3 */
752
753 /* octet 4 */
754 i++;
Harald Welte03740842009-06-10 23:11:52 +0800755 lv[i] = 0x80 | cause->value;
Harald Welteb8a18b52009-06-10 12:08:54 +0800756
757 /* octet 5-N */
Harald Welte03740842009-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 Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800773static int encode_calling(struct msgb *msg,
774 const struct gsm_mncc_number *calling)
Harald Welteb8a18b52009-06-10 12:08:54 +0800775{
Harald Welte03740842009-06-10 23:11:52 +0800776 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welteb8a18b52009-06-10 12:08:54 +0800777}
778
779/* encode 'connected number' */
Harald Welte03740842009-06-10 23:11:52 +0800780static int encode_connected(struct msgb *msg,
781 const struct gsm_mncc_number *connected)
Harald Welteb8a18b52009-06-10 12:08:54 +0800782{
Harald Welte03740842009-06-10 23:11:52 +0800783 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welteb8a18b52009-06-10 12:08:54 +0800784}
785
786/* encode 'redirecting number' */
Harald Welte03740842009-06-10 23:11:52 +0800787static int encode_redirecting(struct msgb *msg,
788 const struct gsm_mncc_number *redirecting)
Harald Welteb8a18b52009-06-10 12:08:54 +0800789{
Harald Welte03740842009-06-10 23:11:52 +0800790 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welteb8a18b52009-06-10 12:08:54 +0800791}
792
793/* decode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800794static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800802 if (in_len > sizeof(facility->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800803 return -EINVAL;
804
Harald Welte03740842009-06-10 23:11:52 +0800805 memcpy(facility->info, lv+1, in_len);
806 facility->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800807
808 return 0;
809}
810
811/* encode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800812static int encode_facility(struct msgb *msg, int lv_only,
813 const struct gsm_mncc_facility *facility)
Harald Welteb8a18b52009-06-10 12:08:54 +0800814{
815 u_int8_t lv[GSM_MAX_FACILITY + 1];
816
Harald Welte03740842009-06-10 23:11:52 +0800817 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welteb8a18b52009-06-10 12:08:54 +0800818 return -EINVAL;
819
Harald Welte03740842009-06-10 23:11:52 +0800820 memcpy(lv+1, facility->info, facility->len);
821 lv[0] = facility->len;
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800876static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welteb8a18b52009-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 Welte03740842009-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 Welteb8a18b52009-06-10 12:08:54 +0800887
888 return 0;
889}
890
891/* encode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800892static int encode_progress(struct msgb *msg, int lv_only,
893 const struct gsm_mncc_progress *p)
Harald Welteb8a18b52009-06-10 12:08:54 +0800894{
895 u_int8_t lv[3];
896
897 lv[0] = 2;
Harald Welte03740842009-06-10 23:11:52 +0800898 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
899 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800909static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welteb8a18b52009-06-10 12:08:54 +0800910 const u_int8_t *lv)
911{
912 u_int8_t in_len = lv[0];
Harald Welte03740842009-06-10 23:11:52 +0800913 char *info = uu->info;
914 int info_len = sizeof(uu->info);
Harald Welteb8a18b52009-06-10 12:08:54 +0800915 int i;
916
917 if (in_len < 1)
918 return -EINVAL;
919
Harald Welte03740842009-06-10 23:11:52 +0800920 uu->proto = lv[1];
Harald Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800935static int encode_useruser(struct msgb *msg, int lv_only,
936 const struct gsm_mncc_useruser *uu)
Harald Welteb8a18b52009-06-10 12:08:54 +0800937{
938 u_int8_t lv[GSM_MAX_USERUSER + 2];
939
Harald Welte03740842009-06-10 23:11:52 +0800940 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welteb8a18b52009-06-10 12:08:54 +0800941 return -EINVAL;
942
Harald Welte03740842009-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 Welteb8a18b52009-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 Welte03740842009-06-10 23:11:52 +0800955static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welteb8a18b52009-06-10 12:08:54 +0800956 const u_int8_t *lv)
957{
958 u_int8_t in_len = lv[0];
959
Harald Welte03740842009-06-10 23:11:52 +0800960 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800961 return -EINVAL;
962
Harald Welte03740842009-06-10 23:11:52 +0800963 memcpy(ssv->info, lv + 1, in_len);
964 ssv->len = in_len;
Harald Welteb8a18b52009-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
Harald Welte59b04682009-06-10 05:40:52 +0800980struct msgb *gsm48_msgb_alloc(void)
981{
Harald Welte9cfc9352009-06-26 19:39:35 +0200982 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
983 "GSM 04.08");
Harald Welte59b04682009-06-10 05:40:52 +0800984}
985
Harald Welte36fe2e82009-07-23 21:13:03 +0200986int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800987{
Harald Welte36fe2e82009-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 Welte4861c822009-07-23 21:21:14 +0200993 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte36fe2e82009-07-23 21:13:03 +0200994 msg->lchan = trans->lchan;
995 }
996
Harald Welte59b04682009-06-10 05:40:52 +0800997 if (msg->lchan) {
998 msg->trx = msg->lchan->ts->trx;
999
Harald Welte03740842009-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 Welte59b04682009-06-10 05:40:52 +08001011 }
1012
1013 msg->l3h = msg->data;
1014
1015 return rsl_data_request(msg, 0);
1016}
1017
Harald Welte59b04682009-06-10 05:40:52 +08001018/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
1019int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
1020{
1021 struct msgb *msg = gsm48_msgb_alloc();
1022 struct gsm48_hdr *gh;
1023
1024 msg->lchan = lchan;
1025
1026 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1027 gh->proto_discr = GSM48_PDISC_MM;
1028 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
1029 gh->data[0] = cause;
1030
1031 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1032
Harald Welte36fe2e82009-07-23 21:13:03 +02001033 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001034}
1035
1036/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
1037int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
1038{
1039 struct gsm_bts *bts = lchan->ts->trx->bts;
1040 struct msgb *msg = gsm48_msgb_alloc();
1041 struct gsm48_hdr *gh;
1042 struct gsm48_loc_area_id *lai;
1043 u_int8_t *mid;
1044 int ret;
1045
1046 msg->lchan = lchan;
1047
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));
1053 gsm0408_generate_lai(lai, bts->network->country_code,
1054 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 Welte36fe2e82009-07-23 21:13:03 +02001061 ret = gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001062
Harald Welte5070e942009-08-09 19:07:00 +02001063 /* send MM INFO with network name */
Harald Welte59b04682009-06-10 05:40:52 +08001064 ret = gsm48_tx_mm_info(lchan);
1065
1066 return ret;
1067}
1068
1069static char bcd2char(u_int8_t bcd)
1070{
1071 if (bcd < 0xa)
1072 return '0' + bcd;
1073 else
1074 return 'A' + (bcd - 0xa);
1075}
1076
1077/* Convert Mobile Identity (10.5.1.4) to string */
1078static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1079{
1080 int i;
1081 u_int8_t mi_type;
1082 char *str_cur = string;
1083 u_int32_t tmsi;
1084
1085 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1086
1087 switch (mi_type) {
1088 case GSM_MI_TYPE_NONE:
1089 break;
1090 case GSM_MI_TYPE_TMSI:
1091 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1092 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1093 memcpy(&tmsi, &mi[1], 4);
1094 tmsi = ntohl(tmsi);
1095 return snprintf(string, str_len, "%u", tmsi);
1096 }
1097 break;
1098 case GSM_MI_TYPE_IMSI:
1099 case GSM_MI_TYPE_IMEI:
1100 case GSM_MI_TYPE_IMEISV:
1101 *str_cur++ = bcd2char(mi[0] >> 4);
1102
1103 for (i = 1; i < mi_len; i++) {
1104 if (str_cur + 2 >= string + str_len)
1105 return str_cur - string;
1106 *str_cur++ = bcd2char(mi[i] & 0xf);
1107 /* skip last nibble in last input byte when GSM_EVEN */
1108 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1109 *str_cur++ = bcd2char(mi[i] >> 4);
1110 }
1111 break;
1112 default:
1113 break;
1114 }
1115 *str_cur++ = '\0';
1116
1117 return str_cur - string;
1118}
1119
1120/* Transmit Chapter 9.2.10 Identity Request */
1121static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1122{
1123 struct msgb *msg = gsm48_msgb_alloc();
1124 struct gsm48_hdr *gh;
1125
1126 msg->lchan = lchan;
1127
1128 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1129 gh->proto_discr = GSM48_PDISC_MM;
1130 gh->msg_type = GSM48_MT_MM_ID_REQ;
1131 gh->data[0] = id_type;
1132
Harald Welte36fe2e82009-07-23 21:13:03 +02001133 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001134}
1135
1136#define MI_SIZE 32
1137
1138/* Parse Chapter 9.2.11 Identity Response */
1139static int mm_rx_id_resp(struct msgb *msg)
1140{
1141 struct gsm48_hdr *gh = msgb_l3(msg);
1142 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001143 struct gsm_bts *bts = lchan->ts->trx->bts;
1144 struct gsm_network *net = bts->network;
Harald Welte59b04682009-06-10 05:40:52 +08001145 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1146 char mi_string[MI_SIZE];
1147
1148 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
1149 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
1150 mi_type, mi_string);
1151
Harald Welte59b04682009-06-10 05:40:52 +08001152 switch (mi_type) {
1153 case GSM_MI_TYPE_IMSI:
Jan Luebbe9bdbd622009-08-12 10:19:34 +02001154 /* look up subscriber based on IMSI, create if not found */
1155 if (!lchan->subscr) {
1156 lchan->subscr = subscr_get_by_imsi(net, mi_string);
Harald Welte (local)16480eb2009-08-13 13:49:51 +02001157 if (!lchan->subscr)
1158 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbee2974032009-08-12 10:12:52 +02001159 }
Harald Welte59b04682009-06-10 05:40:52 +08001160 if (lchan->loc_operation)
1161 lchan->loc_operation->waiting_for_imsi = 0;
1162 break;
1163 case GSM_MI_TYPE_IMEI:
1164 case GSM_MI_TYPE_IMEISV:
1165 /* update subscribe <-> IMEI mapping */
1166 if (lchan->subscr)
1167 db_subscriber_assoc_imei(lchan->subscr, mi_string);
1168 if (lchan->loc_operation)
1169 lchan->loc_operation->waiting_for_imei = 0;
1170 break;
1171 }
1172
1173 /* Check if we can let the mobile station enter */
1174 return gsm0408_authorize(lchan, msg);
1175}
1176
1177
1178static void loc_upd_rej_cb(void *data)
1179{
1180 struct gsm_lchan *lchan = data;
1181
1182 release_loc_updating_req(lchan);
1183 gsm0408_loc_upd_rej(lchan, reject_cause);
1184 lchan_auto_release(lchan);
1185}
1186
1187static void schedule_reject(struct gsm_lchan *lchan)
1188{
1189 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1190 lchan->loc_operation->updating_timer.data = lchan;
1191 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
1192}
1193
1194static const char *lupd_name(u_int8_t type)
1195{
1196 switch (type) {
1197 case GSM48_LUPD_NORMAL:
1198 return "NORMAL";
1199 case GSM48_LUPD_PERIODIC:
1200 return "PEROIDOC";
1201 case GSM48_LUPD_IMSI_ATT:
1202 return "IMSI ATTACH";
1203 default:
1204 return "UNKNOWN";
1205 }
1206}
1207
1208#define MI_SIZE 32
1209/* Chapter 9.2.15: Receive Location Updating Request */
1210static int mm_rx_loc_upd_req(struct msgb *msg)
1211{
1212 struct gsm48_hdr *gh = msgb_l3(msg);
1213 struct gsm48_loc_upd_req *lu;
Harald Welte03740842009-06-10 23:11:52 +08001214 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001215 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001216 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001217 u_int8_t mi_type;
1218 char mi_string[MI_SIZE];
1219 int rc;
1220
1221 lu = (struct gsm48_loc_upd_req *) gh->data;
1222
1223 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
1224
1225 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1226
Harald Welte79639662009-06-27 02:58:43 +02001227 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte59b04682009-06-10 05:40:52 +08001228 lupd_name(lu->type));
1229
1230 /*
1231 * Pseudo Spoof detection: Just drop a second/concurrent
1232 * location updating request.
1233 */
1234 if (lchan->loc_operation) {
Harald Welte79639662009-06-27 02:58:43 +02001235 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Harald Welte59b04682009-06-10 05:40:52 +08001236 lchan->loc_operation);
1237 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1238 return 0;
1239 }
1240
1241 allocate_loc_updating_req(lchan);
1242
1243 switch (mi_type) {
1244 case GSM_MI_TYPE_IMSI:
Harald Welte79639662009-06-27 02:58:43 +02001245 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001246 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001247 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1248 lchan->loc_operation->waiting_for_imei = 1;
1249
Jan Luebbe9bdbd622009-08-12 10:19:34 +02001250 /* look up subscriber based on IMSI, create if not found */
1251 subscr = subscr_get_by_imsi(bts->network, mi_string);
1252 if (!subscr) {
1253 subscr = db_create_subscriber(bts->network, mi_string);
1254 }
Harald Welte59b04682009-06-10 05:40:52 +08001255 break;
1256 case GSM_MI_TYPE_TMSI:
Harald Welte79639662009-06-27 02:58:43 +02001257 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001258 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001259 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1260 lchan->loc_operation->waiting_for_imei = 1;
1261
1262 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte75350412009-07-23 18:46:00 +02001263 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001264 if (!subscr) {
1265 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte59b04682009-06-10 05:40:52 +08001266 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
1267 lchan->loc_operation->waiting_for_imsi = 1;
1268 }
1269 break;
1270 case GSM_MI_TYPE_IMEI:
1271 case GSM_MI_TYPE_IMEISV:
1272 /* no sim card... FIXME: what to do ? */
Harald Welte79639662009-06-27 02:58:43 +02001273 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001274 break;
1275 default:
Harald Welte79639662009-06-27 02:58:43 +02001276 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001277 break;
1278 }
1279
Harald Welteccd69362009-07-04 10:18:00 +02001280 /* schedule the reject timer */
1281 schedule_reject(lchan);
1282
Harald Welte03740842009-06-10 23:11:52 +08001283 if (!subscr) {
Harald Welte79639662009-06-27 02:58:43 +02001284 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte03740842009-06-10 23:11:52 +08001285 /* FIXME: request id? close channel? */
1286 return -EINVAL;
1287 }
1288
Harald Welte59b04682009-06-10 05:40:52 +08001289 lchan->subscr = subscr;
1290
Harald Welteccd69362009-07-04 10:18:00 +02001291 /* check if we can let the subscriber into our network immediately
1292 * or if we need to wait for identity responses. */
Harald Welte59b04682009-06-10 05:40:52 +08001293 return gsm0408_authorize(lchan, msg);
1294}
1295
Harald Welteca745e22009-07-29 12:10:35 +02001296/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte59b04682009-06-10 05:40:52 +08001297int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1298{
1299 struct msgb *msg = gsm48_msgb_alloc();
1300 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1301 struct gsm48_chan_mode_modify *cmm =
1302 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
1303 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
1304
1305 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
1306
1307 lchan->tch_mode = mode;
1308 msg->lchan = lchan;
1309 gh->proto_discr = GSM48_PDISC_RR;
1310 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1311
1312 /* fill the channel information element, this code
1313 * should probably be shared with rsl_rx_chan_rqd() */
1314 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
1315 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
1316 cmm->chan_desc.h0.h = 0;
1317 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1318 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1319 cmm->mode = mode;
1320
Harald Welte36fe2e82009-07-23 21:13:03 +02001321 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001322}
1323
Harald Welte03740842009-06-10 23:11:52 +08001324#if 0
1325static u_int8_t to_bcd8(u_int8_t val)
1326{
1327 return ((val / 10) << 4) | (val % 10);
1328}
1329#endif
1330
Harald Welte59b04682009-06-10 05:40:52 +08001331/* Section 9.2.15a */
1332int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1333{
1334 struct msgb *msg = gsm48_msgb_alloc();
1335 struct gsm48_hdr *gh;
1336 struct gsm_network *net = lchan->ts->trx->bts->network;
1337 u_int8_t *ptr8;
1338 u_int16_t *ptr16;
Daniel Willmannc8188202009-08-13 03:42:07 +02001339 int name_len, name_pad;
Harald Welte59b04682009-06-10 05:40:52 +08001340 int i;
Harald Welte03740842009-06-10 23:11:52 +08001341#if 0
1342 time_t cur_t;
1343 struct tm* cur_time;
1344 int tz15min;
1345#endif
Harald Welte59b04682009-06-10 05:40:52 +08001346
1347 msg->lchan = lchan;
1348
1349 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1350 gh->proto_discr = GSM48_PDISC_MM;
1351 gh->msg_type = GSM48_MT_MM_INFO;
1352
1353 if (net->name_long) {
Daniel Willmannc8188202009-08-13 03:42:07 +02001354#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001355 name_len = strlen(net->name_long);
1356 /* 10.5.3.5a */
1357 ptr8 = msgb_put(msg, 3);
1358 ptr8[0] = GSM48_IE_NAME_LONG;
1359 ptr8[1] = name_len*2 +1;
1360 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1361
1362 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1363 for (i = 0; i < name_len; i++)
1364 ptr16[i] = htons(net->name_long[i]);
1365
1366 /* FIXME: Use Cell Broadcast, not UCS-2, since
1367 * UCS-2 is only supported by later revisions of the spec */
Daniel Willmannc8188202009-08-13 03:42:07 +02001368#endif
1369 name_len = (strlen(net->name_long)*7)/8;
1370 name_pad = (8 - strlen(net->name_long)*7)%8;
1371 if (name_pad > 0)
1372 name_len++;
1373 /* 10.5.3.5a */
1374 ptr8 = msgb_put(msg, 3);
1375 ptr8[0] = GSM48_IE_NAME_LONG;
1376 ptr8[1] = name_len +1;
1377 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1378
1379 ptr8 = msgb_put(msg, name_len);
1380 gsm_7bit_encode(ptr8, net->name_long);
1381
Harald Welte59b04682009-06-10 05:40:52 +08001382 }
1383
1384 if (net->name_short) {
Daniel Willmannc8188202009-08-13 03:42:07 +02001385#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001386 name_len = strlen(net->name_short);
1387 /* 10.5.3.5a */
1388 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Weltef6284712009-07-19 17:51:36 +02001389 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Welte59b04682009-06-10 05:40:52 +08001390 ptr8[1] = name_len*2 + 1;
1391 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1392
1393 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1394 for (i = 0; i < name_len; i++)
1395 ptr16[i] = htons(net->name_short[i]);
Daniel Willmannc8188202009-08-13 03:42:07 +02001396#endif
1397 name_len = (strlen(net->name_short)*7)/8;
1398 name_pad = (8 - strlen(net->name_short)*7)%8;
1399 if (name_pad > 0)
1400 name_len++;
1401 /* 10.5.3.5a */
1402 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1403 ptr8[0] = GSM48_IE_NAME_SHORT;
1404 ptr8[1] = name_len +1;
1405 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1406
1407 ptr8 = msgb_put(msg, name_len);
1408 gsm_7bit_encode(ptr8, net->name_short);
1409
Harald Welte59b04682009-06-10 05:40:52 +08001410 }
1411
1412#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001413 /* Section 10.5.3.9 */
1414 cur_t = time(NULL);
Harald Welte03740842009-06-10 23:11:52 +08001415 cur_time = gmtime(&cur_t);
Harald Welte59b04682009-06-10 05:40:52 +08001416 ptr8 = msgb_put(msg, 8);
1417 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1418 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1419 ptr8[2] = to_bcd8(cur_time->tm_mon);
1420 ptr8[3] = to_bcd8(cur_time->tm_mday);
1421 ptr8[4] = to_bcd8(cur_time->tm_hour);
1422 ptr8[5] = to_bcd8(cur_time->tm_min);
1423 ptr8[6] = to_bcd8(cur_time->tm_sec);
1424 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1425 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte03740842009-06-10 23:11:52 +08001426 ptr8[7] = to_bcd8(tz15min);
Harald Welte59b04682009-06-10 05:40:52 +08001427 if (tz15min < 0)
Harald Welte03740842009-06-10 23:11:52 +08001428 ptr8[7] |= 0x80;
Harald Welte59b04682009-06-10 05:40:52 +08001429#endif
1430
Daniel Willmannc8188202009-08-13 03:42:07 +02001431 DEBUGP(DMM, "-> MM INFO\n");
1432
Harald Welte36fe2e82009-07-23 21:13:03 +02001433 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001434}
1435
Harald Welte36970f62009-08-12 22:56:50 +02001436/* Section 9.2.2 */
1437int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
1438{
1439 struct msgb *msg = gsm48_msgb_alloc();
1440 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1441 u_int8_t *r;
1442
1443 DEBUGP(DMM, "-> AUTH REQ\n");
1444
1445 msg->lchan = lchan;
1446 gh->proto_discr = GSM48_PDISC_MM;
1447 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
1448
1449 /* 16 bytes RAND parameters */
1450 r = msgb_put(msg, 16);
1451 if (rand)
1452 memcpy(r, rand, 16);
1453
1454 return gsm48_sendmsg(msg, NULL);
1455}
1456
1457/* Section 9.2.1 */
1458int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
1459{
1460 DEBUGP(DMM, "-> AUTH REJECT\n");
1461 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
1462}
1463
Harald Welte59b04682009-06-10 05:40:52 +08001464static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1465{
1466 DEBUGP(DMM, "-> CM SERVICE ACK\n");
1467 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
1468}
1469
1470/* 9.2.6 CM service reject */
1471static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1472 enum gsm48_reject_value value)
1473{
1474 struct msgb *msg = gsm48_msgb_alloc();
1475 struct gsm48_hdr *gh;
1476
1477 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1478
1479 msg->lchan = lchan;
1480 use_lchan(lchan);
1481
1482 gh->proto_discr = GSM48_PDISC_MM;
1483 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1484 gh->data[0] = value;
1485 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1486
Harald Welte36fe2e82009-07-23 21:13:03 +02001487 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001488}
1489
Harald Welte583ceaf2009-08-10 10:12:45 +02001490static int send_siemens_mrpci(struct gsm_lchan *lchan,
1491 u_int8_t *classmark2_lv)
1492{
1493 struct rsl_mrpci mrpci;
1494
1495 if (classmark2_lv[0] < 2)
1496 return -EINVAL;
1497
1498 mrpci.power_class = classmark2_lv[1] & 0x7;
1499 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1500 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1501 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1502
1503 return rsl_siemens_mrpci(lchan, &mrpci);
1504}
Harald Welte59b04682009-06-10 05:40:52 +08001505
1506/*
1507 * Handle CM Service Requests
1508 * a) Verify that the packet is long enough to contain the information
1509 * we require otherwsie reject with INCORRECT_MESSAGE
1510 * b) Try to parse the TMSI. If we do not have one reject
1511 * c) Check that we know the subscriber with the TMSI otherwise reject
1512 * with a HLR cause
1513 * d) Set the subscriber on the gsm_lchan and accept
1514 */
1515static int gsm48_rx_mm_serv_req(struct msgb *msg)
1516{
1517 u_int8_t mi_type;
1518 char mi_string[MI_SIZE];
1519
Harald Welte75350412009-07-23 18:46:00 +02001520 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001521 struct gsm_subscriber *subscr;
1522 struct gsm48_hdr *gh = msgb_l3(msg);
1523 struct gsm48_service_request *req =
1524 (struct gsm48_service_request *)gh->data;
1525 /* unfortunately in Phase1 the classmar2 length is variable */
1526 u_int8_t classmark2_len = gh->data[1];
1527 u_int8_t *classmark2 = gh->data+2;
1528 u_int8_t mi_len = *(classmark2 + classmark2_len);
1529 u_int8_t *mi = (classmark2 + classmark2_len + 1);
1530
1531 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
1532 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
1533 DEBUGPC(DMM, "wrong sized message\n");
1534 return gsm48_tx_mm_serv_rej(msg->lchan,
1535 GSM48_REJECT_INCORRECT_MESSAGE);
1536 }
1537
1538 if (msg->data_len < req->mi_len + 6) {
1539 DEBUGPC(DMM, "does not fit in packet\n");
1540 return gsm48_tx_mm_serv_rej(msg->lchan,
1541 GSM48_REJECT_INCORRECT_MESSAGE);
1542 }
1543
1544 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1545 if (mi_type != GSM_MI_TYPE_TMSI) {
1546 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
1547 return gsm48_tx_mm_serv_rej(msg->lchan,
1548 GSM48_REJECT_INCORRECT_MESSAGE);
1549 }
1550
1551 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1552 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
1553 req->cm_service_type, mi_type, mi_string);
1554
Harald Welte583ceaf2009-08-10 10:12:45 +02001555 if (is_siemens_bts(bts))
1556 send_siemens_mrpci(msg->lchan, classmark2-1);
1557
Harald Welte75350412009-07-23 18:46:00 +02001558 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001559
1560 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
1561 if (!subscr)
1562 return gsm48_tx_mm_serv_rej(msg->lchan,
1563 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1564
1565 if (!msg->lchan->subscr)
1566 msg->lchan->subscr = subscr;
1567 else if (msg->lchan->subscr != subscr) {
1568 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1569 subscr_put(subscr);
1570 }
1571
Harald Weltef6845a72009-07-05 14:08:13 +02001572 subscr->equipment.classmark2_len = classmark2_len;
1573 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1574 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001575
1576 return gsm48_tx_mm_serv_ack(msg->lchan);
1577}
1578
1579static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1580{
Harald Welte75350412009-07-23 18:46:00 +02001581 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001582 struct gsm48_hdr *gh = msgb_l3(msg);
1583 struct gsm48_imsi_detach_ind *idi =
1584 (struct gsm48_imsi_detach_ind *) gh->data;
1585 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1586 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001587 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001588
1589 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1590 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1591 mi_type, mi_string);
1592
1593 switch (mi_type) {
1594 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001595 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001596 break;
1597 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001598 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001599 break;
1600 case GSM_MI_TYPE_IMEI:
1601 case GSM_MI_TYPE_IMEISV:
1602 /* no sim card... FIXME: what to do ? */
1603 DEBUGPC(DMM, "unimplemented mobile identity type\n");
1604 break;
1605 default:
1606 DEBUGPC(DMM, "unknown mobile identity type\n");
1607 break;
1608 }
1609
1610 if (subscr) {
1611 subscr_update(subscr, msg->trx->bts,
1612 GSM_SUBSCRIBER_UPDATE_DETACHED);
1613 DEBUGP(DMM, "Subscriber: %s\n",
1614 subscr->name ? subscr->name : subscr->imsi);
1615 subscr_put(subscr);
1616 } else
1617 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1618
Harald Welte59b04682009-06-10 05:40:52 +08001619 return 0;
1620}
1621
1622static int gsm48_rx_mm_status(struct msgb *msg)
1623{
1624 struct gsm48_hdr *gh = msgb_l3(msg);
1625
1626 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1627
1628 return 0;
1629}
1630
1631/* Receive a GSM 04.08 Mobility Management (MM) message */
1632static int gsm0408_rcv_mm(struct msgb *msg)
1633{
1634 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte03740842009-06-10 23:11:52 +08001635 int rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08001636
1637 switch (gh->msg_type & 0xbf) {
1638 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Welte79639662009-06-27 02:58:43 +02001639 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte59b04682009-06-10 05:40:52 +08001640 rc = mm_rx_loc_upd_req(msg);
1641 break;
1642 case GSM48_MT_MM_ID_RESP:
1643 rc = mm_rx_id_resp(msg);
1644 break;
1645 case GSM48_MT_MM_CM_SERV_REQ:
1646 rc = gsm48_rx_mm_serv_req(msg);
1647 break;
1648 case GSM48_MT_MM_STATUS:
1649 rc = gsm48_rx_mm_status(msg);
1650 break;
1651 case GSM48_MT_MM_TMSI_REALL_COMPL:
1652 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1653 msg->lchan->subscr ?
1654 msg->lchan->subscr->imsi :
1655 "unknown subscriber");
1656 break;
1657 case GSM48_MT_MM_IMSI_DETACH_IND:
1658 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1659 break;
1660 case GSM48_MT_MM_CM_REEST_REQ:
1661 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1662 break;
1663 case GSM48_MT_MM_AUTH_RESP:
1664 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
1665 break;
1666 default:
1667 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1668 gh->msg_type);
1669 break;
1670 }
1671
1672 return rc;
1673}
1674
1675/* Receive a PAGING RESPONSE message from the MS */
1676static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1677{
Harald Welte75350412009-07-23 18:46:00 +02001678 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001679 struct gsm48_hdr *gh = msgb_l3(msg);
1680 u_int8_t *classmark2_lv = gh->data + 1;
1681 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1682 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
1683 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001684 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001685 struct paging_signal_data sig_data;
1686 int rc = 0;
1687
1688 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
1689 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1690 mi_type, mi_string);
Harald Welte583ceaf2009-08-10 10:12:45 +02001691
1692 if (is_siemens_bts(bts))
1693 send_siemens_mrpci(msg->lchan, classmark2_lv);
1694
Harald Welte59b04682009-06-10 05:40:52 +08001695 switch (mi_type) {
1696 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001697 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001698 break;
1699 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001700 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001701 break;
1702 }
1703
1704 if (!subscr) {
1705 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1706 /* FIXME: request id? close channel? */
1707 return -EINVAL;
1708 }
1709 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte68b7df22009-08-08 16:03:15 +02001710 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Harald Welte59b04682009-06-10 05:40:52 +08001711
Harald Weltef6845a72009-07-05 14:08:13 +02001712 subscr->equipment.classmark2_len = *classmark2_lv;
1713 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1714 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001715
1716 if (!msg->lchan->subscr) {
1717 msg->lchan->subscr = subscr;
1718 } else if (msg->lchan->subscr != subscr) {
1719 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1720 subscr_put(subscr);
1721 return -EINVAL;
1722 } else {
1723 DEBUGP(DRR, "<- Channel already owned by us\n");
1724 subscr_put(subscr);
1725 subscr = msg->lchan->subscr;
1726 }
1727
1728 sig_data.subscr = subscr;
1729 sig_data.bts = msg->lchan->ts->trx->bts;
1730 sig_data.lchan = msg->lchan;
1731
1732 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Welte876312f2009-06-10 11:21:55 +08001733
1734 /* Stop paging on the bts we received the paging response */
Harald Welte59b04682009-06-10 05:40:52 +08001735 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
1736
1737 /* FIXME: somehow signal the completion of the PAGING to
1738 * the entity that requested the paging */
1739
1740 return rc;
1741}
1742
1743static int gsm48_rx_rr_classmark(struct msgb *msg)
1744{
1745 struct gsm48_hdr *gh = msgb_l3(msg);
1746 struct gsm_subscriber *subscr = msg->lchan->subscr;
1747 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1748 u_int8_t cm2_len, cm3_len = 0;
1749 u_int8_t *cm2, *cm3 = NULL;
1750
1751 DEBUGP(DRR, "CLASSMARK CHANGE ");
1752
1753 /* classmark 2 */
1754 cm2_len = gh->data[0];
1755 cm2 = &gh->data[1];
1756 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1757
1758 if (payload_len > cm2_len + 1) {
1759 /* we must have a classmark3 */
1760 if (gh->data[cm2_len+1] != 0x20) {
1761 DEBUGPC(DRR, "ERR CM3 TAG\n");
1762 return -EINVAL;
1763 }
1764 if (cm2_len > 3) {
1765 DEBUGPC(DRR, "CM2 too long!\n");
1766 return -EINVAL;
1767 }
1768
1769 cm3_len = gh->data[cm2_len+2];
1770 cm3 = &gh->data[cm2_len+3];
1771 if (cm3_len > 14) {
1772 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1773 return -EINVAL;
1774 }
1775 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1776 }
1777 if (subscr) {
Harald Weltef6845a72009-07-05 14:08:13 +02001778 subscr->equipment.classmark2_len = cm2_len;
1779 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Welte59b04682009-06-10 05:40:52 +08001780 if (cm3) {
Harald Weltef6845a72009-07-05 14:08:13 +02001781 subscr->equipment.classmark3_len = cm3_len;
1782 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Welte59b04682009-06-10 05:40:52 +08001783 }
Harald Weltef6845a72009-07-05 14:08:13 +02001784 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001785 }
1786
Harald Welte59b04682009-06-10 05:40:52 +08001787 return 0;
1788}
1789
1790static int gsm48_rx_rr_status(struct msgb *msg)
1791{
1792 struct gsm48_hdr *gh = msgb_l3(msg);
1793
1794 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1795 rr_cause_name(gh->data[0]));
1796
1797 return 0;
1798}
1799
1800static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1801{
1802 struct gsm48_hdr *gh = msgb_l3(msg);
1803 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1804 static struct gsm_meas_rep meas_rep;
1805
Harald Welte02993682009-06-27 02:53:10 +02001806 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Welte59b04682009-06-10 05:40:52 +08001807 parse_meas_rep(&meas_rep, gh->data, payload_len);
1808 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte02993682009-06-27 02:53:10 +02001809 DEBUGPC(DMEAS, "DTX ");
Harald Welte59b04682009-06-10 05:40:52 +08001810 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte02993682009-06-27 02:53:10 +02001811 DEBUGPC(DMEAS, "BA1 ");
Harald Welte59b04682009-06-10 05:40:52 +08001812 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte02993682009-06-27 02:53:10 +02001813 DEBUGPC(DMEAS, "NOT VALID ");
Harald Welte59b04682009-06-10 05:40:52 +08001814 else
Harald Welte02993682009-06-27 02:53:10 +02001815 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Welte59b04682009-06-10 05:40:52 +08001816 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1817 meas_rep.rxqual_sub);
1818
Harald Welte02993682009-06-27 02:53:10 +02001819 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Welte59b04682009-06-10 05:40:52 +08001820
1821 /* FIXME: put the results somwhere */
1822
1823 return 0;
1824}
1825
1826/* Receive a GSM 04.08 Radio Resource (RR) message */
1827static int gsm0408_rcv_rr(struct msgb *msg)
1828{
1829 struct gsm48_hdr *gh = msgb_l3(msg);
1830 int rc = 0;
1831
1832 switch (gh->msg_type) {
1833 case GSM48_MT_RR_CLSM_CHG:
1834 rc = gsm48_rx_rr_classmark(msg);
1835 break;
1836 case GSM48_MT_RR_GPRS_SUSP_REQ:
1837 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1838 break;
1839 case GSM48_MT_RR_PAG_RESP:
1840 rc = gsm48_rr_rx_pag_resp(msg);
1841 break;
1842 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1843 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welteca745e22009-07-29 12:10:35 +02001844 /* We've successfully modified the MS side of the channel,
1845 * now go on to modify the BTS side of the channel */
Harald Welte39274f42009-07-29 15:41:29 +02001846 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte59b04682009-06-10 05:40:52 +08001847 rc = rsl_chan_mode_modify_req(msg->lchan);
1848 break;
1849 case GSM48_MT_RR_STATUS:
1850 rc = gsm48_rx_rr_status(msg);
1851 break;
1852 case GSM48_MT_RR_MEAS_REP:
1853 rc = gsm48_rx_rr_meas_rep(msg);
1854 break;
1855 default:
1856 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1857 gh->msg_type);
1858 break;
1859 }
1860
1861 return rc;
1862}
1863
Harald Welte85a163c2009-08-10 11:43:22 +02001864/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Harald Welte59b04682009-06-10 05:40:52 +08001865int gsm48_send_rr_release(struct gsm_lchan *lchan)
1866{
1867 struct msgb *msg = gsm48_msgb_alloc();
1868 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1869 u_int8_t *cause;
1870
1871 msg->lchan = lchan;
1872 gh->proto_discr = GSM48_PDISC_RR;
1873 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1874
1875 cause = msgb_put(msg, 1);
1876 cause[0] = GSM48_RR_CAUSE_NORMAL;
1877
1878 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1879 lchan->nr, lchan->type);
1880
Harald Welteafe3c232009-07-19 18:36:49 +02001881 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001882 gsm48_sendmsg(msg, NULL);
Harald Welte68b7df22009-08-08 16:03:15 +02001883 /* FIXME: Start Timer T3109 */
Harald Welteafe3c232009-07-19 18:36:49 +02001884
1885 /* Deactivate the SACCH on the BTS side */
1886 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001887}
1888
1889/* Call Control */
1890
1891/* The entire call control code is written in accordance with Figure 7.10c
1892 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1893 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1894 * it for voice */
1895
Harald Welte03740842009-06-10 23:11:52 +08001896static void new_cc_state(struct gsm_trans *trans, int state)
1897{
1898 if (state > 31 || state < 0)
1899 return;
1900
1901 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltec2189a62009-07-23 18:56:43 +02001902 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001903
Harald Weltec2189a62009-07-23 18:56:43 +02001904 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001905}
1906
1907static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001908{
1909 struct msgb *msg = gsm48_msgb_alloc();
1910 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1911 u_int8_t *cause, *call_state;
1912
Harald Welte59b04682009-06-10 05:40:52 +08001913 gh->msg_type = GSM48_MT_CC_STATUS;
1914
1915 cause = msgb_put(msg, 3);
1916 cause[0] = 2;
1917 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1918 cause[2] = 0x80 | 30; /* response to status inquiry */
1919
1920 call_state = msgb_put(msg, 1);
1921 call_state[0] = 0xc0 | 0x00;
1922
Harald Welte36fe2e82009-07-23 21:13:03 +02001923 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001924}
1925
1926static int gsm48_tx_simple(struct gsm_lchan *lchan,
1927 u_int8_t pdisc, u_int8_t msg_type)
1928{
1929 struct msgb *msg = gsm48_msgb_alloc();
1930 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1931
1932 msg->lchan = lchan;
1933
1934 gh->proto_discr = pdisc;
1935 gh->msg_type = msg_type;
1936
Harald Welte36fe2e82009-07-23 21:13:03 +02001937 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001938}
1939
Harald Welte03740842009-06-10 23:11:52 +08001940static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1941{
Harald Weltec2189a62009-07-23 18:56:43 +02001942 if (bsc_timer_pending(&trans->cc.timer)) {
1943 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1944 bsc_del_timer(&trans->cc.timer);
1945 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001946 }
1947}
1948
1949static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1950 int msg_type, struct gsm_mncc *mncc)
1951{
1952 struct msgb *msg;
1953
1954 if (trans)
1955 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02001956 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08001957 "Sending '%s' to MNCC.\n",
1958 trans->lchan->ts->trx->bts->nr,
1959 trans->lchan->ts->trx->nr,
1960 trans->lchan->ts->nr, trans->transaction_id,
1961 (trans->subscr)?(trans->subscr->extension):"-",
1962 get_mncc_name(msg_type));
1963 else
1964 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1965 "Sending '%s' to MNCC.\n",
1966 (trans->subscr)?(trans->subscr->extension):"-",
1967 get_mncc_name(msg_type));
1968 else
1969 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1970 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1971
1972 mncc->msg_type = msg_type;
1973
Harald Welte9cfc9352009-06-26 19:39:35 +02001974 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08001975 if (!msg)
1976 return -ENOMEM;
1977 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1978 msgb_enqueue(&net->upqueue, msg);
1979
1980 return 0;
1981}
1982
1983int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1984 u_int32_t callref, int location, int value)
1985{
1986 struct gsm_mncc rel;
1987
Harald Weltecb0595f2009-06-12 01:54:08 +08001988 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08001989 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001990 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08001991 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1992}
1993
Harald Weltec2189a62009-07-23 18:56:43 +02001994/* Call Control Specific transaction release.
1995 * gets called by trans_free, DO NOT CALL YOURSELF! */
1996void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08001997{
Harald Welte03740842009-06-10 23:11:52 +08001998 gsm48_stop_cc_timer(trans);
1999
2000 /* send release to L4, if callref still exists */
2001 if (trans->callref) {
2002 /* Ressource unavailable */
Harald Welte0abe5a62009-07-23 19:06:52 +02002003 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002004 GSM48_CAUSE_LOC_PRN_S_LU,
2005 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002006 }
Harald Weltec2189a62009-07-23 18:56:43 +02002007 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08002008 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltec2189a62009-07-23 18:56:43 +02002009 if (trans->lchan)
2010 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08002011}
2012
2013static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
2014
Harald Welte59b04682009-06-10 05:40:52 +08002015/* call-back from paging the B-end of the connection */
2016static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
2017 struct msgb *msg, void *_lchan, void *param)
2018{
2019 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08002020 struct gsm_subscriber *subscr = param;
2021 struct gsm_trans *transt, *tmp;
2022 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02002023
Harald Welte59b04682009-06-10 05:40:52 +08002024 if (hooknum != GSM_HOOK_RR_PAGING)
2025 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08002026
2027 if (!subscr)
2028 return -EINVAL;
2029 net = subscr->net;
2030 if (!net) {
2031 DEBUGP(DCC, "Error Network not set!\n");
2032 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002033 }
2034
Harald Welte03740842009-06-10 23:11:52 +08002035 /* check all tranactions (without lchan) for subscriber */
2036 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
2037 if (transt->subscr != subscr || transt->lchan)
2038 continue;
2039 switch (event) {
2040 case GSM_PAGING_SUCCEEDED:
2041 if (!lchan) // paranoid
2042 break;
2043 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
2044 subscr->extension);
2045 /* Assign lchan */
2046 if (!transt->lchan) {
2047 transt->lchan = lchan;
2048 use_lchan(lchan);
2049 }
2050 /* send SETUP request to called party */
Harald Weltec2189a62009-07-23 18:56:43 +02002051 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08002052 break;
2053 case GSM_PAGING_EXPIRED:
2054 DEBUGP(DCC, "Paging subscr %s expired!\n",
2055 subscr->extension);
2056 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002057 mncc_release_ind(transt->subscr->net, transt,
2058 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002059 GSM48_CAUSE_LOC_PRN_S_LU,
2060 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08002061 transt->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002062 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08002063 break;
2064 }
2065 }
Harald Welte59b04682009-06-10 05:40:52 +08002066 return 0;
2067}
2068
Harald Welte3c062072009-07-28 18:25:29 +02002069/* some other part of the code sends us a signal */
2070static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2071 void *handler_data, void *signal_data)
2072{
2073 struct gsm_lchan *lchan = signal_data;
2074 struct gsm_bts_trx_ts *ts;
2075 int rc;
2076
2077 if (subsys != SS_ABISIP)
2078 return 0;
2079
2080 /* in case we use direct BTS-to-BTS RTP */
2081 if (ipacc_rtp_direct)
2082 return 0;
2083
2084 ts = lchan->ts;
2085
2086 switch (signal) {
2087 case S_ABISIP_BIND_ACK:
2088 /* the BTS has successfully bound a TCH to a local ip/port,
2089 * which means we can connect our UDP socket to it */
2090 if (ts->abis_ip.rtp_socket) {
2091 rtp_socket_free(ts->abis_ip.rtp_socket);
2092 ts->abis_ip.rtp_socket = NULL;
2093 }
2094
2095 ts->abis_ip.rtp_socket = rtp_socket_create();
2096 if (!ts->abis_ip.rtp_socket)
2097 goto out_err;
2098
2099 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2100 ts->abis_ip.bound_ip,
2101 ts->abis_ip.bound_port);
2102 if (rc < 0)
2103 goto out_err;
2104 break;
2105 case S_ABISIP_DISC_IND:
2106 /* the BTS tells us a RTP stream has been disconnected */
2107 if (ts->abis_ip.rtp_socket) {
2108 rtp_socket_free(ts->abis_ip.rtp_socket);
2109 ts->abis_ip.rtp_socket = NULL;
2110 }
2111 break;
2112 }
2113
2114 return 0;
2115out_err:
2116 /* FIXME: do something */
2117 return 0;
2118}
2119
2120/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2121static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2122{
2123 struct gsm_bts_trx_ts *ts = lchan->ts;
2124 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2125 int rc;
2126
2127 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2128 ntohs(rs->rtp.sin_local.sin_port),
2129 ts->abis_ip.conn_id,
2130 /* FIXME: use RTP payload of bound socket, not BTS*/
2131 ts->abis_ip.rtp_payload2);
2132
2133 return rc;
2134}
2135
Harald Welte59b04682009-06-10 05:40:52 +08002136/* map two ipaccess RTP streams onto each other */
2137static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2138{
2139 struct gsm_bts *bts = lchan->ts->trx->bts;
2140 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2141 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002142 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002143
2144 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2145 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2146 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2147
2148 if (bts->type != remote_bts->type) {
2149 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2150 return -EINVAL;
2151 }
2152
2153 switch (bts->type) {
2154 case GSM_BTS_TYPE_NANOBTS_900:
2155 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002156 if (!ipacc_rtp_direct) {
2157 /* connect the TCH's to our RTP proxy */
2158 rc = ipacc_connect_proxy_bind(lchan);
2159 if (rc < 0)
2160 return rc;
2161 rc = ipacc_connect_proxy_bind(remote_lchan);
2162
2163 /* connect them with each other */
2164 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2165 remote_lchan->ts->abis_ip.rtp_socket);
2166 } else {
2167 /* directly connect TCH RTP streams to each other */
2168 ts = remote_lchan->ts;
2169 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2170 ts->abis_ip.bound_port,
2171 lchan->ts->abis_ip.conn_id,
2172 ts->abis_ip.rtp_payload2);
2173 if (rc < 0)
2174 return rc;
2175 ts = lchan->ts;
2176 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2177 ts->abis_ip.bound_port,
2178 remote_lchan->ts->abis_ip.conn_id,
2179 ts->abis_ip.rtp_payload2);
2180 }
Harald Welte59b04682009-06-10 05:40:52 +08002181 break;
2182 case GSM_BTS_TYPE_BS11:
2183 trau_mux_map_lchan(lchan, remote_lchan);
2184 break;
2185 default:
2186 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002187 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002188 break;
2189 }
2190
2191 return 0;
2192}
2193
Harald Welte03740842009-06-10 23:11:52 +08002194/* bridge channels of two transactions */
2195static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002196{
Harald Weltec2189a62009-07-23 18:56:43 +02002197 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2198 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002199
Harald Welte03740842009-06-10 23:11:52 +08002200 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002201 return -EIO;
2202
Harald Welte03740842009-06-10 23:11:52 +08002203 if (!trans1->lchan || !trans2->lchan)
2204 return -EIO;
2205
2206 /* through-connect channel */
2207 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002208}
2209
Harald Welte03740842009-06-10 23:11:52 +08002210/* enable receive of channels to upqueue */
2211static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2212{
2213 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002214
Harald Welte03740842009-06-10 23:11:52 +08002215 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002216 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002217 if (!trans)
2218 return -EIO;
2219 if (!trans->lchan)
2220 return 0;
2221
2222 // todo IPACCESS
2223 if (enable)
2224 return trau_recv_lchan(trans->lchan, data->callref);
2225 return trau_mux_unmap(NULL, data->callref);
2226}
2227
2228/* send a frame to channel */
2229static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2230{
2231 struct gsm_trans *trans;
2232
2233 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002234 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002235 if (!trans)
2236 return -EIO;
2237 if (!trans->lchan)
2238 return 0;
2239 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2240 trans->lchan->type != GSM_LCHAN_TCH_H)
2241 return 0;
2242
2243 // todo IPACCESS
2244 return trau_send_lchan(trans->lchan,
2245 (struct decoded_trau_frame *)frame->data);
2246}
2247
2248
2249static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2250{
2251 DEBUGP(DCC, "-> STATUS ENQ\n");
2252 return gsm48_cc_tx_status(trans, msg);
2253}
2254
2255static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2256static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2257
2258static void gsm48_cc_timeout(void *arg)
2259{
2260 struct gsm_trans *trans = arg;
2261 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002262 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2263 int mo_location = GSM48_CAUSE_LOC_USER;
2264 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2265 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002266 struct gsm_mncc mo_rel, l4_rel;
2267
2268 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2269 mo_rel.callref = trans->callref;
2270 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2271 l4_rel.callref = trans->callref;
2272
Harald Weltec2189a62009-07-23 18:56:43 +02002273 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002274 case 0x303:
2275 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002276 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002277 break;
2278 case 0x310:
2279 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002280 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002281 break;
2282 case 0x313:
2283 disconnect = 1;
2284 /* unknown, did not find it in the specs */
2285 break;
2286 case 0x301:
2287 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002288 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002289 break;
2290 case 0x308:
Harald Weltec2189a62009-07-23 18:56:43 +02002291 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002292 /* restart T308 a second time */
Harald Weltec2189a62009-07-23 18:56:43 +02002293 gsm48_cc_tx_release(trans, &trans->cc.msg);
2294 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002295 break; /* stay in release state */
2296 }
Harald Weltec2189a62009-07-23 18:56:43 +02002297 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002298 return;
2299// release = 1;
2300// l4_cause = 14;
2301// break;
2302 case 0x306:
2303 release = 1;
Harald Weltec2189a62009-07-23 18:56:43 +02002304 mo_cause = trans->cc.msg.cause.value;
2305 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002306 break;
2307 case 0x323:
2308 disconnect = 1;
2309 break;
2310 default:
2311 release = 1;
2312 }
2313
2314 if (release && trans->callref) {
2315 /* process release towards layer 4 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002316 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002317 l4_location, l4_cause);
2318 trans->callref = 0;
2319 }
2320
2321 if (disconnect && trans->callref) {
2322 /* process disconnect towards layer 4 */
2323 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte0abe5a62009-07-23 19:06:52 +02002324 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002325 }
2326
2327 /* process disconnect towards mobile station */
2328 if (disconnect || release) {
2329 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltec2189a62009-07-23 18:56:43 +02002330 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2331 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2332 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002333 mo_rel.cause.diag_len = 3;
2334
2335 if (disconnect)
2336 gsm48_cc_tx_disconnect(trans, &mo_rel);
2337 if (release)
2338 gsm48_cc_tx_release(trans, &mo_rel);
2339 }
2340
2341}
2342
2343static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2344 int sec, int micro)
2345{
2346 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltec2189a62009-07-23 18:56:43 +02002347 trans->cc.timer.cb = gsm48_cc_timeout;
2348 trans->cc.timer.data = trans;
2349 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2350 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002351}
2352
2353static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2354{
2355 struct gsm48_hdr *gh = msgb_l3(msg);
2356 u_int8_t msg_type = gh->msg_type & 0xbf;
2357 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2358 struct tlv_parsed tp;
2359 struct gsm_mncc setup;
2360
2361 memset(&setup, 0, sizeof(struct gsm_mncc));
2362 setup.callref = trans->callref;
2363 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2364 /* emergency setup is identified by msg_type */
2365 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2366 setup.emergency = 1;
2367
2368 /* use subscriber as calling party number */
2369 if (trans->subscr) {
2370 setup.fields |= MNCC_F_CALLING;
2371 strncpy(setup.calling.number, trans->subscr->extension,
2372 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002373 strncpy(setup.imsi, trans->subscr->imsi,
2374 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002375 }
2376 /* bearer capability */
2377 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2378 setup.fields |= MNCC_F_BEARER_CAP;
2379 decode_bearer_cap(&setup.bearer_cap,
2380 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2381 }
2382 /* facility */
2383 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2384 setup.fields |= MNCC_F_FACILITY;
2385 decode_facility(&setup.facility,
2386 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2387 }
2388 /* called party bcd number */
2389 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2390 setup.fields |= MNCC_F_CALLED;
2391 decode_called(&setup.called,
2392 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2393 }
2394 /* user-user */
2395 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2396 setup.fields |= MNCC_F_USERUSER;
2397 decode_useruser(&setup.useruser,
2398 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2399 }
2400 /* ss-version */
2401 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2402 setup.fields |= MNCC_F_SSVERSION;
2403 decode_ssversion(&setup.ssversion,
2404 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2405 }
2406 /* CLIR suppression */
2407 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2408 setup.clir.sup = 1;
2409 /* CLIR invocation */
2410 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2411 setup.clir.inv = 1;
2412 /* cc cap */
2413 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2414 setup.fields |= MNCC_F_CCCAP;
2415 decode_cccap(&setup.cccap,
2416 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2417 }
2418
Harald Welte03740842009-06-10 23:11:52 +08002419 new_cc_state(trans, GSM_CSTATE_INITIATED);
2420
2421 /* indicate setup to MNCC */
Harald Welte0abe5a62009-07-23 19:06:52 +02002422 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002423
Harald Welteca745e22009-07-29 12:10:35 +02002424 /* MNCC code will modify the channel asynchronously, we should
2425 * ipaccess-bind only after the modification has been made to the
2426 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002427 return 0;
2428}
2429
2430static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002431{
2432 struct msgb *msg = gsm48_msgb_alloc();
2433 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002434 struct gsm_mncc *setup = arg;
Harald Welte165fc332009-07-23 21:36:44 +02002435 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002436
2437 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2438
Harald Welte03740842009-06-10 23:11:52 +08002439 /* transaction id must not be assigned */
2440 if (trans->transaction_id != 0xff) { /* unasssigned */
2441 DEBUGP(DCC, "TX Setup with assigned transaction. "
2442 "This is not allowed!\n");
2443 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002444 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002445 GSM48_CAUSE_LOC_PRN_S_LU,
2446 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002447 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002448 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002449 return rc;
2450 }
2451
2452 /* Get free transaction_id */
Harald Welte165fc332009-07-23 21:36:44 +02002453 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2454 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002455 /* no free transaction ID */
Harald Welte0abe5a62009-07-23 19:06:52 +02002456 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002457 GSM48_CAUSE_LOC_PRN_S_LU,
2458 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002459 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002460 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002461 return rc;
2462 }
Harald Welte165fc332009-07-23 21:36:44 +02002463 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002464
Harald Welte59b04682009-06-10 05:40:52 +08002465 gh->msg_type = GSM48_MT_CC_SETUP;
2466
Harald Welte03740842009-06-10 23:11:52 +08002467 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002468
Harald Welte03740842009-06-10 23:11:52 +08002469 /* bearer capability */
2470 if (setup->fields & MNCC_F_BEARER_CAP)
2471 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2472 /* facility */
2473 if (setup->fields & MNCC_F_FACILITY)
2474 encode_facility(msg, 0, &setup->facility);
2475 /* progress */
2476 if (setup->fields & MNCC_F_PROGRESS)
2477 encode_progress(msg, 0, &setup->progress);
2478 /* calling party BCD number */
2479 if (setup->fields & MNCC_F_CALLING)
2480 encode_calling(msg, &setup->calling);
2481 /* called party BCD number */
2482 if (setup->fields & MNCC_F_CALLED)
2483 encode_called(msg, &setup->called);
2484 /* user-user */
2485 if (setup->fields & MNCC_F_USERUSER)
2486 encode_useruser(msg, 0, &setup->useruser);
2487 /* redirecting party BCD number */
2488 if (setup->fields & MNCC_F_REDIRECTING)
2489 encode_redirecting(msg, &setup->redirecting);
2490 /* signal */
2491 if (setup->fields & MNCC_F_SIGNAL)
2492 encode_signal(msg, setup->signal);
2493
2494 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002495
Harald Welte36fe2e82009-07-23 21:13:03 +02002496 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002497}
2498
Harald Welte03740842009-06-10 23:11:52 +08002499static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2500{
2501 struct gsm48_hdr *gh = msgb_l3(msg);
2502 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2503 struct tlv_parsed tp;
2504 struct gsm_mncc call_conf;
2505
2506 gsm48_stop_cc_timer(trans);
2507 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2508
2509 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2510 call_conf.callref = trans->callref;
2511 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2512#if 0
2513 /* repeat */
2514 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2515 call_conf.repeat = 1;
2516 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2517 call_conf.repeat = 2;
2518#endif
2519 /* bearer capability */
2520 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2521 call_conf.fields |= MNCC_F_BEARER_CAP;
2522 decode_bearer_cap(&call_conf.bearer_cap,
2523 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2524 }
2525 /* cause */
2526 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2527 call_conf.fields |= MNCC_F_CAUSE;
2528 decode_cause(&call_conf.cause,
2529 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2530 }
2531 /* cc cap */
2532 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2533 call_conf.fields |= MNCC_F_CCCAP;
2534 decode_cccap(&call_conf.cccap,
2535 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2536 }
2537
2538 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2539
Harald Welte0abe5a62009-07-23 19:06:52 +02002540 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2541 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002542}
2543
2544static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2545{
2546 struct gsm_mncc *proceeding = arg;
2547 struct msgb *msg = gsm48_msgb_alloc();
2548 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2549
Harald Welte03740842009-06-10 23:11:52 +08002550 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2551
2552 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2553
2554 /* bearer capability */
2555 if (proceeding->fields & MNCC_F_BEARER_CAP)
2556 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2557 /* facility */
2558 if (proceeding->fields & MNCC_F_FACILITY)
2559 encode_facility(msg, 0, &proceeding->facility);
2560 /* progress */
2561 if (proceeding->fields & MNCC_F_PROGRESS)
2562 encode_progress(msg, 0, &proceeding->progress);
2563
Harald Welte36fe2e82009-07-23 21:13:03 +02002564 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002565}
2566
2567static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2568{
2569 struct gsm48_hdr *gh = msgb_l3(msg);
2570 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2571 struct tlv_parsed tp;
2572 struct gsm_mncc alerting;
2573
2574 gsm48_stop_cc_timer(trans);
2575 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2576
2577 memset(&alerting, 0, sizeof(struct gsm_mncc));
2578 alerting.callref = trans->callref;
2579 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2580 /* facility */
2581 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2582 alerting.fields |= MNCC_F_FACILITY;
2583 decode_facility(&alerting.facility,
2584 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2585 }
2586
2587 /* progress */
2588 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2589 alerting.fields |= MNCC_F_PROGRESS;
2590 decode_progress(&alerting.progress,
2591 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2592 }
2593 /* ss-version */
2594 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2595 alerting.fields |= MNCC_F_SSVERSION;
2596 decode_ssversion(&alerting.ssversion,
2597 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2598 }
2599
2600 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2601
Harald Welte0abe5a62009-07-23 19:06:52 +02002602 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2603 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002604}
2605
2606static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2607{
2608 struct gsm_mncc *alerting = arg;
2609 struct msgb *msg = gsm48_msgb_alloc();
2610 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2611
Harald Welte03740842009-06-10 23:11:52 +08002612 gh->msg_type = GSM48_MT_CC_ALERTING;
2613
2614 /* facility */
2615 if (alerting->fields & MNCC_F_FACILITY)
2616 encode_facility(msg, 0, &alerting->facility);
2617 /* progress */
2618 if (alerting->fields & MNCC_F_PROGRESS)
2619 encode_progress(msg, 0, &alerting->progress);
2620 /* user-user */
2621 if (alerting->fields & MNCC_F_USERUSER)
2622 encode_useruser(msg, 0, &alerting->useruser);
2623
2624 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2625
Harald Welte36fe2e82009-07-23 21:13:03 +02002626 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002627}
2628
2629static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2630{
2631 struct gsm_mncc *progress = arg;
2632 struct msgb *msg = gsm48_msgb_alloc();
2633 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2634
Harald Welte03740842009-06-10 23:11:52 +08002635 gh->msg_type = GSM48_MT_CC_PROGRESS;
2636
2637 /* progress */
2638 encode_progress(msg, 1, &progress->progress);
2639 /* user-user */
2640 if (progress->fields & MNCC_F_USERUSER)
2641 encode_useruser(msg, 0, &progress->useruser);
2642
Harald Welte36fe2e82009-07-23 21:13:03 +02002643 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002644}
2645
2646static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2647{
2648 struct gsm_mncc *connect = arg;
2649 struct msgb *msg = gsm48_msgb_alloc();
2650 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2651
Harald Welte03740842009-06-10 23:11:52 +08002652 gh->msg_type = GSM48_MT_CC_CONNECT;
2653
2654 gsm48_stop_cc_timer(trans);
2655 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2656
2657 /* facility */
2658 if (connect->fields & MNCC_F_FACILITY)
2659 encode_facility(msg, 0, &connect->facility);
2660 /* progress */
2661 if (connect->fields & MNCC_F_PROGRESS)
2662 encode_progress(msg, 0, &connect->progress);
2663 /* connected number */
2664 if (connect->fields & MNCC_F_CONNECTED)
2665 encode_connected(msg, &connect->connected);
2666 /* user-user */
2667 if (connect->fields & MNCC_F_USERUSER)
2668 encode_useruser(msg, 0, &connect->useruser);
2669
2670 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2671
Harald Welte36fe2e82009-07-23 21:13:03 +02002672 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002673}
2674
2675static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2676{
2677 struct gsm48_hdr *gh = msgb_l3(msg);
2678 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2679 struct tlv_parsed tp;
2680 struct gsm_mncc connect;
2681
2682 gsm48_stop_cc_timer(trans);
2683
2684 memset(&connect, 0, sizeof(struct gsm_mncc));
2685 connect.callref = trans->callref;
2686 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2687 /* use subscriber as connected party number */
2688 if (trans->subscr) {
2689 connect.fields |= MNCC_F_CONNECTED;
2690 strncpy(connect.connected.number, trans->subscr->extension,
2691 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002692 strncpy(connect.imsi, trans->subscr->imsi,
2693 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002694 }
2695 /* facility */
2696 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2697 connect.fields |= MNCC_F_FACILITY;
2698 decode_facility(&connect.facility,
2699 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2700 }
2701 /* user-user */
2702 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2703 connect.fields |= MNCC_F_USERUSER;
2704 decode_useruser(&connect.useruser,
2705 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2706 }
2707 /* ss-version */
2708 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2709 connect.fields |= MNCC_F_SSVERSION;
2710 decode_ssversion(&connect.ssversion,
2711 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2712 }
2713
2714 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2715
Harald Welte0abe5a62009-07-23 19:06:52 +02002716 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002717}
2718
2719
2720static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2721{
2722 struct gsm_mncc connect_ack;
2723
2724 gsm48_stop_cc_timer(trans);
2725
2726 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2727
2728 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2729 connect_ack.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002730 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002731 &connect_ack);
2732}
2733
2734static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2735{
2736 struct msgb *msg = gsm48_msgb_alloc();
2737 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2738
Harald Welte03740842009-06-10 23:11:52 +08002739 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2740
2741 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2742
Harald Welte36fe2e82009-07-23 21:13:03 +02002743 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002744}
2745
2746static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2747{
2748 struct gsm48_hdr *gh = msgb_l3(msg);
2749 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2750 struct tlv_parsed tp;
2751 struct gsm_mncc disc;
2752
2753 gsm48_stop_cc_timer(trans);
2754
2755 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2756
2757 memset(&disc, 0, sizeof(struct gsm_mncc));
2758 disc.callref = trans->callref;
2759 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2760 /* cause */
2761 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2762 disc.fields |= MNCC_F_CAUSE;
2763 decode_cause(&disc.cause,
2764 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2765 }
2766 /* facility */
2767 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2768 disc.fields |= MNCC_F_FACILITY;
2769 decode_facility(&disc.facility,
2770 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2771 }
2772 /* user-user */
2773 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2774 disc.fields |= MNCC_F_USERUSER;
2775 decode_useruser(&disc.useruser,
2776 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2777 }
2778 /* ss-version */
2779 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2780 disc.fields |= MNCC_F_SSVERSION;
2781 decode_ssversion(&disc.ssversion,
2782 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2783 }
2784
Harald Welte0abe5a62009-07-23 19:06:52 +02002785 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002786
2787}
2788
Harald Weltebbc636a2009-06-11 14:23:20 +08002789static struct gsm_mncc_cause default_cause = {
2790 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2791 .coding = 0,
2792 .rec = 0,
2793 .rec_val = 0,
2794 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2795 .diag_len = 0,
2796 .diag = { 0 },
2797};
Harald Welte03740842009-06-10 23:11:52 +08002798
2799static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2800{
2801 struct gsm_mncc *disc = arg;
2802 struct msgb *msg = gsm48_msgb_alloc();
2803 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2804
Harald Welte03740842009-06-10 23:11:52 +08002805 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2806
2807 gsm48_stop_cc_timer(trans);
2808 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2809
2810 /* cause */
2811 if (disc->fields & MNCC_F_CAUSE)
2812 encode_cause(msg, 1, &disc->cause);
2813 else
2814 encode_cause(msg, 1, &default_cause);
2815
2816 /* facility */
2817 if (disc->fields & MNCC_F_FACILITY)
2818 encode_facility(msg, 0, &disc->facility);
2819 /* progress */
2820 if (disc->fields & MNCC_F_PROGRESS)
2821 encode_progress(msg, 0, &disc->progress);
2822 /* user-user */
2823 if (disc->fields & MNCC_F_USERUSER)
2824 encode_useruser(msg, 0, &disc->useruser);
2825
2826 /* store disconnect cause for T306 expiry */
Harald Weltec2189a62009-07-23 18:56:43 +02002827 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002828
2829 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2830
Harald Welte36fe2e82009-07-23 21:13:03 +02002831 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002832}
2833
2834static int gsm48_cc_rx_release(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 rel;
2840 int rc;
2841
2842 gsm48_stop_cc_timer(trans);
2843
2844 memset(&rel, 0, sizeof(struct gsm_mncc));
2845 rel.callref = trans->callref;
2846 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2847 /* cause */
2848 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2849 rel.fields |= MNCC_F_CAUSE;
2850 decode_cause(&rel.cause,
2851 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2852 }
2853 /* facility */
2854 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2855 rel.fields |= MNCC_F_FACILITY;
2856 decode_facility(&rel.facility,
2857 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2858 }
2859 /* user-user */
2860 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2861 rel.fields |= MNCC_F_USERUSER;
2862 decode_useruser(&rel.useruser,
2863 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2864 }
2865 /* ss-version */
2866 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2867 rel.fields |= MNCC_F_SSVERSION;
2868 decode_ssversion(&rel.ssversion,
2869 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2870 }
2871
Harald Weltec2189a62009-07-23 18:56:43 +02002872 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002873 /* release collision 5.4.5 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002874 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002875 } else {
Harald Welte0abe5a62009-07-23 19:06:52 +02002876 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002877 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte0abe5a62009-07-23 19:06:52 +02002878 GSM48_MT_CC_RELEASE_COMPL);
2879 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002880 }
2881
2882 new_cc_state(trans, GSM_CSTATE_NULL);
2883
2884 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002885 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002886
2887 return rc;
2888}
2889
2890static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2891{
2892 struct gsm_mncc *rel = arg;
2893 struct msgb *msg = gsm48_msgb_alloc();
2894 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2895
Harald Welte03740842009-06-10 23:11:52 +08002896 gh->msg_type = GSM48_MT_CC_RELEASE;
2897
2898 trans->callref = 0;
2899
2900 gsm48_stop_cc_timer(trans);
2901 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2902
2903 /* cause */
2904 if (rel->fields & MNCC_F_CAUSE)
2905 encode_cause(msg, 0, &rel->cause);
2906 /* facility */
2907 if (rel->fields & MNCC_F_FACILITY)
2908 encode_facility(msg, 0, &rel->facility);
2909 /* user-user */
2910 if (rel->fields & MNCC_F_USERUSER)
2911 encode_useruser(msg, 0, &rel->useruser);
2912
Harald Weltec2189a62009-07-23 18:56:43 +02002913 trans->cc.T308_second = 0;
2914 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002915
Harald Weltec2189a62009-07-23 18:56:43 +02002916 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002917 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2918
Harald Welte36fe2e82009-07-23 21:13:03 +02002919 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002920}
2921
2922static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2923{
2924 struct gsm48_hdr *gh = msgb_l3(msg);
2925 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2926 struct tlv_parsed tp;
2927 struct gsm_mncc rel;
2928 int rc = 0;
2929
2930 gsm48_stop_cc_timer(trans);
2931
2932 memset(&rel, 0, sizeof(struct gsm_mncc));
2933 rel.callref = trans->callref;
2934 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2935 /* cause */
2936 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2937 rel.fields |= MNCC_F_CAUSE;
2938 decode_cause(&rel.cause,
2939 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2940 }
2941 /* facility */
2942 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2943 rel.fields |= MNCC_F_FACILITY;
2944 decode_facility(&rel.facility,
2945 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2946 }
2947 /* user-user */
2948 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2949 rel.fields |= MNCC_F_USERUSER;
2950 decode_useruser(&rel.useruser,
2951 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2952 }
2953 /* ss-version */
2954 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2955 rel.fields |= MNCC_F_SSVERSION;
2956 decode_ssversion(&rel.ssversion,
2957 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2958 }
2959
2960 if (trans->callref) {
Harald Weltec2189a62009-07-23 18:56:43 +02002961 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08002962 case GSM_CSTATE_CALL_PRESENT:
Harald Welte0abe5a62009-07-23 19:06:52 +02002963 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002964 MNCC_REJ_IND, &rel);
2965 break;
2966 case GSM_CSTATE_RELEASE_REQ:
Harald Welte0abe5a62009-07-23 19:06:52 +02002967 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002968 MNCC_REL_CNF, &rel);
2969 break;
2970 default:
Harald Welte0abe5a62009-07-23 19:06:52 +02002971 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002972 MNCC_REL_IND, &rel);
2973 }
2974 }
2975
2976 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002977 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002978
2979 return rc;
2980}
2981
2982static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2983{
2984 struct gsm_mncc *rel = arg;
2985 struct msgb *msg = gsm48_msgb_alloc();
2986 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2987
Harald Welte03740842009-06-10 23:11:52 +08002988 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2989
2990 trans->callref = 0;
2991
2992 gsm48_stop_cc_timer(trans);
2993
2994 /* cause */
2995 if (rel->fields & MNCC_F_CAUSE)
2996 encode_cause(msg, 0, &rel->cause);
2997 /* facility */
2998 if (rel->fields & MNCC_F_FACILITY)
2999 encode_facility(msg, 0, &rel->facility);
3000 /* user-user */
3001 if (rel->fields & MNCC_F_USERUSER)
3002 encode_useruser(msg, 0, &rel->useruser);
3003
Harald Weltec2189a62009-07-23 18:56:43 +02003004 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003005
Harald Welte36fe2e82009-07-23 21:13:03 +02003006 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003007}
3008
3009static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
3010{
3011 struct gsm48_hdr *gh = msgb_l3(msg);
3012 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3013 struct tlv_parsed tp;
3014 struct gsm_mncc fac;
3015
3016 memset(&fac, 0, sizeof(struct gsm_mncc));
3017 fac.callref = trans->callref;
3018 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
3019 /* facility */
3020 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
3021 fac.fields |= MNCC_F_FACILITY;
3022 decode_facility(&fac.facility,
3023 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
3024 }
3025 /* ss-version */
3026 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3027 fac.fields |= MNCC_F_SSVERSION;
3028 decode_ssversion(&fac.ssversion,
3029 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3030 }
3031
Harald Welte0abe5a62009-07-23 19:06:52 +02003032 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08003033}
3034
3035static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
3036{
3037 struct gsm_mncc *fac = arg;
3038 struct msgb *msg = gsm48_msgb_alloc();
3039 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3040
Harald Welte03740842009-06-10 23:11:52 +08003041 gh->msg_type = GSM48_MT_CC_FACILITY;
3042
3043 /* facility */
3044 encode_facility(msg, 1, &fac->facility);
3045
Harald Welte36fe2e82009-07-23 21:13:03 +02003046 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003047}
3048
3049static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
3050{
3051 struct gsm_mncc hold;
3052
3053 memset(&hold, 0, sizeof(struct gsm_mncc));
3054 hold.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003055 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08003056}
3057
3058static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3059{
3060 struct msgb *msg = gsm48_msgb_alloc();
3061 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3062
Harald Welte03740842009-06-10 23:11:52 +08003063 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3064
Harald Welte36fe2e82009-07-23 21:13:03 +02003065 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003066}
3067
3068static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3069{
3070 struct gsm_mncc *hold_rej = arg;
3071 struct msgb *msg = gsm48_msgb_alloc();
3072 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3073
Harald Welte03740842009-06-10 23:11:52 +08003074 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3075
3076 /* cause */
3077 if (hold_rej->fields & MNCC_F_CAUSE)
3078 encode_cause(msg, 1, &hold_rej->cause);
3079 else
3080 encode_cause(msg, 1, &default_cause);
3081
Harald Welte36fe2e82009-07-23 21:13:03 +02003082 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003083}
3084
3085static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3086{
3087 struct gsm_mncc retrieve;
3088
3089 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3090 retrieve.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003091 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3092 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08003093}
3094
3095static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3096{
3097 struct msgb *msg = gsm48_msgb_alloc();
3098 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3099
Harald Welte03740842009-06-10 23:11:52 +08003100 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3101
Harald Welte36fe2e82009-07-23 21:13:03 +02003102 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003103}
3104
3105static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3106{
3107 struct gsm_mncc *retrieve_rej = arg;
3108 struct msgb *msg = gsm48_msgb_alloc();
3109 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3110
Harald Welte03740842009-06-10 23:11:52 +08003111 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3112
3113 /* cause */
3114 if (retrieve_rej->fields & MNCC_F_CAUSE)
3115 encode_cause(msg, 1, &retrieve_rej->cause);
3116 else
3117 encode_cause(msg, 1, &default_cause);
3118
Harald Welte36fe2e82009-07-23 21:13:03 +02003119 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003120}
3121
3122static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3123{
3124 struct gsm48_hdr *gh = msgb_l3(msg);
3125 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3126 struct tlv_parsed tp;
3127 struct gsm_mncc dtmf;
3128
3129 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3130 dtmf.callref = trans->callref;
3131 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3132 /* keypad facility */
3133 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3134 dtmf.fields |= MNCC_F_KEYPAD;
3135 decode_keypad(&dtmf.keypad,
3136 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3137 }
3138
Harald Welte0abe5a62009-07-23 19:06:52 +02003139 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003140}
3141
3142static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3143{
3144 struct gsm_mncc *dtmf = arg;
3145 struct msgb *msg = gsm48_msgb_alloc();
3146 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3147
Harald Welte03740842009-06-10 23:11:52 +08003148 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3149
3150 /* keypad */
3151 if (dtmf->fields & MNCC_F_KEYPAD)
3152 encode_keypad(msg, dtmf->keypad);
3153
Harald Welte36fe2e82009-07-23 21:13:03 +02003154 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003155}
3156
3157static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3158{
3159 struct gsm_mncc *dtmf = arg;
3160 struct msgb *msg = gsm48_msgb_alloc();
3161 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3162
Harald Welte03740842009-06-10 23:11:52 +08003163 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3164
3165 /* cause */
3166 if (dtmf->fields & MNCC_F_CAUSE)
3167 encode_cause(msg, 1, &dtmf->cause);
3168 else
3169 encode_cause(msg, 1, &default_cause);
3170
Harald Welte36fe2e82009-07-23 21:13:03 +02003171 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003172}
3173
3174static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3175{
3176 struct msgb *msg = gsm48_msgb_alloc();
3177 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3178
Harald Welte03740842009-06-10 23:11:52 +08003179 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3180
Harald Welte36fe2e82009-07-23 21:13:03 +02003181 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003182}
3183
3184static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3185{
3186 struct gsm_mncc dtmf;
3187
3188 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3189 dtmf.callref = trans->callref;
3190
Harald Welte0abe5a62009-07-23 19:06:52 +02003191 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003192}
3193
3194static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3195{
3196 struct gsm48_hdr *gh = msgb_l3(msg);
3197 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3198 struct tlv_parsed tp;
3199 struct gsm_mncc modify;
3200
3201 memset(&modify, 0, sizeof(struct gsm_mncc));
3202 modify.callref = trans->callref;
3203 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3204 /* bearer capability */
3205 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3206 modify.fields |= MNCC_F_BEARER_CAP;
3207 decode_bearer_cap(&modify.bearer_cap,
3208 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3209 }
3210
3211 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3212
Harald Welte0abe5a62009-07-23 19:06:52 +02003213 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003214}
3215
3216static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3217{
3218 struct gsm_mncc *modify = arg;
3219 struct msgb *msg = gsm48_msgb_alloc();
3220 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3221
Harald Welte03740842009-06-10 23:11:52 +08003222 gh->msg_type = GSM48_MT_CC_MODIFY;
3223
3224 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3225
3226 /* bearer capability */
3227 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3228
3229 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3230
Harald Welte36fe2e82009-07-23 21:13:03 +02003231 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003232}
3233
3234static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3235{
3236 struct gsm48_hdr *gh = msgb_l3(msg);
3237 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3238 struct tlv_parsed tp;
3239 struct gsm_mncc modify;
3240
3241 gsm48_stop_cc_timer(trans);
3242
3243 memset(&modify, 0, sizeof(struct gsm_mncc));
3244 modify.callref = trans->callref;
3245 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3246 /* bearer capability */
3247 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3248 modify.fields |= MNCC_F_BEARER_CAP;
3249 decode_bearer_cap(&modify.bearer_cap,
3250 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3251 }
3252
3253 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3254
Harald Welte0abe5a62009-07-23 19:06:52 +02003255 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003256}
3257
3258static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3259{
3260 struct gsm_mncc *modify = arg;
3261 struct msgb *msg = gsm48_msgb_alloc();
3262 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3263
Harald Welte03740842009-06-10 23:11:52 +08003264 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3265
3266 /* bearer capability */
3267 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3268
3269 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3270
Harald Welte36fe2e82009-07-23 21:13:03 +02003271 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003272}
3273
3274static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3275{
3276 struct gsm48_hdr *gh = msgb_l3(msg);
3277 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3278 struct tlv_parsed tp;
3279 struct gsm_mncc modify;
3280
3281 gsm48_stop_cc_timer(trans);
3282
3283 memset(&modify, 0, sizeof(struct gsm_mncc));
3284 modify.callref = trans->callref;
3285 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3286 /* bearer capability */
3287 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3288 modify.fields |= GSM48_IE_BEARER_CAP;
3289 decode_bearer_cap(&modify.bearer_cap,
3290 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3291 }
3292 /* cause */
3293 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3294 modify.fields |= MNCC_F_CAUSE;
3295 decode_cause(&modify.cause,
3296 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3297 }
3298
3299 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3300
Harald Welte0abe5a62009-07-23 19:06:52 +02003301 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003302}
3303
3304static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3305{
3306 struct gsm_mncc *modify = arg;
3307 struct msgb *msg = gsm48_msgb_alloc();
3308 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3309
Harald Welte03740842009-06-10 23:11:52 +08003310 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3311
3312 /* bearer capability */
3313 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3314 /* cause */
3315 encode_cause(msg, 1, &modify->cause);
3316
3317 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3318
Harald Welte36fe2e82009-07-23 21:13:03 +02003319 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003320}
3321
3322static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3323{
3324 struct gsm_mncc *notify = arg;
3325 struct msgb *msg = gsm48_msgb_alloc();
3326 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3327
Harald Welte03740842009-06-10 23:11:52 +08003328 gh->msg_type = GSM48_MT_CC_NOTIFY;
3329
3330 /* notify */
3331 encode_notify(msg, notify->notify);
3332
Harald Welte36fe2e82009-07-23 21:13:03 +02003333 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003334}
3335
3336static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3337{
3338 struct gsm48_hdr *gh = msgb_l3(msg);
3339 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3340// struct tlv_parsed tp;
3341 struct gsm_mncc notify;
3342
3343 memset(&notify, 0, sizeof(struct gsm_mncc));
3344 notify.callref = trans->callref;
3345// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3346 if (payload_len >= 1)
3347 decode_notify(&notify.notify, gh->data);
3348
Harald Welte0abe5a62009-07-23 19:06:52 +02003349 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003350}
3351
3352static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3353{
3354 struct gsm_mncc *user = arg;
3355 struct msgb *msg = gsm48_msgb_alloc();
3356 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3357
Harald Welte03740842009-06-10 23:11:52 +08003358 gh->msg_type = GSM48_MT_CC_USER_INFO;
3359
3360 /* user-user */
3361 if (user->fields & MNCC_F_USERUSER)
3362 encode_useruser(msg, 1, &user->useruser);
3363 /* more data */
3364 if (user->more)
3365 encode_more(msg);
3366
Harald Welte36fe2e82009-07-23 21:13:03 +02003367 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003368}
3369
3370static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3371{
3372 struct gsm48_hdr *gh = msgb_l3(msg);
3373 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3374 struct tlv_parsed tp;
3375 struct gsm_mncc user;
3376
3377 memset(&user, 0, sizeof(struct gsm_mncc));
3378 user.callref = trans->callref;
3379 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3380 /* user-user */
3381 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3382 user.fields |= MNCC_F_USERUSER;
3383 decode_useruser(&user.useruser,
3384 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3385 }
3386 /* more data */
3387 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3388 user.more = 1;
3389
Harald Welte0abe5a62009-07-23 19:06:52 +02003390 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003391}
3392
3393static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3394{
3395 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003396 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003397
Harald Welteca745e22009-07-29 12:10:35 +02003398 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3399 if (rc < 0)
3400 return rc;
3401
3402 /* FIXME: we not only need to do this after mode modify, but
3403 * also after channel activation */
3404 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3405 mode->lchan_mode != GSM48_CMODE_SIGN)
3406 rc = rsl_ipacc_bind(trans->lchan);
3407
3408 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003409}
3410
3411static struct downstate {
3412 u_int32_t states;
3413 int type;
3414 int (*rout) (struct gsm_trans *trans, void *arg);
3415} downstatelist[] = {
3416 /* mobile originating call establishment */
3417 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3418 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3419 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3420 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3421 {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 */
3422 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3423 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3424 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3425 /* mobile terminating call establishment */
3426 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3427 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3428 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3429 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3430 /* signalling during call */
3431 {SBIT(GSM_CSTATE_ACTIVE),
3432 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3433 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3434 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3435 {ALL_STATES,
3436 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3437 {ALL_STATES,
3438 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3439 {ALL_STATES,
3440 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3441 {SBIT(GSM_CSTATE_ACTIVE),
3442 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3443 {SBIT(GSM_CSTATE_ACTIVE),
3444 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3445 {SBIT(GSM_CSTATE_ACTIVE),
3446 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3447 {SBIT(GSM_CSTATE_ACTIVE),
3448 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3449 {SBIT(GSM_CSTATE_ACTIVE),
3450 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3451 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3452 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3453 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3454 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3455 {SBIT(GSM_CSTATE_ACTIVE),
3456 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3457 /* clearing */
3458 {SBIT(GSM_CSTATE_INITIATED),
3459 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3460 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3461 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3462 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3463 MNCC_REL_REQ, gsm48_cc_tx_release},
3464 /* special */
3465 {ALL_STATES,
3466 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3467};
3468
3469#define DOWNSLLEN \
3470 (sizeof(downstatelist) / sizeof(struct downstate))
3471
3472
3473int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3474{
Harald Welteaa60edb2009-08-09 18:52:33 +02003475 int i, rc = 0;
Harald Welte03740842009-06-10 23:11:52 +08003476 struct gsm_trans *trans = NULL, *transt;
3477 struct gsm_subscriber *subscr;
Harald Welteaa60edb2009-08-09 18:52:33 +02003478 struct gsm_lchan *lchan = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003479 struct gsm_bts *bts = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003480 struct gsm_mncc *data = arg, rel;
3481
3482 /* handle special messages */
3483 switch(msg_type) {
3484 case MNCC_BRIDGE:
3485 return tch_bridge(net, arg);
3486 case MNCC_FRAME_DROP:
3487 return tch_recv(net, arg, 0);
3488 case MNCC_FRAME_RECV:
3489 return tch_recv(net, arg, 1);
3490 case GSM_TRAU_FRAME:
3491 return tch_frame(net, arg);
3492 }
3493
3494 memset(&rel, 0, sizeof(struct gsm_mncc));
3495 rel.callref = data->callref;
3496
3497 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02003498 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003499
3500 /* Callref unknown */
3501 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003502 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003503 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3504 "Received '%s' from MNCC with "
3505 "unknown callref %d\n", data->called.number,
3506 get_mncc_name(msg_type), data->callref);
3507 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003508 return mncc_release_ind(net, NULL, data->callref,
3509 GSM48_CAUSE_LOC_PRN_S_LU,
3510 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003511 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003512 if (!data->called.number[0] && !data->imsi[0]) {
3513 DEBUGP(DCC, "(bts - trx - ts - ti) "
3514 "Received '%s' from MNCC with "
3515 "no number or IMSI\n", get_mncc_name(msg_type));
3516 /* Invalid number */
3517 return mncc_release_ind(net, NULL, data->callref,
3518 GSM48_CAUSE_LOC_PRN_S_LU,
3519 GSM48_CC_CAUSE_INV_NR_FORMAT);
3520 }
Harald Welte03740842009-06-10 23:11:52 +08003521 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003522 if (data->called.number[0])
Harald Welte75350412009-07-23 18:46:00 +02003523 subscr = subscr_get_by_extension(net,
3524 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003525 else
Harald Welte75350412009-07-23 18:46:00 +02003526 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003527 /* If subscriber is not found */
3528 if (!subscr) {
3529 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3530 "Received '%s' from MNCC with "
3531 "unknown subscriber %s\n", data->called.number,
3532 get_mncc_name(msg_type), data->called.number);
3533 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003534 return mncc_release_ind(net, NULL, data->callref,
3535 GSM48_CAUSE_LOC_PRN_S_LU,
3536 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003537 }
3538 /* If subscriber is not "attached" */
3539 if (!subscr->lac) {
3540 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3541 "Received '%s' from MNCC with "
3542 "detached subscriber %s\n", data->called.number,
3543 get_mncc_name(msg_type), data->called.number);
3544 subscr_put(subscr);
3545 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003546 return mncc_release_ind(net, NULL, data->callref,
3547 GSM48_CAUSE_LOC_PRN_S_LU,
3548 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003549 }
3550 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003551 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3552 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003553 DEBUGP(DCC, "No memory for trans.\n");
3554 subscr_put(subscr);
3555 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003556 mncc_release_ind(net, NULL, data->callref,
3557 GSM48_CAUSE_LOC_PRN_S_LU,
3558 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003559 return -ENOMEM;
3560 }
Harald Welte03740842009-06-10 23:11:52 +08003561 /* Find lchan */
Harald Welteaa60edb2009-08-09 18:52:33 +02003562 lchan = lchan_for_subscr(subscr);
Harald Welte03740842009-06-10 23:11:52 +08003563 /* If subscriber has no lchan */
3564 if (!lchan) {
3565 /* find transaction with this subscriber already paging */
3566 llist_for_each_entry(transt, &net->trans_list, entry) {
3567 /* Transaction of our lchan? */
3568 if (transt == trans ||
3569 transt->subscr != subscr)
3570 continue;
3571 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3572 "Received '%s' from MNCC with "
3573 "unallocated channel, paging already "
3574 "started.\n", bts->nr,
3575 data->called.number,
3576 get_mncc_name(msg_type));
3577 return 0;
3578 }
3579 /* store setup informations until paging was successfull */
Harald Weltec2189a62009-07-23 18:56:43 +02003580 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte2a3a81b2009-08-01 19:31:47 +02003581 /* Trigger paging */
3582 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3583 setup_trig_pag_evt, subscr);
Harald Welte03740842009-06-10 23:11:52 +08003584 return 0;
3585 }
3586 /* Assign lchan */
3587 trans->lchan = lchan;
3588 use_lchan(lchan);
3589 }
3590 lchan = trans->lchan;
3591
3592 /* if paging did not respond yet */
3593 if (!lchan) {
3594 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3595 "Received '%s' from MNCC in paging state\n",
3596 (trans->subscr)?(trans->subscr->extension):"-",
3597 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003598 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3599 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003600 if (msg_type == MNCC_REL_REQ)
3601 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3602 else
3603 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3604 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003605 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003606 return rc;
3607 }
3608
3609 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3610 "Received '%s' from MNCC in state %d (%s)\n",
3611 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3612 trans->transaction_id,
3613 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003614 get_mncc_name(msg_type), trans->cc.state,
3615 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003616
3617 /* Find function for current state and message */
3618 for (i = 0; i < DOWNSLLEN; i++)
3619 if ((msg_type == downstatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003620 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003621 break;
3622 if (i == DOWNSLLEN) {
3623 DEBUGP(DCC, "Message unhandled at this state.\n");
3624 return 0;
3625 }
3626
3627 rc = downstatelist[i].rout(trans, arg);
3628
3629 return rc;
3630}
3631
3632
3633static struct datastate {
3634 u_int32_t states;
3635 int type;
3636 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3637} datastatelist[] = {
3638 /* mobile originating call establishment */
3639 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3640 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3641 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3642 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3643 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3644 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3645 /* mobile terminating call establishment */
3646 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3647 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3648 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3649 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3650 {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 */
3651 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3652 /* signalling during call */
3653 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3654 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3655 {SBIT(GSM_CSTATE_ACTIVE),
3656 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3657 {ALL_STATES,
3658 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3659 {ALL_STATES,
3660 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3661 {ALL_STATES,
3662 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3663 {SBIT(GSM_CSTATE_ACTIVE),
3664 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3665 {SBIT(GSM_CSTATE_ACTIVE),
3666 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3667 {SBIT(GSM_CSTATE_ACTIVE),
3668 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3669 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3670 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3671 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3672 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3673 {SBIT(GSM_CSTATE_ACTIVE),
3674 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3675 /* clearing */
3676 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3677 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3678 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3679 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3680 {ALL_STATES, /* 5.4.3.4 */
3681 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3682};
3683
3684#define DATASLLEN \
3685 (sizeof(datastatelist) / sizeof(struct datastate))
3686
Harald Welte59b04682009-06-10 05:40:52 +08003687static int gsm0408_rcv_cc(struct msgb *msg)
3688{
3689 struct gsm48_hdr *gh = msgb_l3(msg);
3690 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003691 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003692 struct gsm_lchan *lchan = msg->lchan;
Harald Weltec2189a62009-07-23 18:56:43 +02003693 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003694 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003695
Harald Welte03740842009-06-10 23:11:52 +08003696 if (msg_type & 0x80) {
3697 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3698 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003699 }
Harald Welte03740842009-06-10 23:11:52 +08003700
3701 /* Find transaction */
Harald Welte0d824162009-07-23 21:58:40 +02003702 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltec2189a62009-07-23 18:56:43 +02003703
Harald Welte4861c822009-07-23 21:21:14 +02003704 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003705 "Received '%s' from MS in state %d (%s)\n",
3706 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3707 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003708 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3709 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003710
3711 /* Create transaction */
3712 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003713 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003714 "creating new trans.\n", transaction_id);
3715 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003716 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3717 transaction_id, new_callref++);
3718 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003719 DEBUGP(DCC, "No memory for trans.\n");
3720 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003721 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003722 GSM48_MT_CC_RELEASE_COMPL);
3723 return -ENOMEM;
3724 }
Harald Welte03740842009-06-10 23:11:52 +08003725 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003726 trans->lchan = lchan;
3727 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003728 }
3729
3730 /* find function for current state and message */
3731 for (i = 0; i < DATASLLEN; i++)
3732 if ((msg_type == datastatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003733 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003734 break;
3735 if (i == DATASLLEN) {
3736 DEBUGP(DCC, "Message unhandled at this state.\n");
3737 return 0;
3738 }
3739
3740 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003741
3742 return rc;
3743}
3744
3745/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3746int gsm0408_rcvmsg(struct msgb *msg)
3747{
3748 struct gsm48_hdr *gh = msgb_l3(msg);
3749 u_int8_t pdisc = gh->proto_discr & 0x0f;
3750 int rc = 0;
3751
3752 switch (pdisc) {
3753 case GSM48_PDISC_CC:
3754 rc = gsm0408_rcv_cc(msg);
3755 break;
3756 case GSM48_PDISC_MM:
3757 rc = gsm0408_rcv_mm(msg);
3758 break;
3759 case GSM48_PDISC_RR:
3760 rc = gsm0408_rcv_rr(msg);
3761 break;
3762 case GSM48_PDISC_SMS:
3763 rc = gsm0411_rcv_sms(msg);
3764 break;
3765 case GSM48_PDISC_MM_GPRS:
3766 case GSM48_PDISC_SM_GPRS:
3767 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3768 pdisc);
3769 break;
3770 default:
3771 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3772 pdisc);
3773 break;
3774 }
3775
3776 return rc;
3777}
3778
Harald Welte59b04682009-06-10 05:40:52 +08003779/* Section 9.1.8 / Table 9.9 */
3780struct chreq {
3781 u_int8_t val;
3782 u_int8_t mask;
3783 enum chreq_type type;
3784};
3785
3786/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3787static const struct chreq chreq_type_neci1[] = {
3788 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3789 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3790 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3791 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3792 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3793 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3794 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3795 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3796 { 0x10, 0xf0, CHREQ_T_SDCCH },
3797 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3798 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3799 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3800};
3801
3802/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3803static const struct chreq chreq_type_neci0[] = {
3804 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3805 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3806 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3807 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3808 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3809 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3810 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3811 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3812};
3813
3814static const enum gsm_chan_t ctype_by_chreq[] = {
3815 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3816 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3817 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3818 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3819 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3820 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3821 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3822 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3823 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3824 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3825 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3826 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3827};
3828
3829static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3830 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3831 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3832 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3833 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3834 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3835 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3836 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3837 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3838 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3839 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3840 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3841 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3842};
3843
3844enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3845{
3846 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003847 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003848
Harald Welte1ab707e2009-08-10 02:14:46 +02003849 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3850 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003851 if ((ra & chr->mask) == chr->val)
3852 return ctype_by_chreq[chr->type];
3853 }
3854 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3855 return GSM_LCHAN_SDCCH;
3856}
3857
3858enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3859{
3860 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003861 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003862
Harald Welte1ab707e2009-08-10 02:14:46 +02003863 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3864 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003865 if ((ra & chr->mask) == chr->val)
3866 return reason_by_chreq[chr->type];
3867 }
3868 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3869 return GSM_CHREQ_REASON_OTHER;
3870}
Harald Welte03740842009-06-10 23:11:52 +08003871
3872/* dequeue messages to layer 4 */
3873int bsc_upqueue(struct gsm_network *net)
3874{
3875 struct gsm_mncc *mncc;
3876 struct msgb *msg;
3877 int work = 0;
3878
3879 if (net)
3880 while ((msg = msgb_dequeue(&net->upqueue))) {
3881 mncc = (struct gsm_mncc *)msg->data;
3882 if (net->mncc_recv)
3883 net->mncc_recv(net, mncc->msg_type, mncc);
3884 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003885 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003886 }
3887
3888 return work;
3889}
Harald Weltec2189a62009-07-23 18:56:43 +02003890
Harald Welte3c062072009-07-28 18:25:29 +02003891/*
3892 * This will be ran by the linker when loading the DSO. We use it to
3893 * do system initialization, e.g. registration of signal handlers.
3894 */
3895static __attribute__((constructor)) void on_dso_load_0408(void)
3896{
3897 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3898 "loc_updating_oper");
3899 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3900 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3901}