blob: ddbcd6978fec1baa1a1a45db0eaa61d4ec0b876a [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>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
42#include <openbsc/chan_alloc.h>
43#include <openbsc/paging.h>
44#include <openbsc/signal.h>
45#include <openbsc/trau_frame.h>
46#include <openbsc/trau_mux.h>
Harald Welte3c062072009-07-28 18:25:29 +020047#include <openbsc/rtp_proxy.h>
Harald Weltea8379772009-06-20 22:36:41 +020048#include <openbsc/talloc.h>
Harald Weltec2189a62009-07-23 18:56:43 +020049#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080050
51#define GSM48_ALLOC_SIZE 1024
52#define GSM48_ALLOC_HEADROOM 128
53
Harald Welteb8a18b52009-06-10 12:08:54 +080054#define GSM_MAX_FACILITY 128
55#define GSM_MAX_SSVERSION 128
56#define GSM_MAX_USERUSER 128
57
Harald Weltea8379772009-06-20 22:36:41 +020058static void *tall_locop_ctx;
Harald Weltea8379772009-06-20 22:36:41 +020059
Harald Welte3c062072009-07-28 18:25:29 +020060/* should ip.access BTS use direct RTP streams between each other (1),
61 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
62int ipacc_rtp_direct = 1;
63
Harald Welte59b04682009-06-10 05:40:52 +080064static const struct tlv_definition rsl_att_tlvdef = {
65 .def = {
66 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
67 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
69 [GSM48_IE_UTC] = { TLV_TYPE_TV },
70 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
71 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
72
73 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
74 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
75 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
76 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
77 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
78 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
79 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welteb8a18b52009-06-10 12:08:54 +080080 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte59b04682009-06-10 05:40:52 +080081 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
82 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welteb8a18b52009-06-10 12:08:54 +080083 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
84 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte59b04682009-06-10 05:40:52 +080085 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
86 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
89 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
91 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
92 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
94 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
95 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
96 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
98 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welteb8a18b52009-06-10 12:08:54 +080099 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
100 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte59b04682009-06-10 05:40:52 +0800101 /* FIXME: more elements */
102 },
103};
104
105static const char *rr_cause_names[] = {
106 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
107 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
108 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
109 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
110 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
111 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
112 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
113 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
114 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
115 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
116 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
117 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
118 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
119 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
120 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
121 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
122 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
123};
124
Harald Welte03740842009-06-10 23:11:52 +0800125static const char *cc_state_names[] = {
126 "NULL",
127 "INITIATED",
128 "illegal state 2",
129 "MO_CALL_PROC",
130 "CALL_DELIVERED",
131 "illegal state 5",
132 "CALL_PRESENT",
133 "CALL_RECEIVED",
134 "CONNECT_REQUEST",
135 "MO_TERM_CALL_CONF",
136 "ACTIVE",
137 "DISCONNECT_REQ",
138 "DISCONNECT_IND",
139 "illegal state 13",
140 "illegal state 14",
141 "illegal state 15",
142 "illegal state 16",
143 "illegal state 17",
144 "illegal state 18",
145 "RELEASE_REQ",
146 "illegal state 20",
147 "illegal state 21",
148 "illegal state 22",
149 "illegal state 23",
150 "illegal state 24",
151 "illegal state 25",
152 "MO_ORIG_MODIFY",
153 "MO_TERM_MODIFY",
154 "CONNECT_IND",
155 "illegal state 29",
156 "illegal state 30",
157 "illegal state 31",
158};
159
160static const char *cc_msg_names[] = {
161 "unknown 0x00",
162 "ALERTING",
163 "CALL_PROC",
164 "PROGRESS",
165 "ESTAB",
166 "SETUP",
167 "ESTAB_CONF",
168 "CONNECT",
169 "CALL_CONF",
170 "START_CC",
171 "unknown 0x0a",
172 "RECALL",
173 "unknown 0x0c",
174 "unknown 0x0d",
175 "EMERG_SETUP",
176 "CONNECT_ACK",
177 "USER_INFO",
178 "unknown 0x11",
179 "unknown 0x12",
180 "MODIFY_REJECT",
181 "unknown 0x14",
182 "unknown 0x15",
183 "unknown 0x16",
184 "MODIFY",
185 "HOLD",
186 "HOLD_ACK",
187 "HOLD_REJ",
188 "unknown 0x1b",
189 "RETR",
190 "RETR_ACK",
191 "RETR_REJ",
192 "MODIFY_COMPL",
193 "unknown 0x20",
194 "unknown 0x21",
195 "unknown 0x22",
196 "unknown 0x23",
197 "unknown 0x24",
198 "DISCONNECT",
199 "unknown 0x26",
200 "unknown 0x27",
201 "unknown 0x28",
202 "unknown 0x29",
203 "RELEASE_COMPL",
204 "unknown 0x2b",
205 "unknown 0x2c",
206 "RELEASE",
207 "unknown 0x2e",
208 "unknown 0x2f",
209 "unknown 0x30",
210 "STOP_DTMF",
211 "STOP_DTMF_ACK",
212 "unknown 0x33",
213 "STATUS_ENQ",
214 "START_DTMF",
215 "START_DTMF_ACK",
216 "START_DTMF_REJ",
217 "unknown 0x38",
218 "CONG_CTRL",
219 "FACILITY",
220 "unknown 0x3b",
221 "STATUS",
222 "unknown 0x3c",
223 "NOTIFY",
224 "unknown 0x3f",
225};
226
Harald Welte59b04682009-06-10 05:40:52 +0800227static char strbuf[64];
228
229static const char *rr_cause_name(u_int8_t cause)
230{
231 if (cause < ARRAY_SIZE(rr_cause_names) &&
232 rr_cause_names[cause])
233 return rr_cause_names[cause];
234
235 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
236 return strbuf;
237}
238
239static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
240 int len)
241{
242 memset(rep, 0, sizeof(*rep));
243
244 if (data[0] & 0x80)
245 rep->flags |= MEAS_REP_F_BA1;
246 if (data[0] & 0x40)
247 rep->flags |= MEAS_REP_F_DTX;
Harald Welteba6589d2009-07-05 04:05:44 +0200248 if ((data[1] & 0x40) == 0x00)
Harald Welte59b04682009-06-10 05:40:52 +0800249 rep->flags |= MEAS_REP_F_VALID;
250
251 rep->rxlev_full = data[0] & 0x3f;
252 rep->rxlev_sub = data[1] & 0x3f;
253 rep->rxqual_full = (data[3] >> 4) & 0x7;
254 rep->rxqual_sub = (data[3] >> 1) & 0x7;
255 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
256 if (rep->num_cell < 1)
257 return;
258
259 /* an encoding nightmare in perfection */
260
261 rep->cell[0].rxlev = data[4] & 0x3f;
262 rep->cell[0].bcch_freq = data[5] >> 2;
263 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
264 if (rep->num_cell < 2)
265 return;
266
267 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
268 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
269 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
270 if (rep->num_cell < 3)
271 return;
272
273 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
274 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
275 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
276 if (rep->num_cell < 4)
277 return;
278
279 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
280 rep->cell[3].bcch_freq = data[11] & 0x1f;
281 rep->cell[3].bsic = data[12] >> 2;
282 if (rep->num_cell < 5)
283 return;
284
285 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
286 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
287 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
288 if (rep->num_cell < 6)
289 return;
290
291 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
292 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
293 rep->cell[5].bsic = data[16] & 0x3f;
294}
295
296int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
297static int gsm48_tx_simple(struct gsm_lchan *lchan,
298 u_int8_t pdisc, u_int8_t msg_type);
299static void schedule_reject(struct gsm_lchan *lchan);
300
301struct gsm_lai {
302 u_int16_t mcc;
303 u_int16_t mnc;
304 u_int16_t lac;
305};
306
307static int authorize_everonye = 0;
308void gsm0408_allow_everyone(int everyone)
309{
310 printf("Allowing everyone?\n");
311 authorize_everonye = everyone;
312}
313
314static int reject_cause = 0;
315void gsm0408_set_reject_cause(int cause)
316{
317 reject_cause = cause;
318}
319
Harald Welte03740842009-06-10 23:11:52 +0800320static u_int32_t new_callref = 0x80000001;
321
Harald Welte59b04682009-06-10 05:40:52 +0800322static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
323 struct gsm_subscriber *subscriber)
324{
325 if (!subscriber)
326 return 0;
327
328 /*
329 * Do not send accept yet as more information should arrive. Some
330 * phones will not send us the information and we will have to check
331 * what we want to do with that.
332 */
333 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
334 return 0;
335
336 if (authorize_everonye)
337 return 1;
338
339 return subscriber->authorized;
340}
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:
1154 if (!lchan->subscr)
Harald Welte75350412009-07-23 18:46:00 +02001155 lchan->subscr = db_create_subscriber(net, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001156 if (lchan->loc_operation)
1157 lchan->loc_operation->waiting_for_imsi = 0;
1158 break;
1159 case GSM_MI_TYPE_IMEI:
1160 case GSM_MI_TYPE_IMEISV:
1161 /* update subscribe <-> IMEI mapping */
1162 if (lchan->subscr)
1163 db_subscriber_assoc_imei(lchan->subscr, mi_string);
1164 if (lchan->loc_operation)
1165 lchan->loc_operation->waiting_for_imei = 0;
1166 break;
1167 }
1168
1169 /* Check if we can let the mobile station enter */
1170 return gsm0408_authorize(lchan, msg);
1171}
1172
1173
1174static void loc_upd_rej_cb(void *data)
1175{
1176 struct gsm_lchan *lchan = data;
1177
1178 release_loc_updating_req(lchan);
1179 gsm0408_loc_upd_rej(lchan, reject_cause);
1180 lchan_auto_release(lchan);
1181}
1182
1183static void schedule_reject(struct gsm_lchan *lchan)
1184{
1185 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1186 lchan->loc_operation->updating_timer.data = lchan;
1187 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
1188}
1189
1190static const char *lupd_name(u_int8_t type)
1191{
1192 switch (type) {
1193 case GSM48_LUPD_NORMAL:
1194 return "NORMAL";
1195 case GSM48_LUPD_PERIODIC:
1196 return "PEROIDOC";
1197 case GSM48_LUPD_IMSI_ATT:
1198 return "IMSI ATTACH";
1199 default:
1200 return "UNKNOWN";
1201 }
1202}
1203
1204#define MI_SIZE 32
1205/* Chapter 9.2.15: Receive Location Updating Request */
1206static int mm_rx_loc_upd_req(struct msgb *msg)
1207{
1208 struct gsm48_hdr *gh = msgb_l3(msg);
1209 struct gsm48_loc_upd_req *lu;
Harald Welte03740842009-06-10 23:11:52 +08001210 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001211 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001212 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001213 u_int8_t mi_type;
1214 char mi_string[MI_SIZE];
1215 int rc;
1216
1217 lu = (struct gsm48_loc_upd_req *) gh->data;
1218
1219 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
1220
1221 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1222
Harald Welte79639662009-06-27 02:58:43 +02001223 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte59b04682009-06-10 05:40:52 +08001224 lupd_name(lu->type));
1225
1226 /*
1227 * Pseudo Spoof detection: Just drop a second/concurrent
1228 * location updating request.
1229 */
1230 if (lchan->loc_operation) {
Harald Welte79639662009-06-27 02:58:43 +02001231 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Harald Welte59b04682009-06-10 05:40:52 +08001232 lchan->loc_operation);
1233 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1234 return 0;
1235 }
1236
1237 allocate_loc_updating_req(lchan);
1238
1239 switch (mi_type) {
1240 case GSM_MI_TYPE_IMSI:
Harald Welte79639662009-06-27 02:58:43 +02001241 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001242 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001243 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1244 lchan->loc_operation->waiting_for_imei = 1;
1245
1246 /* look up subscriber based on IMSI */
Harald Welte75350412009-07-23 18:46:00 +02001247 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001248 break;
1249 case GSM_MI_TYPE_TMSI:
Harald Welte79639662009-06-27 02:58:43 +02001250 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001251 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001252 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1253 lchan->loc_operation->waiting_for_imei = 1;
1254
1255 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte75350412009-07-23 18:46:00 +02001256 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001257 if (!subscr) {
1258 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte59b04682009-06-10 05:40:52 +08001259 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
1260 lchan->loc_operation->waiting_for_imsi = 1;
1261 }
1262 break;
1263 case GSM_MI_TYPE_IMEI:
1264 case GSM_MI_TYPE_IMEISV:
1265 /* no sim card... FIXME: what to do ? */
Harald Welte79639662009-06-27 02:58:43 +02001266 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001267 break;
1268 default:
Harald Welte79639662009-06-27 02:58:43 +02001269 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001270 break;
1271 }
1272
Harald Welteccd69362009-07-04 10:18:00 +02001273 /* schedule the reject timer */
1274 schedule_reject(lchan);
1275
Harald Welte03740842009-06-10 23:11:52 +08001276 if (!subscr) {
Harald Welte79639662009-06-27 02:58:43 +02001277 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte03740842009-06-10 23:11:52 +08001278 /* FIXME: request id? close channel? */
1279 return -EINVAL;
1280 }
1281
Harald Welte59b04682009-06-10 05:40:52 +08001282 lchan->subscr = subscr;
1283
Harald Welteccd69362009-07-04 10:18:00 +02001284 /* check if we can let the subscriber into our network immediately
1285 * or if we need to wait for identity responses. */
Harald Welte59b04682009-06-10 05:40:52 +08001286 return gsm0408_authorize(lchan, msg);
1287}
1288
Harald Welteca745e22009-07-29 12:10:35 +02001289/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte59b04682009-06-10 05:40:52 +08001290int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1291{
1292 struct msgb *msg = gsm48_msgb_alloc();
1293 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1294 struct gsm48_chan_mode_modify *cmm =
1295 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
1296 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
1297
1298 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
1299
1300 lchan->tch_mode = mode;
1301 msg->lchan = lchan;
1302 gh->proto_discr = GSM48_PDISC_RR;
1303 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1304
1305 /* fill the channel information element, this code
1306 * should probably be shared with rsl_rx_chan_rqd() */
1307 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
1308 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
1309 cmm->chan_desc.h0.h = 0;
1310 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1311 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1312 cmm->mode = mode;
1313
Harald Welte36fe2e82009-07-23 21:13:03 +02001314 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001315}
1316
Harald Welte03740842009-06-10 23:11:52 +08001317#if 0
1318static u_int8_t to_bcd8(u_int8_t val)
1319{
1320 return ((val / 10) << 4) | (val % 10);
1321}
1322#endif
1323
Harald Welte59b04682009-06-10 05:40:52 +08001324/* Section 9.2.15a */
1325int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1326{
1327 struct msgb *msg = gsm48_msgb_alloc();
1328 struct gsm48_hdr *gh;
1329 struct gsm_network *net = lchan->ts->trx->bts->network;
1330 u_int8_t *ptr8;
1331 u_int16_t *ptr16;
1332 int name_len;
1333 int i;
Harald Welte03740842009-06-10 23:11:52 +08001334#if 0
1335 time_t cur_t;
1336 struct tm* cur_time;
1337 int tz15min;
1338#endif
Harald Welte59b04682009-06-10 05:40:52 +08001339
1340 msg->lchan = lchan;
1341
1342 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1343 gh->proto_discr = GSM48_PDISC_MM;
1344 gh->msg_type = GSM48_MT_MM_INFO;
1345
1346 if (net->name_long) {
1347 name_len = strlen(net->name_long);
1348 /* 10.5.3.5a */
1349 ptr8 = msgb_put(msg, 3);
1350 ptr8[0] = GSM48_IE_NAME_LONG;
1351 ptr8[1] = name_len*2 +1;
1352 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1353
1354 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1355 for (i = 0; i < name_len; i++)
1356 ptr16[i] = htons(net->name_long[i]);
1357
1358 /* FIXME: Use Cell Broadcast, not UCS-2, since
1359 * UCS-2 is only supported by later revisions of the spec */
1360 }
1361
1362 if (net->name_short) {
1363 name_len = strlen(net->name_short);
1364 /* 10.5.3.5a */
1365 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Weltef6284712009-07-19 17:51:36 +02001366 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Welte59b04682009-06-10 05:40:52 +08001367 ptr8[1] = name_len*2 + 1;
1368 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1369
1370 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1371 for (i = 0; i < name_len; i++)
1372 ptr16[i] = htons(net->name_short[i]);
1373 }
1374
1375#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001376 /* Section 10.5.3.9 */
1377 cur_t = time(NULL);
Harald Welte03740842009-06-10 23:11:52 +08001378 cur_time = gmtime(&cur_t);
Harald Welte59b04682009-06-10 05:40:52 +08001379 ptr8 = msgb_put(msg, 8);
1380 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1381 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1382 ptr8[2] = to_bcd8(cur_time->tm_mon);
1383 ptr8[3] = to_bcd8(cur_time->tm_mday);
1384 ptr8[4] = to_bcd8(cur_time->tm_hour);
1385 ptr8[5] = to_bcd8(cur_time->tm_min);
1386 ptr8[6] = to_bcd8(cur_time->tm_sec);
1387 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1388 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte03740842009-06-10 23:11:52 +08001389 ptr8[7] = to_bcd8(tz15min);
Harald Welte59b04682009-06-10 05:40:52 +08001390 if (tz15min < 0)
Harald Welte03740842009-06-10 23:11:52 +08001391 ptr8[7] |= 0x80;
Harald Welte59b04682009-06-10 05:40:52 +08001392#endif
1393
Harald Welte36fe2e82009-07-23 21:13:03 +02001394 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001395}
1396
1397static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1398{
1399 DEBUGP(DMM, "-> CM SERVICE ACK\n");
1400 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
1401}
1402
1403/* 9.2.6 CM service reject */
1404static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1405 enum gsm48_reject_value value)
1406{
1407 struct msgb *msg = gsm48_msgb_alloc();
1408 struct gsm48_hdr *gh;
1409
1410 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1411
1412 msg->lchan = lchan;
1413 use_lchan(lchan);
1414
1415 gh->proto_discr = GSM48_PDISC_MM;
1416 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1417 gh->data[0] = value;
1418 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1419
Harald Welte36fe2e82009-07-23 21:13:03 +02001420 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001421}
1422
Harald Welte583ceaf2009-08-10 10:12:45 +02001423static int send_siemens_mrpci(struct gsm_lchan *lchan,
1424 u_int8_t *classmark2_lv)
1425{
1426 struct rsl_mrpci mrpci;
1427
1428 if (classmark2_lv[0] < 2)
1429 return -EINVAL;
1430
1431 mrpci.power_class = classmark2_lv[1] & 0x7;
1432 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1433 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1434 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1435
1436 return rsl_siemens_mrpci(lchan, &mrpci);
1437}
Harald Welte59b04682009-06-10 05:40:52 +08001438
1439/*
1440 * Handle CM Service Requests
1441 * a) Verify that the packet is long enough to contain the information
1442 * we require otherwsie reject with INCORRECT_MESSAGE
1443 * b) Try to parse the TMSI. If we do not have one reject
1444 * c) Check that we know the subscriber with the TMSI otherwise reject
1445 * with a HLR cause
1446 * d) Set the subscriber on the gsm_lchan and accept
1447 */
1448static int gsm48_rx_mm_serv_req(struct msgb *msg)
1449{
1450 u_int8_t mi_type;
1451 char mi_string[MI_SIZE];
1452
Harald Welte75350412009-07-23 18:46:00 +02001453 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001454 struct gsm_subscriber *subscr;
1455 struct gsm48_hdr *gh = msgb_l3(msg);
1456 struct gsm48_service_request *req =
1457 (struct gsm48_service_request *)gh->data;
1458 /* unfortunately in Phase1 the classmar2 length is variable */
1459 u_int8_t classmark2_len = gh->data[1];
1460 u_int8_t *classmark2 = gh->data+2;
1461 u_int8_t mi_len = *(classmark2 + classmark2_len);
1462 u_int8_t *mi = (classmark2 + classmark2_len + 1);
1463
1464 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
1465 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
1466 DEBUGPC(DMM, "wrong sized message\n");
1467 return gsm48_tx_mm_serv_rej(msg->lchan,
1468 GSM48_REJECT_INCORRECT_MESSAGE);
1469 }
1470
1471 if (msg->data_len < req->mi_len + 6) {
1472 DEBUGPC(DMM, "does not fit in packet\n");
1473 return gsm48_tx_mm_serv_rej(msg->lchan,
1474 GSM48_REJECT_INCORRECT_MESSAGE);
1475 }
1476
1477 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1478 if (mi_type != GSM_MI_TYPE_TMSI) {
1479 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
1480 return gsm48_tx_mm_serv_rej(msg->lchan,
1481 GSM48_REJECT_INCORRECT_MESSAGE);
1482 }
1483
1484 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1485 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
1486 req->cm_service_type, mi_type, mi_string);
1487
Harald Welte583ceaf2009-08-10 10:12:45 +02001488 if (is_siemens_bts(bts))
1489 send_siemens_mrpci(msg->lchan, classmark2-1);
1490
Harald Welte75350412009-07-23 18:46:00 +02001491 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001492
1493 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
1494 if (!subscr)
1495 return gsm48_tx_mm_serv_rej(msg->lchan,
1496 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1497
1498 if (!msg->lchan->subscr)
1499 msg->lchan->subscr = subscr;
1500 else if (msg->lchan->subscr != subscr) {
1501 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1502 subscr_put(subscr);
1503 }
1504
Harald Weltef6845a72009-07-05 14:08:13 +02001505 subscr->equipment.classmark2_len = classmark2_len;
1506 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1507 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001508
1509 return gsm48_tx_mm_serv_ack(msg->lchan);
1510}
1511
1512static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1513{
Harald Welte75350412009-07-23 18:46:00 +02001514 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001515 struct gsm48_hdr *gh = msgb_l3(msg);
1516 struct gsm48_imsi_detach_ind *idi =
1517 (struct gsm48_imsi_detach_ind *) gh->data;
1518 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1519 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001520 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001521
1522 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1523 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1524 mi_type, mi_string);
1525
1526 switch (mi_type) {
1527 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001528 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001529 break;
1530 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001531 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001532 break;
1533 case GSM_MI_TYPE_IMEI:
1534 case GSM_MI_TYPE_IMEISV:
1535 /* no sim card... FIXME: what to do ? */
1536 DEBUGPC(DMM, "unimplemented mobile identity type\n");
1537 break;
1538 default:
1539 DEBUGPC(DMM, "unknown mobile identity type\n");
1540 break;
1541 }
1542
1543 if (subscr) {
1544 subscr_update(subscr, msg->trx->bts,
1545 GSM_SUBSCRIBER_UPDATE_DETACHED);
1546 DEBUGP(DMM, "Subscriber: %s\n",
1547 subscr->name ? subscr->name : subscr->imsi);
1548 subscr_put(subscr);
1549 } else
1550 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1551
Harald Welte59b04682009-06-10 05:40:52 +08001552 return 0;
1553}
1554
1555static int gsm48_rx_mm_status(struct msgb *msg)
1556{
1557 struct gsm48_hdr *gh = msgb_l3(msg);
1558
1559 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1560
1561 return 0;
1562}
1563
1564/* Receive a GSM 04.08 Mobility Management (MM) message */
1565static int gsm0408_rcv_mm(struct msgb *msg)
1566{
1567 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte03740842009-06-10 23:11:52 +08001568 int rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08001569
1570 switch (gh->msg_type & 0xbf) {
1571 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Welte79639662009-06-27 02:58:43 +02001572 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte59b04682009-06-10 05:40:52 +08001573 rc = mm_rx_loc_upd_req(msg);
1574 break;
1575 case GSM48_MT_MM_ID_RESP:
1576 rc = mm_rx_id_resp(msg);
1577 break;
1578 case GSM48_MT_MM_CM_SERV_REQ:
1579 rc = gsm48_rx_mm_serv_req(msg);
1580 break;
1581 case GSM48_MT_MM_STATUS:
1582 rc = gsm48_rx_mm_status(msg);
1583 break;
1584 case GSM48_MT_MM_TMSI_REALL_COMPL:
1585 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1586 msg->lchan->subscr ?
1587 msg->lchan->subscr->imsi :
1588 "unknown subscriber");
1589 break;
1590 case GSM48_MT_MM_IMSI_DETACH_IND:
1591 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1592 break;
1593 case GSM48_MT_MM_CM_REEST_REQ:
1594 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1595 break;
1596 case GSM48_MT_MM_AUTH_RESP:
1597 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
1598 break;
1599 default:
1600 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1601 gh->msg_type);
1602 break;
1603 }
1604
1605 return rc;
1606}
1607
1608/* Receive a PAGING RESPONSE message from the MS */
1609static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1610{
Harald Welte75350412009-07-23 18:46:00 +02001611 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001612 struct gsm48_hdr *gh = msgb_l3(msg);
1613 u_int8_t *classmark2_lv = gh->data + 1;
1614 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1615 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
1616 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001617 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001618 struct paging_signal_data sig_data;
1619 int rc = 0;
1620
1621 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
1622 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1623 mi_type, mi_string);
Harald Welte583ceaf2009-08-10 10:12:45 +02001624
1625 if (is_siemens_bts(bts))
1626 send_siemens_mrpci(msg->lchan, classmark2_lv);
1627
Harald Welte59b04682009-06-10 05:40:52 +08001628 switch (mi_type) {
1629 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001630 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001631 break;
1632 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001633 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001634 break;
1635 }
1636
1637 if (!subscr) {
1638 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1639 /* FIXME: request id? close channel? */
1640 return -EINVAL;
1641 }
1642 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte68b7df22009-08-08 16:03:15 +02001643 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Harald Welte59b04682009-06-10 05:40:52 +08001644
Harald Weltef6845a72009-07-05 14:08:13 +02001645 subscr->equipment.classmark2_len = *classmark2_lv;
1646 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1647 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001648
1649 if (!msg->lchan->subscr) {
1650 msg->lchan->subscr = subscr;
1651 } else if (msg->lchan->subscr != subscr) {
1652 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1653 subscr_put(subscr);
1654 return -EINVAL;
1655 } else {
1656 DEBUGP(DRR, "<- Channel already owned by us\n");
1657 subscr_put(subscr);
1658 subscr = msg->lchan->subscr;
1659 }
1660
1661 sig_data.subscr = subscr;
1662 sig_data.bts = msg->lchan->ts->trx->bts;
1663 sig_data.lchan = msg->lchan;
1664
1665 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Welte876312f2009-06-10 11:21:55 +08001666
1667 /* Stop paging on the bts we received the paging response */
Harald Welte59b04682009-06-10 05:40:52 +08001668 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
1669
1670 /* FIXME: somehow signal the completion of the PAGING to
1671 * the entity that requested the paging */
1672
1673 return rc;
1674}
1675
1676static int gsm48_rx_rr_classmark(struct msgb *msg)
1677{
1678 struct gsm48_hdr *gh = msgb_l3(msg);
1679 struct gsm_subscriber *subscr = msg->lchan->subscr;
1680 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1681 u_int8_t cm2_len, cm3_len = 0;
1682 u_int8_t *cm2, *cm3 = NULL;
1683
1684 DEBUGP(DRR, "CLASSMARK CHANGE ");
1685
1686 /* classmark 2 */
1687 cm2_len = gh->data[0];
1688 cm2 = &gh->data[1];
1689 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1690
1691 if (payload_len > cm2_len + 1) {
1692 /* we must have a classmark3 */
1693 if (gh->data[cm2_len+1] != 0x20) {
1694 DEBUGPC(DRR, "ERR CM3 TAG\n");
1695 return -EINVAL;
1696 }
1697 if (cm2_len > 3) {
1698 DEBUGPC(DRR, "CM2 too long!\n");
1699 return -EINVAL;
1700 }
1701
1702 cm3_len = gh->data[cm2_len+2];
1703 cm3 = &gh->data[cm2_len+3];
1704 if (cm3_len > 14) {
1705 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1706 return -EINVAL;
1707 }
1708 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1709 }
1710 if (subscr) {
Harald Weltef6845a72009-07-05 14:08:13 +02001711 subscr->equipment.classmark2_len = cm2_len;
1712 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Welte59b04682009-06-10 05:40:52 +08001713 if (cm3) {
Harald Weltef6845a72009-07-05 14:08:13 +02001714 subscr->equipment.classmark3_len = cm3_len;
1715 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Welte59b04682009-06-10 05:40:52 +08001716 }
Harald Weltef6845a72009-07-05 14:08:13 +02001717 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001718 }
1719
Harald Welte59b04682009-06-10 05:40:52 +08001720 return 0;
1721}
1722
1723static int gsm48_rx_rr_status(struct msgb *msg)
1724{
1725 struct gsm48_hdr *gh = msgb_l3(msg);
1726
1727 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1728 rr_cause_name(gh->data[0]));
1729
1730 return 0;
1731}
1732
1733static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1734{
1735 struct gsm48_hdr *gh = msgb_l3(msg);
1736 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1737 static struct gsm_meas_rep meas_rep;
1738
Harald Welte02993682009-06-27 02:53:10 +02001739 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Welte59b04682009-06-10 05:40:52 +08001740 parse_meas_rep(&meas_rep, gh->data, payload_len);
1741 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte02993682009-06-27 02:53:10 +02001742 DEBUGPC(DMEAS, "DTX ");
Harald Welte59b04682009-06-10 05:40:52 +08001743 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte02993682009-06-27 02:53:10 +02001744 DEBUGPC(DMEAS, "BA1 ");
Harald Welte59b04682009-06-10 05:40:52 +08001745 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte02993682009-06-27 02:53:10 +02001746 DEBUGPC(DMEAS, "NOT VALID ");
Harald Welte59b04682009-06-10 05:40:52 +08001747 else
Harald Welte02993682009-06-27 02:53:10 +02001748 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Welte59b04682009-06-10 05:40:52 +08001749 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1750 meas_rep.rxqual_sub);
1751
Harald Welte02993682009-06-27 02:53:10 +02001752 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Welte59b04682009-06-10 05:40:52 +08001753
1754 /* FIXME: put the results somwhere */
1755
1756 return 0;
1757}
1758
1759/* Receive a GSM 04.08 Radio Resource (RR) message */
1760static int gsm0408_rcv_rr(struct msgb *msg)
1761{
1762 struct gsm48_hdr *gh = msgb_l3(msg);
1763 int rc = 0;
1764
1765 switch (gh->msg_type) {
1766 case GSM48_MT_RR_CLSM_CHG:
1767 rc = gsm48_rx_rr_classmark(msg);
1768 break;
1769 case GSM48_MT_RR_GPRS_SUSP_REQ:
1770 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1771 break;
1772 case GSM48_MT_RR_PAG_RESP:
1773 rc = gsm48_rr_rx_pag_resp(msg);
1774 break;
1775 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1776 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welteca745e22009-07-29 12:10:35 +02001777 /* We've successfully modified the MS side of the channel,
1778 * now go on to modify the BTS side of the channel */
Harald Welte39274f42009-07-29 15:41:29 +02001779 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte59b04682009-06-10 05:40:52 +08001780 rc = rsl_chan_mode_modify_req(msg->lchan);
1781 break;
1782 case GSM48_MT_RR_STATUS:
1783 rc = gsm48_rx_rr_status(msg);
1784 break;
1785 case GSM48_MT_RR_MEAS_REP:
1786 rc = gsm48_rx_rr_meas_rep(msg);
1787 break;
1788 default:
1789 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1790 gh->msg_type);
1791 break;
1792 }
1793
1794 return rc;
1795}
1796
1797/* 7.1.7 and 9.1.7 Channel release*/
1798int gsm48_send_rr_release(struct gsm_lchan *lchan)
1799{
1800 struct msgb *msg = gsm48_msgb_alloc();
1801 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1802 u_int8_t *cause;
1803
1804 msg->lchan = lchan;
1805 gh->proto_discr = GSM48_PDISC_RR;
1806 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1807
1808 cause = msgb_put(msg, 1);
1809 cause[0] = GSM48_RR_CAUSE_NORMAL;
1810
1811 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1812 lchan->nr, lchan->type);
1813
Harald Welteafe3c232009-07-19 18:36:49 +02001814 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001815 gsm48_sendmsg(msg, NULL);
Harald Welte68b7df22009-08-08 16:03:15 +02001816 /* FIXME: Start Timer T3109 */
Harald Welteafe3c232009-07-19 18:36:49 +02001817
1818 /* Deactivate the SACCH on the BTS side */
1819 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001820}
1821
1822/* Call Control */
1823
1824/* The entire call control code is written in accordance with Figure 7.10c
1825 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1826 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1827 * it for voice */
1828
Harald Welte03740842009-06-10 23:11:52 +08001829static void new_cc_state(struct gsm_trans *trans, int state)
1830{
1831 if (state > 31 || state < 0)
1832 return;
1833
1834 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltec2189a62009-07-23 18:56:43 +02001835 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001836
Harald Weltec2189a62009-07-23 18:56:43 +02001837 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001838}
1839
1840static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001841{
1842 struct msgb *msg = gsm48_msgb_alloc();
1843 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1844 u_int8_t *cause, *call_state;
1845
Harald Welte59b04682009-06-10 05:40:52 +08001846 gh->msg_type = GSM48_MT_CC_STATUS;
1847
1848 cause = msgb_put(msg, 3);
1849 cause[0] = 2;
1850 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1851 cause[2] = 0x80 | 30; /* response to status inquiry */
1852
1853 call_state = msgb_put(msg, 1);
1854 call_state[0] = 0xc0 | 0x00;
1855
Harald Welte36fe2e82009-07-23 21:13:03 +02001856 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001857}
1858
1859static int gsm48_tx_simple(struct gsm_lchan *lchan,
1860 u_int8_t pdisc, u_int8_t msg_type)
1861{
1862 struct msgb *msg = gsm48_msgb_alloc();
1863 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1864
1865 msg->lchan = lchan;
1866
1867 gh->proto_discr = pdisc;
1868 gh->msg_type = msg_type;
1869
Harald Welte36fe2e82009-07-23 21:13:03 +02001870 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001871}
1872
Harald Welte03740842009-06-10 23:11:52 +08001873static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1874{
Harald Weltec2189a62009-07-23 18:56:43 +02001875 if (bsc_timer_pending(&trans->cc.timer)) {
1876 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1877 bsc_del_timer(&trans->cc.timer);
1878 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001879 }
1880}
1881
1882static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1883 int msg_type, struct gsm_mncc *mncc)
1884{
1885 struct msgb *msg;
1886
1887 if (trans)
1888 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02001889 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08001890 "Sending '%s' to MNCC.\n",
1891 trans->lchan->ts->trx->bts->nr,
1892 trans->lchan->ts->trx->nr,
1893 trans->lchan->ts->nr, trans->transaction_id,
1894 (trans->subscr)?(trans->subscr->extension):"-",
1895 get_mncc_name(msg_type));
1896 else
1897 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1898 "Sending '%s' to MNCC.\n",
1899 (trans->subscr)?(trans->subscr->extension):"-",
1900 get_mncc_name(msg_type));
1901 else
1902 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1903 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1904
1905 mncc->msg_type = msg_type;
1906
Harald Welte9cfc9352009-06-26 19:39:35 +02001907 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08001908 if (!msg)
1909 return -ENOMEM;
1910 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1911 msgb_enqueue(&net->upqueue, msg);
1912
1913 return 0;
1914}
1915
1916int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1917 u_int32_t callref, int location, int value)
1918{
1919 struct gsm_mncc rel;
1920
Harald Weltecb0595f2009-06-12 01:54:08 +08001921 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08001922 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001923 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08001924 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1925}
1926
Harald Weltec2189a62009-07-23 18:56:43 +02001927/* Call Control Specific transaction release.
1928 * gets called by trans_free, DO NOT CALL YOURSELF! */
1929void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08001930{
Harald Welte03740842009-06-10 23:11:52 +08001931 gsm48_stop_cc_timer(trans);
1932
1933 /* send release to L4, if callref still exists */
1934 if (trans->callref) {
1935 /* Ressource unavailable */
Harald Welte0abe5a62009-07-23 19:06:52 +02001936 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001937 GSM48_CAUSE_LOC_PRN_S_LU,
1938 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08001939 }
Harald Weltec2189a62009-07-23 18:56:43 +02001940 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08001941 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltec2189a62009-07-23 18:56:43 +02001942 if (trans->lchan)
1943 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08001944}
1945
1946static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1947
Harald Welte59b04682009-06-10 05:40:52 +08001948/* call-back from paging the B-end of the connection */
1949static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
1950 struct msgb *msg, void *_lchan, void *param)
1951{
1952 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08001953 struct gsm_subscriber *subscr = param;
1954 struct gsm_trans *transt, *tmp;
1955 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02001956
Harald Welte59b04682009-06-10 05:40:52 +08001957 if (hooknum != GSM_HOOK_RR_PAGING)
1958 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08001959
1960 if (!subscr)
1961 return -EINVAL;
1962 net = subscr->net;
1963 if (!net) {
1964 DEBUGP(DCC, "Error Network not set!\n");
1965 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001966 }
1967
Harald Welte03740842009-06-10 23:11:52 +08001968 /* check all tranactions (without lchan) for subscriber */
1969 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1970 if (transt->subscr != subscr || transt->lchan)
1971 continue;
1972 switch (event) {
1973 case GSM_PAGING_SUCCEEDED:
1974 if (!lchan) // paranoid
1975 break;
1976 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1977 subscr->extension);
1978 /* Assign lchan */
1979 if (!transt->lchan) {
1980 transt->lchan = lchan;
1981 use_lchan(lchan);
1982 }
1983 /* send SETUP request to called party */
Harald Weltec2189a62009-07-23 18:56:43 +02001984 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08001985 break;
1986 case GSM_PAGING_EXPIRED:
1987 DEBUGP(DCC, "Paging subscr %s expired!\n",
1988 subscr->extension);
1989 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02001990 mncc_release_ind(transt->subscr->net, transt,
1991 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001992 GSM48_CAUSE_LOC_PRN_S_LU,
1993 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08001994 transt->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02001995 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08001996 break;
1997 }
1998 }
Harald Welte59b04682009-06-10 05:40:52 +08001999 return 0;
2000}
2001
Harald Welte3c062072009-07-28 18:25:29 +02002002/* some other part of the code sends us a signal */
2003static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2004 void *handler_data, void *signal_data)
2005{
2006 struct gsm_lchan *lchan = signal_data;
2007 struct gsm_bts_trx_ts *ts;
2008 int rc;
2009
2010 if (subsys != SS_ABISIP)
2011 return 0;
2012
2013 /* in case we use direct BTS-to-BTS RTP */
2014 if (ipacc_rtp_direct)
2015 return 0;
2016
2017 ts = lchan->ts;
2018
2019 switch (signal) {
2020 case S_ABISIP_BIND_ACK:
2021 /* the BTS has successfully bound a TCH to a local ip/port,
2022 * which means we can connect our UDP socket to it */
2023 if (ts->abis_ip.rtp_socket) {
2024 rtp_socket_free(ts->abis_ip.rtp_socket);
2025 ts->abis_ip.rtp_socket = NULL;
2026 }
2027
2028 ts->abis_ip.rtp_socket = rtp_socket_create();
2029 if (!ts->abis_ip.rtp_socket)
2030 goto out_err;
2031
2032 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2033 ts->abis_ip.bound_ip,
2034 ts->abis_ip.bound_port);
2035 if (rc < 0)
2036 goto out_err;
2037 break;
2038 case S_ABISIP_DISC_IND:
2039 /* the BTS tells us a RTP stream has been disconnected */
2040 if (ts->abis_ip.rtp_socket) {
2041 rtp_socket_free(ts->abis_ip.rtp_socket);
2042 ts->abis_ip.rtp_socket = NULL;
2043 }
2044 break;
2045 }
2046
2047 return 0;
2048out_err:
2049 /* FIXME: do something */
2050 return 0;
2051}
2052
2053/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2054static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2055{
2056 struct gsm_bts_trx_ts *ts = lchan->ts;
2057 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2058 int rc;
2059
2060 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2061 ntohs(rs->rtp.sin_local.sin_port),
2062 ts->abis_ip.conn_id,
2063 /* FIXME: use RTP payload of bound socket, not BTS*/
2064 ts->abis_ip.rtp_payload2);
2065
2066 return rc;
2067}
2068
Harald Welte59b04682009-06-10 05:40:52 +08002069/* map two ipaccess RTP streams onto each other */
2070static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2071{
2072 struct gsm_bts *bts = lchan->ts->trx->bts;
2073 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2074 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002075 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002076
2077 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2078 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2079 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2080
2081 if (bts->type != remote_bts->type) {
2082 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2083 return -EINVAL;
2084 }
2085
2086 switch (bts->type) {
2087 case GSM_BTS_TYPE_NANOBTS_900:
2088 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002089 if (!ipacc_rtp_direct) {
2090 /* connect the TCH's to our RTP proxy */
2091 rc = ipacc_connect_proxy_bind(lchan);
2092 if (rc < 0)
2093 return rc;
2094 rc = ipacc_connect_proxy_bind(remote_lchan);
2095
2096 /* connect them with each other */
2097 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2098 remote_lchan->ts->abis_ip.rtp_socket);
2099 } else {
2100 /* directly connect TCH RTP streams to each other */
2101 ts = remote_lchan->ts;
2102 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2103 ts->abis_ip.bound_port,
2104 lchan->ts->abis_ip.conn_id,
2105 ts->abis_ip.rtp_payload2);
2106 if (rc < 0)
2107 return rc;
2108 ts = lchan->ts;
2109 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2110 ts->abis_ip.bound_port,
2111 remote_lchan->ts->abis_ip.conn_id,
2112 ts->abis_ip.rtp_payload2);
2113 }
Harald Welte59b04682009-06-10 05:40:52 +08002114 break;
2115 case GSM_BTS_TYPE_BS11:
2116 trau_mux_map_lchan(lchan, remote_lchan);
2117 break;
2118 default:
2119 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002120 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002121 break;
2122 }
2123
2124 return 0;
2125}
2126
Harald Welte03740842009-06-10 23:11:52 +08002127/* bridge channels of two transactions */
2128static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002129{
Harald Weltec2189a62009-07-23 18:56:43 +02002130 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2131 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002132
Harald Welte03740842009-06-10 23:11:52 +08002133 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002134 return -EIO;
2135
Harald Welte03740842009-06-10 23:11:52 +08002136 if (!trans1->lchan || !trans2->lchan)
2137 return -EIO;
2138
2139 /* through-connect channel */
2140 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002141}
2142
Harald Welte03740842009-06-10 23:11:52 +08002143/* enable receive of channels to upqueue */
2144static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2145{
2146 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002147
Harald Welte03740842009-06-10 23:11:52 +08002148 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002149 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002150 if (!trans)
2151 return -EIO;
2152 if (!trans->lchan)
2153 return 0;
2154
2155 // todo IPACCESS
2156 if (enable)
2157 return trau_recv_lchan(trans->lchan, data->callref);
2158 return trau_mux_unmap(NULL, data->callref);
2159}
2160
2161/* send a frame to channel */
2162static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2163{
2164 struct gsm_trans *trans;
2165
2166 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002167 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002168 if (!trans)
2169 return -EIO;
2170 if (!trans->lchan)
2171 return 0;
2172 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2173 trans->lchan->type != GSM_LCHAN_TCH_H)
2174 return 0;
2175
2176 // todo IPACCESS
2177 return trau_send_lchan(trans->lchan,
2178 (struct decoded_trau_frame *)frame->data);
2179}
2180
2181
2182static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2183{
2184 DEBUGP(DCC, "-> STATUS ENQ\n");
2185 return gsm48_cc_tx_status(trans, msg);
2186}
2187
2188static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2189static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2190
2191static void gsm48_cc_timeout(void *arg)
2192{
2193 struct gsm_trans *trans = arg;
2194 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002195 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2196 int mo_location = GSM48_CAUSE_LOC_USER;
2197 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2198 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002199 struct gsm_mncc mo_rel, l4_rel;
2200
2201 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2202 mo_rel.callref = trans->callref;
2203 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2204 l4_rel.callref = trans->callref;
2205
Harald Weltec2189a62009-07-23 18:56:43 +02002206 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002207 case 0x303:
2208 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002209 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002210 break;
2211 case 0x310:
2212 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002213 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002214 break;
2215 case 0x313:
2216 disconnect = 1;
2217 /* unknown, did not find it in the specs */
2218 break;
2219 case 0x301:
2220 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002221 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002222 break;
2223 case 0x308:
Harald Weltec2189a62009-07-23 18:56:43 +02002224 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002225 /* restart T308 a second time */
Harald Weltec2189a62009-07-23 18:56:43 +02002226 gsm48_cc_tx_release(trans, &trans->cc.msg);
2227 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002228 break; /* stay in release state */
2229 }
Harald Weltec2189a62009-07-23 18:56:43 +02002230 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002231 return;
2232// release = 1;
2233// l4_cause = 14;
2234// break;
2235 case 0x306:
2236 release = 1;
Harald Weltec2189a62009-07-23 18:56:43 +02002237 mo_cause = trans->cc.msg.cause.value;
2238 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002239 break;
2240 case 0x323:
2241 disconnect = 1;
2242 break;
2243 default:
2244 release = 1;
2245 }
2246
2247 if (release && trans->callref) {
2248 /* process release towards layer 4 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002249 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002250 l4_location, l4_cause);
2251 trans->callref = 0;
2252 }
2253
2254 if (disconnect && trans->callref) {
2255 /* process disconnect towards layer 4 */
2256 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte0abe5a62009-07-23 19:06:52 +02002257 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002258 }
2259
2260 /* process disconnect towards mobile station */
2261 if (disconnect || release) {
2262 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltec2189a62009-07-23 18:56:43 +02002263 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2264 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2265 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002266 mo_rel.cause.diag_len = 3;
2267
2268 if (disconnect)
2269 gsm48_cc_tx_disconnect(trans, &mo_rel);
2270 if (release)
2271 gsm48_cc_tx_release(trans, &mo_rel);
2272 }
2273
2274}
2275
2276static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2277 int sec, int micro)
2278{
2279 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltec2189a62009-07-23 18:56:43 +02002280 trans->cc.timer.cb = gsm48_cc_timeout;
2281 trans->cc.timer.data = trans;
2282 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2283 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002284}
2285
2286static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2287{
2288 struct gsm48_hdr *gh = msgb_l3(msg);
2289 u_int8_t msg_type = gh->msg_type & 0xbf;
2290 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2291 struct tlv_parsed tp;
2292 struct gsm_mncc setup;
2293
2294 memset(&setup, 0, sizeof(struct gsm_mncc));
2295 setup.callref = trans->callref;
2296 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2297 /* emergency setup is identified by msg_type */
2298 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2299 setup.emergency = 1;
2300
2301 /* use subscriber as calling party number */
2302 if (trans->subscr) {
2303 setup.fields |= MNCC_F_CALLING;
2304 strncpy(setup.calling.number, trans->subscr->extension,
2305 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002306 strncpy(setup.imsi, trans->subscr->imsi,
2307 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002308 }
2309 /* bearer capability */
2310 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2311 setup.fields |= MNCC_F_BEARER_CAP;
2312 decode_bearer_cap(&setup.bearer_cap,
2313 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2314 }
2315 /* facility */
2316 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2317 setup.fields |= MNCC_F_FACILITY;
2318 decode_facility(&setup.facility,
2319 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2320 }
2321 /* called party bcd number */
2322 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2323 setup.fields |= MNCC_F_CALLED;
2324 decode_called(&setup.called,
2325 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2326 }
2327 /* user-user */
2328 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2329 setup.fields |= MNCC_F_USERUSER;
2330 decode_useruser(&setup.useruser,
2331 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2332 }
2333 /* ss-version */
2334 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2335 setup.fields |= MNCC_F_SSVERSION;
2336 decode_ssversion(&setup.ssversion,
2337 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2338 }
2339 /* CLIR suppression */
2340 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2341 setup.clir.sup = 1;
2342 /* CLIR invocation */
2343 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2344 setup.clir.inv = 1;
2345 /* cc cap */
2346 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2347 setup.fields |= MNCC_F_CCCAP;
2348 decode_cccap(&setup.cccap,
2349 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2350 }
2351
Harald Welte03740842009-06-10 23:11:52 +08002352 new_cc_state(trans, GSM_CSTATE_INITIATED);
2353
2354 /* indicate setup to MNCC */
Harald Welte0abe5a62009-07-23 19:06:52 +02002355 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002356
Harald Welteca745e22009-07-29 12:10:35 +02002357 /* MNCC code will modify the channel asynchronously, we should
2358 * ipaccess-bind only after the modification has been made to the
2359 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002360 return 0;
2361}
2362
2363static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002364{
2365 struct msgb *msg = gsm48_msgb_alloc();
2366 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002367 struct gsm_mncc *setup = arg;
Harald Welte165fc332009-07-23 21:36:44 +02002368 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002369
2370 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2371
Harald Welte03740842009-06-10 23:11:52 +08002372 /* transaction id must not be assigned */
2373 if (trans->transaction_id != 0xff) { /* unasssigned */
2374 DEBUGP(DCC, "TX Setup with assigned transaction. "
2375 "This is not allowed!\n");
2376 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002377 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002378 GSM48_CAUSE_LOC_PRN_S_LU,
2379 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002380 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002381 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002382 return rc;
2383 }
2384
2385 /* Get free transaction_id */
Harald Welte165fc332009-07-23 21:36:44 +02002386 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2387 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002388 /* no free transaction ID */
Harald Welte0abe5a62009-07-23 19:06:52 +02002389 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002390 GSM48_CAUSE_LOC_PRN_S_LU,
2391 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002392 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002393 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002394 return rc;
2395 }
Harald Welte165fc332009-07-23 21:36:44 +02002396 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002397
Harald Welte59b04682009-06-10 05:40:52 +08002398 gh->msg_type = GSM48_MT_CC_SETUP;
2399
Harald Welte03740842009-06-10 23:11:52 +08002400 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002401
Harald Welte03740842009-06-10 23:11:52 +08002402 /* bearer capability */
2403 if (setup->fields & MNCC_F_BEARER_CAP)
2404 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2405 /* facility */
2406 if (setup->fields & MNCC_F_FACILITY)
2407 encode_facility(msg, 0, &setup->facility);
2408 /* progress */
2409 if (setup->fields & MNCC_F_PROGRESS)
2410 encode_progress(msg, 0, &setup->progress);
2411 /* calling party BCD number */
2412 if (setup->fields & MNCC_F_CALLING)
2413 encode_calling(msg, &setup->calling);
2414 /* called party BCD number */
2415 if (setup->fields & MNCC_F_CALLED)
2416 encode_called(msg, &setup->called);
2417 /* user-user */
2418 if (setup->fields & MNCC_F_USERUSER)
2419 encode_useruser(msg, 0, &setup->useruser);
2420 /* redirecting party BCD number */
2421 if (setup->fields & MNCC_F_REDIRECTING)
2422 encode_redirecting(msg, &setup->redirecting);
2423 /* signal */
2424 if (setup->fields & MNCC_F_SIGNAL)
2425 encode_signal(msg, setup->signal);
2426
2427 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002428
Harald Welte36fe2e82009-07-23 21:13:03 +02002429 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002430}
2431
Harald Welte03740842009-06-10 23:11:52 +08002432static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2433{
2434 struct gsm48_hdr *gh = msgb_l3(msg);
2435 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2436 struct tlv_parsed tp;
2437 struct gsm_mncc call_conf;
2438
2439 gsm48_stop_cc_timer(trans);
2440 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2441
2442 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2443 call_conf.callref = trans->callref;
2444 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2445#if 0
2446 /* repeat */
2447 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2448 call_conf.repeat = 1;
2449 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2450 call_conf.repeat = 2;
2451#endif
2452 /* bearer capability */
2453 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2454 call_conf.fields |= MNCC_F_BEARER_CAP;
2455 decode_bearer_cap(&call_conf.bearer_cap,
2456 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2457 }
2458 /* cause */
2459 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2460 call_conf.fields |= MNCC_F_CAUSE;
2461 decode_cause(&call_conf.cause,
2462 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2463 }
2464 /* cc cap */
2465 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2466 call_conf.fields |= MNCC_F_CCCAP;
2467 decode_cccap(&call_conf.cccap,
2468 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2469 }
2470
2471 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2472
Harald Welte0abe5a62009-07-23 19:06:52 +02002473 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2474 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002475}
2476
2477static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2478{
2479 struct gsm_mncc *proceeding = arg;
2480 struct msgb *msg = gsm48_msgb_alloc();
2481 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2482
Harald Welte03740842009-06-10 23:11:52 +08002483 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2484
2485 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2486
2487 /* bearer capability */
2488 if (proceeding->fields & MNCC_F_BEARER_CAP)
2489 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2490 /* facility */
2491 if (proceeding->fields & MNCC_F_FACILITY)
2492 encode_facility(msg, 0, &proceeding->facility);
2493 /* progress */
2494 if (proceeding->fields & MNCC_F_PROGRESS)
2495 encode_progress(msg, 0, &proceeding->progress);
2496
Harald Welte36fe2e82009-07-23 21:13:03 +02002497 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002498}
2499
2500static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2501{
2502 struct gsm48_hdr *gh = msgb_l3(msg);
2503 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2504 struct tlv_parsed tp;
2505 struct gsm_mncc alerting;
2506
2507 gsm48_stop_cc_timer(trans);
2508 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2509
2510 memset(&alerting, 0, sizeof(struct gsm_mncc));
2511 alerting.callref = trans->callref;
2512 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2513 /* facility */
2514 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2515 alerting.fields |= MNCC_F_FACILITY;
2516 decode_facility(&alerting.facility,
2517 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2518 }
2519
2520 /* progress */
2521 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2522 alerting.fields |= MNCC_F_PROGRESS;
2523 decode_progress(&alerting.progress,
2524 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2525 }
2526 /* ss-version */
2527 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2528 alerting.fields |= MNCC_F_SSVERSION;
2529 decode_ssversion(&alerting.ssversion,
2530 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2531 }
2532
2533 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2534
Harald Welte0abe5a62009-07-23 19:06:52 +02002535 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2536 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002537}
2538
2539static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2540{
2541 struct gsm_mncc *alerting = arg;
2542 struct msgb *msg = gsm48_msgb_alloc();
2543 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2544
Harald Welte03740842009-06-10 23:11:52 +08002545 gh->msg_type = GSM48_MT_CC_ALERTING;
2546
2547 /* facility */
2548 if (alerting->fields & MNCC_F_FACILITY)
2549 encode_facility(msg, 0, &alerting->facility);
2550 /* progress */
2551 if (alerting->fields & MNCC_F_PROGRESS)
2552 encode_progress(msg, 0, &alerting->progress);
2553 /* user-user */
2554 if (alerting->fields & MNCC_F_USERUSER)
2555 encode_useruser(msg, 0, &alerting->useruser);
2556
2557 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2558
Harald Welte36fe2e82009-07-23 21:13:03 +02002559 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002560}
2561
2562static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2563{
2564 struct gsm_mncc *progress = arg;
2565 struct msgb *msg = gsm48_msgb_alloc();
2566 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2567
Harald Welte03740842009-06-10 23:11:52 +08002568 gh->msg_type = GSM48_MT_CC_PROGRESS;
2569
2570 /* progress */
2571 encode_progress(msg, 1, &progress->progress);
2572 /* user-user */
2573 if (progress->fields & MNCC_F_USERUSER)
2574 encode_useruser(msg, 0, &progress->useruser);
2575
Harald Welte36fe2e82009-07-23 21:13:03 +02002576 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002577}
2578
2579static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2580{
2581 struct gsm_mncc *connect = arg;
2582 struct msgb *msg = gsm48_msgb_alloc();
2583 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2584
Harald Welte03740842009-06-10 23:11:52 +08002585 gh->msg_type = GSM48_MT_CC_CONNECT;
2586
2587 gsm48_stop_cc_timer(trans);
2588 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2589
2590 /* facility */
2591 if (connect->fields & MNCC_F_FACILITY)
2592 encode_facility(msg, 0, &connect->facility);
2593 /* progress */
2594 if (connect->fields & MNCC_F_PROGRESS)
2595 encode_progress(msg, 0, &connect->progress);
2596 /* connected number */
2597 if (connect->fields & MNCC_F_CONNECTED)
2598 encode_connected(msg, &connect->connected);
2599 /* user-user */
2600 if (connect->fields & MNCC_F_USERUSER)
2601 encode_useruser(msg, 0, &connect->useruser);
2602
2603 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2604
Harald Welte36fe2e82009-07-23 21:13:03 +02002605 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002606}
2607
2608static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2609{
2610 struct gsm48_hdr *gh = msgb_l3(msg);
2611 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2612 struct tlv_parsed tp;
2613 struct gsm_mncc connect;
2614
2615 gsm48_stop_cc_timer(trans);
2616
2617 memset(&connect, 0, sizeof(struct gsm_mncc));
2618 connect.callref = trans->callref;
2619 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2620 /* use subscriber as connected party number */
2621 if (trans->subscr) {
2622 connect.fields |= MNCC_F_CONNECTED;
2623 strncpy(connect.connected.number, trans->subscr->extension,
2624 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002625 strncpy(connect.imsi, trans->subscr->imsi,
2626 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002627 }
2628 /* facility */
2629 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2630 connect.fields |= MNCC_F_FACILITY;
2631 decode_facility(&connect.facility,
2632 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2633 }
2634 /* user-user */
2635 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2636 connect.fields |= MNCC_F_USERUSER;
2637 decode_useruser(&connect.useruser,
2638 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2639 }
2640 /* ss-version */
2641 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2642 connect.fields |= MNCC_F_SSVERSION;
2643 decode_ssversion(&connect.ssversion,
2644 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2645 }
2646
2647 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2648
Harald Welte0abe5a62009-07-23 19:06:52 +02002649 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002650}
2651
2652
2653static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2654{
2655 struct gsm_mncc connect_ack;
2656
2657 gsm48_stop_cc_timer(trans);
2658
2659 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2660
2661 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2662 connect_ack.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002663 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002664 &connect_ack);
2665}
2666
2667static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2668{
2669 struct msgb *msg = gsm48_msgb_alloc();
2670 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2671
Harald Welte03740842009-06-10 23:11:52 +08002672 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2673
2674 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2675
Harald Welte36fe2e82009-07-23 21:13:03 +02002676 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002677}
2678
2679static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2680{
2681 struct gsm48_hdr *gh = msgb_l3(msg);
2682 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2683 struct tlv_parsed tp;
2684 struct gsm_mncc disc;
2685
2686 gsm48_stop_cc_timer(trans);
2687
2688 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2689
2690 memset(&disc, 0, sizeof(struct gsm_mncc));
2691 disc.callref = trans->callref;
2692 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2693 /* cause */
2694 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2695 disc.fields |= MNCC_F_CAUSE;
2696 decode_cause(&disc.cause,
2697 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2698 }
2699 /* facility */
2700 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2701 disc.fields |= MNCC_F_FACILITY;
2702 decode_facility(&disc.facility,
2703 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2704 }
2705 /* user-user */
2706 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2707 disc.fields |= MNCC_F_USERUSER;
2708 decode_useruser(&disc.useruser,
2709 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2710 }
2711 /* ss-version */
2712 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2713 disc.fields |= MNCC_F_SSVERSION;
2714 decode_ssversion(&disc.ssversion,
2715 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2716 }
2717
Harald Welte0abe5a62009-07-23 19:06:52 +02002718 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002719
2720}
2721
Harald Weltebbc636a2009-06-11 14:23:20 +08002722static struct gsm_mncc_cause default_cause = {
2723 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2724 .coding = 0,
2725 .rec = 0,
2726 .rec_val = 0,
2727 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2728 .diag_len = 0,
2729 .diag = { 0 },
2730};
Harald Welte03740842009-06-10 23:11:52 +08002731
2732static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2733{
2734 struct gsm_mncc *disc = arg;
2735 struct msgb *msg = gsm48_msgb_alloc();
2736 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2737
Harald Welte03740842009-06-10 23:11:52 +08002738 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2739
2740 gsm48_stop_cc_timer(trans);
2741 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2742
2743 /* cause */
2744 if (disc->fields & MNCC_F_CAUSE)
2745 encode_cause(msg, 1, &disc->cause);
2746 else
2747 encode_cause(msg, 1, &default_cause);
2748
2749 /* facility */
2750 if (disc->fields & MNCC_F_FACILITY)
2751 encode_facility(msg, 0, &disc->facility);
2752 /* progress */
2753 if (disc->fields & MNCC_F_PROGRESS)
2754 encode_progress(msg, 0, &disc->progress);
2755 /* user-user */
2756 if (disc->fields & MNCC_F_USERUSER)
2757 encode_useruser(msg, 0, &disc->useruser);
2758
2759 /* store disconnect cause for T306 expiry */
Harald Weltec2189a62009-07-23 18:56:43 +02002760 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002761
2762 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2763
Harald Welte36fe2e82009-07-23 21:13:03 +02002764 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002765}
2766
2767static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2768{
2769 struct gsm48_hdr *gh = msgb_l3(msg);
2770 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2771 struct tlv_parsed tp;
2772 struct gsm_mncc rel;
2773 int rc;
2774
2775 gsm48_stop_cc_timer(trans);
2776
2777 memset(&rel, 0, sizeof(struct gsm_mncc));
2778 rel.callref = trans->callref;
2779 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2780 /* cause */
2781 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2782 rel.fields |= MNCC_F_CAUSE;
2783 decode_cause(&rel.cause,
2784 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2785 }
2786 /* facility */
2787 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2788 rel.fields |= MNCC_F_FACILITY;
2789 decode_facility(&rel.facility,
2790 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2791 }
2792 /* user-user */
2793 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2794 rel.fields |= MNCC_F_USERUSER;
2795 decode_useruser(&rel.useruser,
2796 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2797 }
2798 /* ss-version */
2799 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2800 rel.fields |= MNCC_F_SSVERSION;
2801 decode_ssversion(&rel.ssversion,
2802 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2803 }
2804
Harald Weltec2189a62009-07-23 18:56:43 +02002805 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002806 /* release collision 5.4.5 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002807 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002808 } else {
Harald Welte0abe5a62009-07-23 19:06:52 +02002809 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002810 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte0abe5a62009-07-23 19:06:52 +02002811 GSM48_MT_CC_RELEASE_COMPL);
2812 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002813 }
2814
2815 new_cc_state(trans, GSM_CSTATE_NULL);
2816
2817 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002818 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002819
2820 return rc;
2821}
2822
2823static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2824{
2825 struct gsm_mncc *rel = arg;
2826 struct msgb *msg = gsm48_msgb_alloc();
2827 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2828
Harald Welte03740842009-06-10 23:11:52 +08002829 gh->msg_type = GSM48_MT_CC_RELEASE;
2830
2831 trans->callref = 0;
2832
2833 gsm48_stop_cc_timer(trans);
2834 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2835
2836 /* cause */
2837 if (rel->fields & MNCC_F_CAUSE)
2838 encode_cause(msg, 0, &rel->cause);
2839 /* facility */
2840 if (rel->fields & MNCC_F_FACILITY)
2841 encode_facility(msg, 0, &rel->facility);
2842 /* user-user */
2843 if (rel->fields & MNCC_F_USERUSER)
2844 encode_useruser(msg, 0, &rel->useruser);
2845
Harald Weltec2189a62009-07-23 18:56:43 +02002846 trans->cc.T308_second = 0;
2847 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002848
Harald Weltec2189a62009-07-23 18:56:43 +02002849 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002850 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2851
Harald Welte36fe2e82009-07-23 21:13:03 +02002852 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002853}
2854
2855static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2856{
2857 struct gsm48_hdr *gh = msgb_l3(msg);
2858 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2859 struct tlv_parsed tp;
2860 struct gsm_mncc rel;
2861 int rc = 0;
2862
2863 gsm48_stop_cc_timer(trans);
2864
2865 memset(&rel, 0, sizeof(struct gsm_mncc));
2866 rel.callref = trans->callref;
2867 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2868 /* cause */
2869 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2870 rel.fields |= MNCC_F_CAUSE;
2871 decode_cause(&rel.cause,
2872 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2873 }
2874 /* facility */
2875 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2876 rel.fields |= MNCC_F_FACILITY;
2877 decode_facility(&rel.facility,
2878 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2879 }
2880 /* user-user */
2881 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2882 rel.fields |= MNCC_F_USERUSER;
2883 decode_useruser(&rel.useruser,
2884 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2885 }
2886 /* ss-version */
2887 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2888 rel.fields |= MNCC_F_SSVERSION;
2889 decode_ssversion(&rel.ssversion,
2890 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2891 }
2892
2893 if (trans->callref) {
Harald Weltec2189a62009-07-23 18:56:43 +02002894 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08002895 case GSM_CSTATE_CALL_PRESENT:
Harald Welte0abe5a62009-07-23 19:06:52 +02002896 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002897 MNCC_REJ_IND, &rel);
2898 break;
2899 case GSM_CSTATE_RELEASE_REQ:
Harald Welte0abe5a62009-07-23 19:06:52 +02002900 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002901 MNCC_REL_CNF, &rel);
2902 break;
2903 default:
Harald Welte0abe5a62009-07-23 19:06:52 +02002904 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002905 MNCC_REL_IND, &rel);
2906 }
2907 }
2908
2909 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002910 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002911
2912 return rc;
2913}
2914
2915static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2916{
2917 struct gsm_mncc *rel = arg;
2918 struct msgb *msg = gsm48_msgb_alloc();
2919 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2920
Harald Welte03740842009-06-10 23:11:52 +08002921 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2922
2923 trans->callref = 0;
2924
2925 gsm48_stop_cc_timer(trans);
2926
2927 /* cause */
2928 if (rel->fields & MNCC_F_CAUSE)
2929 encode_cause(msg, 0, &rel->cause);
2930 /* facility */
2931 if (rel->fields & MNCC_F_FACILITY)
2932 encode_facility(msg, 0, &rel->facility);
2933 /* user-user */
2934 if (rel->fields & MNCC_F_USERUSER)
2935 encode_useruser(msg, 0, &rel->useruser);
2936
Harald Weltec2189a62009-07-23 18:56:43 +02002937 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002938
Harald Welte36fe2e82009-07-23 21:13:03 +02002939 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002940}
2941
2942static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2943{
2944 struct gsm48_hdr *gh = msgb_l3(msg);
2945 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2946 struct tlv_parsed tp;
2947 struct gsm_mncc fac;
2948
2949 memset(&fac, 0, sizeof(struct gsm_mncc));
2950 fac.callref = trans->callref;
2951 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2952 /* facility */
2953 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2954 fac.fields |= MNCC_F_FACILITY;
2955 decode_facility(&fac.facility,
2956 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2957 }
2958 /* ss-version */
2959 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2960 fac.fields |= MNCC_F_SSVERSION;
2961 decode_ssversion(&fac.ssversion,
2962 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2963 }
2964
Harald Welte0abe5a62009-07-23 19:06:52 +02002965 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08002966}
2967
2968static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2969{
2970 struct gsm_mncc *fac = arg;
2971 struct msgb *msg = gsm48_msgb_alloc();
2972 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2973
Harald Welte03740842009-06-10 23:11:52 +08002974 gh->msg_type = GSM48_MT_CC_FACILITY;
2975
2976 /* facility */
2977 encode_facility(msg, 1, &fac->facility);
2978
Harald Welte36fe2e82009-07-23 21:13:03 +02002979 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002980}
2981
2982static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2983{
2984 struct gsm_mncc hold;
2985
2986 memset(&hold, 0, sizeof(struct gsm_mncc));
2987 hold.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002988 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08002989}
2990
2991static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2992{
2993 struct msgb *msg = gsm48_msgb_alloc();
2994 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2995
Harald Welte03740842009-06-10 23:11:52 +08002996 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2997
Harald Welte36fe2e82009-07-23 21:13:03 +02002998 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002999}
3000
3001static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3002{
3003 struct gsm_mncc *hold_rej = arg;
3004 struct msgb *msg = gsm48_msgb_alloc();
3005 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3006
Harald Welte03740842009-06-10 23:11:52 +08003007 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3008
3009 /* cause */
3010 if (hold_rej->fields & MNCC_F_CAUSE)
3011 encode_cause(msg, 1, &hold_rej->cause);
3012 else
3013 encode_cause(msg, 1, &default_cause);
3014
Harald Welte36fe2e82009-07-23 21:13:03 +02003015 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003016}
3017
3018static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3019{
3020 struct gsm_mncc retrieve;
3021
3022 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3023 retrieve.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003024 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3025 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08003026}
3027
3028static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3029{
3030 struct msgb *msg = gsm48_msgb_alloc();
3031 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3032
Harald Welte03740842009-06-10 23:11:52 +08003033 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3034
Harald Welte36fe2e82009-07-23 21:13:03 +02003035 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003036}
3037
3038static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3039{
3040 struct gsm_mncc *retrieve_rej = arg;
3041 struct msgb *msg = gsm48_msgb_alloc();
3042 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3043
Harald Welte03740842009-06-10 23:11:52 +08003044 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3045
3046 /* cause */
3047 if (retrieve_rej->fields & MNCC_F_CAUSE)
3048 encode_cause(msg, 1, &retrieve_rej->cause);
3049 else
3050 encode_cause(msg, 1, &default_cause);
3051
Harald Welte36fe2e82009-07-23 21:13:03 +02003052 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003053}
3054
3055static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3056{
3057 struct gsm48_hdr *gh = msgb_l3(msg);
3058 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3059 struct tlv_parsed tp;
3060 struct gsm_mncc dtmf;
3061
3062 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3063 dtmf.callref = trans->callref;
3064 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3065 /* keypad facility */
3066 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3067 dtmf.fields |= MNCC_F_KEYPAD;
3068 decode_keypad(&dtmf.keypad,
3069 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3070 }
3071
Harald Welte0abe5a62009-07-23 19:06:52 +02003072 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003073}
3074
3075static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3076{
3077 struct gsm_mncc *dtmf = arg;
3078 struct msgb *msg = gsm48_msgb_alloc();
3079 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3080
Harald Welte03740842009-06-10 23:11:52 +08003081 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3082
3083 /* keypad */
3084 if (dtmf->fields & MNCC_F_KEYPAD)
3085 encode_keypad(msg, dtmf->keypad);
3086
Harald Welte36fe2e82009-07-23 21:13:03 +02003087 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003088}
3089
3090static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3091{
3092 struct gsm_mncc *dtmf = arg;
3093 struct msgb *msg = gsm48_msgb_alloc();
3094 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3095
Harald Welte03740842009-06-10 23:11:52 +08003096 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3097
3098 /* cause */
3099 if (dtmf->fields & MNCC_F_CAUSE)
3100 encode_cause(msg, 1, &dtmf->cause);
3101 else
3102 encode_cause(msg, 1, &default_cause);
3103
Harald Welte36fe2e82009-07-23 21:13:03 +02003104 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003105}
3106
3107static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3108{
3109 struct msgb *msg = gsm48_msgb_alloc();
3110 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3111
Harald Welte03740842009-06-10 23:11:52 +08003112 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3113
Harald Welte36fe2e82009-07-23 21:13:03 +02003114 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003115}
3116
3117static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3118{
3119 struct gsm_mncc dtmf;
3120
3121 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3122 dtmf.callref = trans->callref;
3123
Harald Welte0abe5a62009-07-23 19:06:52 +02003124 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003125}
3126
3127static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3128{
3129 struct gsm48_hdr *gh = msgb_l3(msg);
3130 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3131 struct tlv_parsed tp;
3132 struct gsm_mncc modify;
3133
3134 memset(&modify, 0, sizeof(struct gsm_mncc));
3135 modify.callref = trans->callref;
3136 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3137 /* bearer capability */
3138 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3139 modify.fields |= MNCC_F_BEARER_CAP;
3140 decode_bearer_cap(&modify.bearer_cap,
3141 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3142 }
3143
3144 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3145
Harald Welte0abe5a62009-07-23 19:06:52 +02003146 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003147}
3148
3149static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3150{
3151 struct gsm_mncc *modify = arg;
3152 struct msgb *msg = gsm48_msgb_alloc();
3153 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3154
Harald Welte03740842009-06-10 23:11:52 +08003155 gh->msg_type = GSM48_MT_CC_MODIFY;
3156
3157 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3158
3159 /* bearer capability */
3160 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3161
3162 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3163
Harald Welte36fe2e82009-07-23 21:13:03 +02003164 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003165}
3166
3167static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3168{
3169 struct gsm48_hdr *gh = msgb_l3(msg);
3170 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3171 struct tlv_parsed tp;
3172 struct gsm_mncc modify;
3173
3174 gsm48_stop_cc_timer(trans);
3175
3176 memset(&modify, 0, sizeof(struct gsm_mncc));
3177 modify.callref = trans->callref;
3178 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3179 /* bearer capability */
3180 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3181 modify.fields |= MNCC_F_BEARER_CAP;
3182 decode_bearer_cap(&modify.bearer_cap,
3183 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3184 }
3185
3186 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3187
Harald Welte0abe5a62009-07-23 19:06:52 +02003188 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003189}
3190
3191static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3192{
3193 struct gsm_mncc *modify = arg;
3194 struct msgb *msg = gsm48_msgb_alloc();
3195 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3196
Harald Welte03740842009-06-10 23:11:52 +08003197 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3198
3199 /* bearer capability */
3200 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3201
3202 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3203
Harald Welte36fe2e82009-07-23 21:13:03 +02003204 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003205}
3206
3207static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3208{
3209 struct gsm48_hdr *gh = msgb_l3(msg);
3210 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3211 struct tlv_parsed tp;
3212 struct gsm_mncc modify;
3213
3214 gsm48_stop_cc_timer(trans);
3215
3216 memset(&modify, 0, sizeof(struct gsm_mncc));
3217 modify.callref = trans->callref;
3218 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3219 /* bearer capability */
3220 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3221 modify.fields |= GSM48_IE_BEARER_CAP;
3222 decode_bearer_cap(&modify.bearer_cap,
3223 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3224 }
3225 /* cause */
3226 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3227 modify.fields |= MNCC_F_CAUSE;
3228 decode_cause(&modify.cause,
3229 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3230 }
3231
3232 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3233
Harald Welte0abe5a62009-07-23 19:06:52 +02003234 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003235}
3236
3237static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3238{
3239 struct gsm_mncc *modify = arg;
3240 struct msgb *msg = gsm48_msgb_alloc();
3241 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3242
Harald Welte03740842009-06-10 23:11:52 +08003243 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3244
3245 /* bearer capability */
3246 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3247 /* cause */
3248 encode_cause(msg, 1, &modify->cause);
3249
3250 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3251
Harald Welte36fe2e82009-07-23 21:13:03 +02003252 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003253}
3254
3255static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3256{
3257 struct gsm_mncc *notify = arg;
3258 struct msgb *msg = gsm48_msgb_alloc();
3259 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3260
Harald Welte03740842009-06-10 23:11:52 +08003261 gh->msg_type = GSM48_MT_CC_NOTIFY;
3262
3263 /* notify */
3264 encode_notify(msg, notify->notify);
3265
Harald Welte36fe2e82009-07-23 21:13:03 +02003266 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003267}
3268
3269static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3270{
3271 struct gsm48_hdr *gh = msgb_l3(msg);
3272 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3273// struct tlv_parsed tp;
3274 struct gsm_mncc notify;
3275
3276 memset(&notify, 0, sizeof(struct gsm_mncc));
3277 notify.callref = trans->callref;
3278// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3279 if (payload_len >= 1)
3280 decode_notify(&notify.notify, gh->data);
3281
Harald Welte0abe5a62009-07-23 19:06:52 +02003282 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003283}
3284
3285static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3286{
3287 struct gsm_mncc *user = arg;
3288 struct msgb *msg = gsm48_msgb_alloc();
3289 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3290
Harald Welte03740842009-06-10 23:11:52 +08003291 gh->msg_type = GSM48_MT_CC_USER_INFO;
3292
3293 /* user-user */
3294 if (user->fields & MNCC_F_USERUSER)
3295 encode_useruser(msg, 1, &user->useruser);
3296 /* more data */
3297 if (user->more)
3298 encode_more(msg);
3299
Harald Welte36fe2e82009-07-23 21:13:03 +02003300 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003301}
3302
3303static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3304{
3305 struct gsm48_hdr *gh = msgb_l3(msg);
3306 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3307 struct tlv_parsed tp;
3308 struct gsm_mncc user;
3309
3310 memset(&user, 0, sizeof(struct gsm_mncc));
3311 user.callref = trans->callref;
3312 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3313 /* user-user */
3314 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3315 user.fields |= MNCC_F_USERUSER;
3316 decode_useruser(&user.useruser,
3317 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3318 }
3319 /* more data */
3320 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3321 user.more = 1;
3322
Harald Welte0abe5a62009-07-23 19:06:52 +02003323 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003324}
3325
3326static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3327{
3328 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003329 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003330
Harald Welteca745e22009-07-29 12:10:35 +02003331 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3332 if (rc < 0)
3333 return rc;
3334
3335 /* FIXME: we not only need to do this after mode modify, but
3336 * also after channel activation */
3337 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3338 mode->lchan_mode != GSM48_CMODE_SIGN)
3339 rc = rsl_ipacc_bind(trans->lchan);
3340
3341 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003342}
3343
3344static struct downstate {
3345 u_int32_t states;
3346 int type;
3347 int (*rout) (struct gsm_trans *trans, void *arg);
3348} downstatelist[] = {
3349 /* mobile originating call establishment */
3350 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3351 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3352 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3353 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3354 {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 */
3355 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3356 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3357 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3358 /* mobile terminating call establishment */
3359 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3360 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3361 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3362 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3363 /* signalling during call */
3364 {SBIT(GSM_CSTATE_ACTIVE),
3365 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3366 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3367 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3368 {ALL_STATES,
3369 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3370 {ALL_STATES,
3371 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3372 {ALL_STATES,
3373 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3374 {SBIT(GSM_CSTATE_ACTIVE),
3375 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3376 {SBIT(GSM_CSTATE_ACTIVE),
3377 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3378 {SBIT(GSM_CSTATE_ACTIVE),
3379 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3380 {SBIT(GSM_CSTATE_ACTIVE),
3381 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3382 {SBIT(GSM_CSTATE_ACTIVE),
3383 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3384 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3385 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3386 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3387 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3388 {SBIT(GSM_CSTATE_ACTIVE),
3389 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3390 /* clearing */
3391 {SBIT(GSM_CSTATE_INITIATED),
3392 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3393 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3394 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3395 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3396 MNCC_REL_REQ, gsm48_cc_tx_release},
3397 /* special */
3398 {ALL_STATES,
3399 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3400};
3401
3402#define DOWNSLLEN \
3403 (sizeof(downstatelist) / sizeof(struct downstate))
3404
3405
3406int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3407{
Harald Welteaa60edb2009-08-09 18:52:33 +02003408 int i, rc = 0;
Harald Welte03740842009-06-10 23:11:52 +08003409 struct gsm_trans *trans = NULL, *transt;
3410 struct gsm_subscriber *subscr;
Harald Welteaa60edb2009-08-09 18:52:33 +02003411 struct gsm_lchan *lchan = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003412 struct gsm_bts *bts = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003413 struct gsm_mncc *data = arg, rel;
3414
3415 /* handle special messages */
3416 switch(msg_type) {
3417 case MNCC_BRIDGE:
3418 return tch_bridge(net, arg);
3419 case MNCC_FRAME_DROP:
3420 return tch_recv(net, arg, 0);
3421 case MNCC_FRAME_RECV:
3422 return tch_recv(net, arg, 1);
3423 case GSM_TRAU_FRAME:
3424 return tch_frame(net, arg);
3425 }
3426
3427 memset(&rel, 0, sizeof(struct gsm_mncc));
3428 rel.callref = data->callref;
3429
3430 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02003431 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003432
3433 /* Callref unknown */
3434 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003435 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003436 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3437 "Received '%s' from MNCC with "
3438 "unknown callref %d\n", data->called.number,
3439 get_mncc_name(msg_type), data->callref);
3440 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003441 return mncc_release_ind(net, NULL, data->callref,
3442 GSM48_CAUSE_LOC_PRN_S_LU,
3443 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003444 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003445 if (!data->called.number[0] && !data->imsi[0]) {
3446 DEBUGP(DCC, "(bts - trx - ts - ti) "
3447 "Received '%s' from MNCC with "
3448 "no number or IMSI\n", get_mncc_name(msg_type));
3449 /* Invalid number */
3450 return mncc_release_ind(net, NULL, data->callref,
3451 GSM48_CAUSE_LOC_PRN_S_LU,
3452 GSM48_CC_CAUSE_INV_NR_FORMAT);
3453 }
Harald Welte03740842009-06-10 23:11:52 +08003454 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003455 if (data->called.number[0])
Harald Welte75350412009-07-23 18:46:00 +02003456 subscr = subscr_get_by_extension(net,
3457 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003458 else
Harald Welte75350412009-07-23 18:46:00 +02003459 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003460 /* If subscriber is not found */
3461 if (!subscr) {
3462 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3463 "Received '%s' from MNCC with "
3464 "unknown subscriber %s\n", data->called.number,
3465 get_mncc_name(msg_type), data->called.number);
3466 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003467 return mncc_release_ind(net, NULL, data->callref,
3468 GSM48_CAUSE_LOC_PRN_S_LU,
3469 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003470 }
3471 /* If subscriber is not "attached" */
3472 if (!subscr->lac) {
3473 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3474 "Received '%s' from MNCC with "
3475 "detached subscriber %s\n", data->called.number,
3476 get_mncc_name(msg_type), data->called.number);
3477 subscr_put(subscr);
3478 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003479 return mncc_release_ind(net, NULL, data->callref,
3480 GSM48_CAUSE_LOC_PRN_S_LU,
3481 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003482 }
3483 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003484 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3485 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003486 DEBUGP(DCC, "No memory for trans.\n");
3487 subscr_put(subscr);
3488 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003489 mncc_release_ind(net, NULL, data->callref,
3490 GSM48_CAUSE_LOC_PRN_S_LU,
3491 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003492 return -ENOMEM;
3493 }
Harald Welte03740842009-06-10 23:11:52 +08003494 /* Find lchan */
Harald Welteaa60edb2009-08-09 18:52:33 +02003495 lchan = lchan_for_subscr(subscr);
Harald Welte03740842009-06-10 23:11:52 +08003496 /* If subscriber has no lchan */
3497 if (!lchan) {
3498 /* find transaction with this subscriber already paging */
3499 llist_for_each_entry(transt, &net->trans_list, entry) {
3500 /* Transaction of our lchan? */
3501 if (transt == trans ||
3502 transt->subscr != subscr)
3503 continue;
3504 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3505 "Received '%s' from MNCC with "
3506 "unallocated channel, paging already "
3507 "started.\n", bts->nr,
3508 data->called.number,
3509 get_mncc_name(msg_type));
3510 return 0;
3511 }
3512 /* store setup informations until paging was successfull */
Harald Weltec2189a62009-07-23 18:56:43 +02003513 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte2a3a81b2009-08-01 19:31:47 +02003514 /* Trigger paging */
3515 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3516 setup_trig_pag_evt, subscr);
Harald Welte03740842009-06-10 23:11:52 +08003517 return 0;
3518 }
3519 /* Assign lchan */
3520 trans->lchan = lchan;
3521 use_lchan(lchan);
3522 }
3523 lchan = trans->lchan;
3524
3525 /* if paging did not respond yet */
3526 if (!lchan) {
3527 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3528 "Received '%s' from MNCC in paging state\n",
3529 (trans->subscr)?(trans->subscr->extension):"-",
3530 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003531 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3532 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003533 if (msg_type == MNCC_REL_REQ)
3534 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3535 else
3536 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3537 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003538 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003539 return rc;
3540 }
3541
3542 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3543 "Received '%s' from MNCC in state %d (%s)\n",
3544 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3545 trans->transaction_id,
3546 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003547 get_mncc_name(msg_type), trans->cc.state,
3548 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003549
3550 /* Find function for current state and message */
3551 for (i = 0; i < DOWNSLLEN; i++)
3552 if ((msg_type == downstatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003553 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003554 break;
3555 if (i == DOWNSLLEN) {
3556 DEBUGP(DCC, "Message unhandled at this state.\n");
3557 return 0;
3558 }
3559
3560 rc = downstatelist[i].rout(trans, arg);
3561
3562 return rc;
3563}
3564
3565
3566static struct datastate {
3567 u_int32_t states;
3568 int type;
3569 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3570} datastatelist[] = {
3571 /* mobile originating call establishment */
3572 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3573 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3574 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3575 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3576 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3577 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3578 /* mobile terminating call establishment */
3579 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3580 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3581 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3582 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3583 {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 */
3584 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3585 /* signalling during call */
3586 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3587 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3588 {SBIT(GSM_CSTATE_ACTIVE),
3589 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3590 {ALL_STATES,
3591 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3592 {ALL_STATES,
3593 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3594 {ALL_STATES,
3595 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3596 {SBIT(GSM_CSTATE_ACTIVE),
3597 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3598 {SBIT(GSM_CSTATE_ACTIVE),
3599 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3600 {SBIT(GSM_CSTATE_ACTIVE),
3601 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3602 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3603 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3604 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3605 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3606 {SBIT(GSM_CSTATE_ACTIVE),
3607 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3608 /* clearing */
3609 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3610 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3611 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3612 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3613 {ALL_STATES, /* 5.4.3.4 */
3614 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3615};
3616
3617#define DATASLLEN \
3618 (sizeof(datastatelist) / sizeof(struct datastate))
3619
Harald Welte59b04682009-06-10 05:40:52 +08003620static int gsm0408_rcv_cc(struct msgb *msg)
3621{
3622 struct gsm48_hdr *gh = msgb_l3(msg);
3623 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003624 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003625 struct gsm_lchan *lchan = msg->lchan;
Harald Weltec2189a62009-07-23 18:56:43 +02003626 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003627 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003628
Harald Welte03740842009-06-10 23:11:52 +08003629 if (msg_type & 0x80) {
3630 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3631 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003632 }
Harald Welte03740842009-06-10 23:11:52 +08003633
3634 /* Find transaction */
Harald Welte0d824162009-07-23 21:58:40 +02003635 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltec2189a62009-07-23 18:56:43 +02003636
Harald Welte4861c822009-07-23 21:21:14 +02003637 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003638 "Received '%s' from MS in state %d (%s)\n",
3639 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3640 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003641 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3642 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003643
3644 /* Create transaction */
3645 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003646 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003647 "creating new trans.\n", transaction_id);
3648 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003649 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3650 transaction_id, new_callref++);
3651 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003652 DEBUGP(DCC, "No memory for trans.\n");
3653 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003654 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003655 GSM48_MT_CC_RELEASE_COMPL);
3656 return -ENOMEM;
3657 }
Harald Welte03740842009-06-10 23:11:52 +08003658 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003659 trans->lchan = lchan;
3660 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003661 }
3662
3663 /* find function for current state and message */
3664 for (i = 0; i < DATASLLEN; i++)
3665 if ((msg_type == datastatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003666 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003667 break;
3668 if (i == DATASLLEN) {
3669 DEBUGP(DCC, "Message unhandled at this state.\n");
3670 return 0;
3671 }
3672
3673 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003674
3675 return rc;
3676}
3677
3678/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3679int gsm0408_rcvmsg(struct msgb *msg)
3680{
3681 struct gsm48_hdr *gh = msgb_l3(msg);
3682 u_int8_t pdisc = gh->proto_discr & 0x0f;
3683 int rc = 0;
3684
3685 switch (pdisc) {
3686 case GSM48_PDISC_CC:
3687 rc = gsm0408_rcv_cc(msg);
3688 break;
3689 case GSM48_PDISC_MM:
3690 rc = gsm0408_rcv_mm(msg);
3691 break;
3692 case GSM48_PDISC_RR:
3693 rc = gsm0408_rcv_rr(msg);
3694 break;
3695 case GSM48_PDISC_SMS:
3696 rc = gsm0411_rcv_sms(msg);
3697 break;
3698 case GSM48_PDISC_MM_GPRS:
3699 case GSM48_PDISC_SM_GPRS:
3700 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3701 pdisc);
3702 break;
3703 default:
3704 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3705 pdisc);
3706 break;
3707 }
3708
3709 return rc;
3710}
3711
Harald Welte59b04682009-06-10 05:40:52 +08003712/* Section 9.1.8 / Table 9.9 */
3713struct chreq {
3714 u_int8_t val;
3715 u_int8_t mask;
3716 enum chreq_type type;
3717};
3718
3719/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3720static const struct chreq chreq_type_neci1[] = {
3721 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3722 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3723 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3724 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3725 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3726 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3727 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3728 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3729 { 0x10, 0xf0, CHREQ_T_SDCCH },
3730 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3731 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3732 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3733};
3734
3735/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3736static const struct chreq chreq_type_neci0[] = {
3737 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3738 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3739 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3740 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3741 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3742 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3743 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3744 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3745};
3746
3747static const enum gsm_chan_t ctype_by_chreq[] = {
3748 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3749 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3750 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3751 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3752 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3753 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3754 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3755 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3756 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3757 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3758 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3759 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3760};
3761
3762static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3763 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3764 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3765 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3766 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3767 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3768 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3769 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3770 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3771 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3772 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3773 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3774 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3775};
3776
3777enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3778{
3779 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003780 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003781
Harald Welte1ab707e2009-08-10 02:14:46 +02003782 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3783 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003784 if ((ra & chr->mask) == chr->val)
3785 return ctype_by_chreq[chr->type];
3786 }
3787 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3788 return GSM_LCHAN_SDCCH;
3789}
3790
3791enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3792{
3793 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003794 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003795
Harald Welte1ab707e2009-08-10 02:14:46 +02003796 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3797 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003798 if ((ra & chr->mask) == chr->val)
3799 return reason_by_chreq[chr->type];
3800 }
3801 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3802 return GSM_CHREQ_REASON_OTHER;
3803}
Harald Welte03740842009-06-10 23:11:52 +08003804
3805/* dequeue messages to layer 4 */
3806int bsc_upqueue(struct gsm_network *net)
3807{
3808 struct gsm_mncc *mncc;
3809 struct msgb *msg;
3810 int work = 0;
3811
3812 if (net)
3813 while ((msg = msgb_dequeue(&net->upqueue))) {
3814 mncc = (struct gsm_mncc *)msg->data;
3815 if (net->mncc_recv)
3816 net->mncc_recv(net, mncc->msg_type, mncc);
3817 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003818 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003819 }
3820
3821 return work;
3822}
Harald Weltec2189a62009-07-23 18:56:43 +02003823
Harald Welte3c062072009-07-28 18:25:29 +02003824/*
3825 * This will be ran by the linker when loading the DSO. We use it to
3826 * do system initialization, e.g. registration of signal handlers.
3827 */
3828static __attribute__((constructor)) void on_dso_load_0408(void)
3829{
3830 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3831 "loc_updating_oper");
3832 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3833 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3834}