blob: a7577d249dd23c412439107674f3d7a7d35750a9 [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 Weltea54b48d2009-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;
248 if (data[1] & 0x40)
249 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)) {
367 db_subscriber_alloc_tmsi(lchan->subscr);
368 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
369 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
370 release_loc_updating_req(lchan);
371 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
372 }
373
374 return 0;
375}
376
377static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
378 void *handler_data, void *signal_data)
379{
Harald Welte03740842009-06-10 23:11:52 +0800380 struct gsm_trans *trans, *temp;
381
Harald Welte59b04682009-06-10 05:40:52 +0800382 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
383 return 0;
384
385 /*
386 * Cancel any outstanding location updating request
387 * operation taking place on the lchan.
388 */
Harald Welte12560da2009-07-04 09:35:21 +0200389 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Welte1ff81b52009-06-26 20:17:06 +0200390 if (!lchan)
391 return 0;
392
Harald Welte59b04682009-06-10 05:40:52 +0800393 release_loc_updating_req(lchan);
394
Harald Welte03740842009-06-10 23:11:52 +0800395 /* Free all transactions that are associated with the released lchan */
Harald Weltea54b48d2009-07-23 18:56:43 +0200396 /* FIXME: this is not neccessarily the right thing to do, we should
397 * only set trans->lchan to NULL and wait for another lchan to be
398 * established to the same MM entity (phone/subscriber) */
Harald Welte03740842009-06-10 23:11:52 +0800399 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
400 if (trans->lchan == lchan)
Harald Weltea54b48d2009-07-23 18:56:43 +0200401 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +0800402 }
403
Harald Welte59b04682009-06-10 05:40:52 +0800404 return 0;
405}
406
Harald Welte59b04682009-06-10 05:40:52 +0800407static void to_bcd(u_int8_t *bcd, u_int16_t val)
408{
409 bcd[2] = val % 10;
410 val = val / 10;
411 bcd[1] = val % 10;
412 val = val / 10;
413 bcd[0] = val % 10;
414 val = val / 10;
415}
416
417void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
418 u_int16_t mnc, u_int16_t lac)
419{
420 u_int8_t bcd[3];
421
422 to_bcd(bcd, mcc);
423 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
424 lai48->digits[1] = bcd[2];
425
426 to_bcd(bcd, mnc);
427 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
428#if 0
429 lai48->digits[1] |= bcd[2] << 4;
430 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
431#else
432 lai48->digits[1] |= 0xf << 4;
433 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
434#endif
435
436 lai48->lac = htons(lac);
437}
438
439#define TMSI_LEN 5
440#define MID_TMSI_LEN (TMSI_LEN + 2)
441
442int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
443{
444 u_int32_t *tptr = (u_int32_t *) &buf[3];
445
446 buf[0] = GSM48_IE_MOBILE_ID;
447 buf[1] = TMSI_LEN;
448 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
449 *tptr = htonl(tmsi);
450
451 return 7;
452}
453
454static const char bcd_num_digits[] = {
455 '0', '1', '2', '3', '4', '5', '6', '7',
456 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
457};
458
Harald Welteb8a18b52009-06-10 12:08:54 +0800459/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
460int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
461 int h_len)
Harald Welte59b04682009-06-10 05:40:52 +0800462{
463 u_int8_t in_len = bcd_lv[0];
464 int i;
465
Harald Welteb8a18b52009-06-10 12:08:54 +0800466 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte59b04682009-06-10 05:40:52 +0800467 /* lower nibble */
468 output_len--;
469 if (output_len <= 1)
470 break;
471 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
472
473 /* higher nibble */
474 output_len--;
475 if (output_len <= 1)
476 break;
477 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
478 }
479 if (output_len >= 1)
480 *output++ = '\0';
481
Harald Welteb8a18b52009-06-10 12:08:54 +0800482 return 0;
Harald Welte59b04682009-06-10 05:40:52 +0800483}
484
485/* convert a single ASCII character to call-control BCD */
486static int asc_to_bcd(const char asc)
487{
488 int i;
489
490 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
491 if (bcd_num_digits[i] == asc)
492 return i;
493 }
494 return -EINVAL;
495}
496
Harald Welteb8a18b52009-06-10 12:08:54 +0800497/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte59b04682009-06-10 05:40:52 +0800498int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welteb8a18b52009-06-10 12:08:54 +0800499 int h_len, const char *input)
Harald Welte59b04682009-06-10 05:40:52 +0800500{
501 int in_len = strlen(input);
502 int i;
Harald Welteb8a18b52009-06-10 12:08:54 +0800503 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800504
505 /* two digits per byte, plus type byte */
Harald Welteb8a18b52009-06-10 12:08:54 +0800506 bcd_lv[0] = in_len/2 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800507 if (in_len % 2)
508 bcd_lv[0]++;
509
Harald Welteb8a18b52009-06-10 12:08:54 +0800510 if (bcd_lv[0] > max_len)
511 return -EIO;
Harald Welte59b04682009-06-10 05:40:52 +0800512
513 for (i = 0; i < in_len; i++) {
514 int rc = asc_to_bcd(input[i]);
515 if (rc < 0)
516 return rc;
517 if (i % 2 == 0)
518 *bcd_cur = rc;
519 else
520 *bcd_cur++ |= (rc << 4);
521 }
522 /* append padding nibble in case of odd length */
523 if (i % 2)
524 *bcd_cur++ |= 0xf0;
525
526 /* return how many bytes we used */
527 return (bcd_cur - bcd_lv);
528}
529
Harald Welteb8a18b52009-06-10 12:08:54 +0800530/* decode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800531static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welteb8a18b52009-06-10 12:08:54 +0800532 const u_int8_t *lv)
533{
534 u_int8_t in_len = lv[0];
535 int i, s;
536
537 if (in_len < 1)
538 return -EINVAL;
539
Harald Welte03740842009-06-10 23:11:52 +0800540 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welteb8a18b52009-06-10 12:08:54 +0800541
542 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800543 bcap->transfer = lv[1] & 0x07;
544 bcap->mode = (lv[1] & 0x08) >> 3;
545 bcap->coding = (lv[1] & 0x10) >> 4;
546 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800547
548 i = 1;
549 s = 0;
550 while(!(lv[i] & 0x80)) {
551 i++; /* octet 3a etc */
552 if (in_len < i)
553 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800554 bcap->speech_ver[s++] = lv[i] & 0x0f;
555 bcap->speech_ver[s] = -1; /* end of list */
Harald Welteb8a18b52009-06-10 12:08:54 +0800556 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800557 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800558 if (s == 7) /* maximum speech versions + end of list */
559 return 0;
560 }
561
562 return 0;
563}
564
565/* encode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800566static int encode_bearer_cap(struct msgb *msg, int lv_only,
567 const struct gsm_mncc_bearer_cap *bcap)
Harald Welteb8a18b52009-06-10 12:08:54 +0800568{
569 u_int8_t lv[32 + 1];
570 int i, s;
571
Harald Welte03740842009-06-10 23:11:52 +0800572 lv[1] = bcap->transfer;
573 lv[1] |= bcap->mode << 3;
574 lv[1] |= bcap->coding << 4;
575 lv[1] |= bcap->radio << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800576
577 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800578 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800579 i++; /* octet 3a etc */
Harald Welte03740842009-06-10 23:11:52 +0800580 lv[i] = bcap->speech_ver[s];
Harald Welteb8a18b52009-06-10 12:08:54 +0800581 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800582 lv[i] |= bcap->speech_ctm << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800583 }
584 lv[i] |= 0x80; /* last IE of octet 3 etc */
585
586 lv[0] = i;
587 if (lv_only)
588 msgb_lv_put(msg, lv[0], lv+1);
589 else
590 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
591
592 return 0;
593}
594
595/* decode 'call control cap' */
Harald Welte03740842009-06-10 23:11:52 +0800596static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800597{
598 u_int8_t in_len = lv[0];
599
600 if (in_len < 1)
601 return -EINVAL;
602
603 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800604 ccap->dtmf = lv[1] & 0x01;
605 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welteb8a18b52009-06-10 12:08:54 +0800606
607 return 0;
608}
609
610/* decode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800611static int decode_called(struct gsm_mncc_number *called,
612 const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800613{
614 u_int8_t in_len = lv[0];
615
616 if (in_len < 1)
617 return -EINVAL;
618
619 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800620 called->plan = lv[1] & 0x0f;
621 called->type = (lv[1] & 0x70) >> 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800622
623 /* octet 4..N */
Harald Welte03740842009-06-10 23:11:52 +0800624 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800625
626 return 0;
627}
628
629/* encode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800630static int encode_called(struct msgb *msg,
631 const struct gsm_mncc_number *called)
Harald Welteb8a18b52009-06-10 12:08:54 +0800632{
633 u_int8_t lv[18];
634 int ret;
635
636 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800637 lv[1] = called->plan;
638 lv[1] |= called->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800639
640 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800641 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800642 if (ret < 0)
643 return ret;
644
645 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
646
647 return 0;
648}
649
650/* encode callerid of various IEs */
Harald Welte03740842009-06-10 23:11:52 +0800651static int encode_callerid(struct msgb *msg, int ie,
652 const struct gsm_mncc_number *callerid)
Harald Welteb8a18b52009-06-10 12:08:54 +0800653{
654 u_int8_t lv[13];
655 int h_len = 1;
656 int ret;
657
658 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800659 lv[1] = callerid->plan;
660 lv[1] |= callerid->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800661
Harald Welte03740842009-06-10 23:11:52 +0800662 if (callerid->present || callerid->screen) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800663 /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800664 lv[2] = callerid->screen;
665 lv[2] |= callerid->present << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800666 lv[2] |= 0x80;
667 h_len++;
668 } else
669 lv[1] |= 0x80;
670
671 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800672 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800673 if (ret < 0)
674 return ret;
675
676 msgb_tlv_put(msg, ie, lv[0], lv+1);
677
678 return 0;
679}
680
681/* decode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800682static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welteb8a18b52009-06-10 12:08:54 +0800683 const u_int8_t *lv)
684{
685 u_int8_t in_len = lv[0];
686 int i;
687
688 if (in_len < 2)
689 return -EINVAL;
690
Harald Welte03740842009-06-10 23:11:52 +0800691 cause->diag_len = 0;
Harald Welteb8a18b52009-06-10 12:08:54 +0800692
693 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800694 cause->location = lv[1] & 0x0f;
695 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800696
697 i = 1;
698 if (!(lv[i] & 0x80)) {
699 i++; /* octet 3a */
700 if (in_len < i+1)
701 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800702 cause->rec = 1;
703 cause->rec_val = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800704
705 }
706 i++;
707
708 /* octet 4 */
Harald Welte03740842009-06-10 23:11:52 +0800709 cause->value = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800710 i++;
711
712 if (in_len < i) /* no diag */
713 return 0;
714
715 if (in_len - (i-1) > 32) /* maximum 32 octets */
716 return 0;
717
718 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800719 memcpy(cause->diag, lv + i, in_len - (i-1));
720 cause->diag_len = in_len - (i-1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800721
722 return 0;
723}
724
725/* encode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800726static int encode_cause(struct msgb *msg, int lv_only,
727 const struct gsm_mncc_cause *cause)
Harald Welteb8a18b52009-06-10 12:08:54 +0800728{
729 u_int8_t lv[32+4];
730 int i;
731
Harald Welte03740842009-06-10 23:11:52 +0800732 if (cause->diag_len > 32)
Harald Welteb8a18b52009-06-10 12:08:54 +0800733 return -EINVAL;
734
735 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800736 lv[1] = cause->location;
737 lv[1] |= cause->coding << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800738
739 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800740 if (cause->rec) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800741 i++; /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800742 lv[i] = cause->rec_val;
Harald Welteb8a18b52009-06-10 12:08:54 +0800743 }
744 lv[i] |= 0x80; /* end of octet 3 */
745
746 /* octet 4 */
747 i++;
Harald Welte03740842009-06-10 23:11:52 +0800748 lv[i] = 0x80 | cause->value;
Harald Welteb8a18b52009-06-10 12:08:54 +0800749
750 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800751 if (cause->diag_len) {
752 memcpy(lv + i, cause->diag, cause->diag_len);
753 i += cause->diag_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800754 }
755
756 lv[0] = i;
757 if (lv_only)
758 msgb_lv_put(msg, lv[0], lv+1);
759 else
760 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
761
762 return 0;
763}
764
765/* encode 'calling number' */
Harald Welte03740842009-06-10 23:11:52 +0800766static int encode_calling(struct msgb *msg,
767 const struct gsm_mncc_number *calling)
Harald Welteb8a18b52009-06-10 12:08:54 +0800768{
Harald Welte03740842009-06-10 23:11:52 +0800769 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welteb8a18b52009-06-10 12:08:54 +0800770}
771
772/* encode 'connected number' */
Harald Welte03740842009-06-10 23:11:52 +0800773static int encode_connected(struct msgb *msg,
774 const struct gsm_mncc_number *connected)
Harald Welteb8a18b52009-06-10 12:08:54 +0800775{
Harald Welte03740842009-06-10 23:11:52 +0800776 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welteb8a18b52009-06-10 12:08:54 +0800777}
778
779/* encode 'redirecting number' */
Harald Welte03740842009-06-10 23:11:52 +0800780static int encode_redirecting(struct msgb *msg,
781 const struct gsm_mncc_number *redirecting)
Harald Welteb8a18b52009-06-10 12:08:54 +0800782{
Harald Welte03740842009-06-10 23:11:52 +0800783 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welteb8a18b52009-06-10 12:08:54 +0800784}
785
786/* decode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800787static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welteb8a18b52009-06-10 12:08:54 +0800788 const u_int8_t *lv)
789{
790 u_int8_t in_len = lv[0];
791
792 if (in_len < 1)
793 return -EINVAL;
794
Harald Welte03740842009-06-10 23:11:52 +0800795 if (in_len > sizeof(facility->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800796 return -EINVAL;
797
Harald Welte03740842009-06-10 23:11:52 +0800798 memcpy(facility->info, lv+1, in_len);
799 facility->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800800
801 return 0;
802}
803
804/* encode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800805static int encode_facility(struct msgb *msg, int lv_only,
806 const struct gsm_mncc_facility *facility)
Harald Welteb8a18b52009-06-10 12:08:54 +0800807{
808 u_int8_t lv[GSM_MAX_FACILITY + 1];
809
Harald Welte03740842009-06-10 23:11:52 +0800810 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welteb8a18b52009-06-10 12:08:54 +0800811 return -EINVAL;
812
Harald Welte03740842009-06-10 23:11:52 +0800813 memcpy(lv+1, facility->info, facility->len);
814 lv[0] = facility->len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800815 if (lv_only)
816 msgb_lv_put(msg, lv[0], lv+1);
817 else
818 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
819
820 return 0;
821}
822
823/* decode 'notify' */
824static int decode_notify(int *notify, const u_int8_t *v)
825{
826 *notify = v[0] & 0x7f;
827
828 return 0;
829}
830
831/* encode 'notify' */
832static int encode_notify(struct msgb *msg, int notify)
833{
834 msgb_v_put(msg, notify | 0x80);
835
836 return 0;
837}
838
839/* encode 'signal' */
840static int encode_signal(struct msgb *msg, int signal)
841{
842 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
843
844 return 0;
845}
846
847/* decode 'keypad' */
848static int decode_keypad(int *keypad, const u_int8_t *lv)
849{
850 u_int8_t in_len = lv[0];
851
852 if (in_len < 1)
853 return -EINVAL;
854
855 *keypad = lv[1] & 0x7f;
856
857 return 0;
858}
859
860/* encode 'keypad' */
861static int encode_keypad(struct msgb *msg, int keypad)
862{
863 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
864
865 return 0;
866}
867
868/* decode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800869static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welteb8a18b52009-06-10 12:08:54 +0800870 const u_int8_t *lv)
871{
872 u_int8_t in_len = lv[0];
873
874 if (in_len < 2)
875 return -EINVAL;
876
Harald Welte03740842009-06-10 23:11:52 +0800877 progress->coding = (lv[1] & 0x60) >> 5;
878 progress->location = lv[1] & 0x0f;
879 progress->descr = lv[2] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800880
881 return 0;
882}
883
884/* encode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800885static int encode_progress(struct msgb *msg, int lv_only,
886 const struct gsm_mncc_progress *p)
Harald Welteb8a18b52009-06-10 12:08:54 +0800887{
888 u_int8_t lv[3];
889
890 lv[0] = 2;
Harald Welte03740842009-06-10 23:11:52 +0800891 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
892 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welteb8a18b52009-06-10 12:08:54 +0800893 if (lv_only)
894 msgb_lv_put(msg, lv[0], lv+1);
895 else
896 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
897
898 return 0;
899}
900
901/* decode 'user-user' */
Harald Welte03740842009-06-10 23:11:52 +0800902static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welteb8a18b52009-06-10 12:08:54 +0800903 const u_int8_t *lv)
904{
905 u_int8_t in_len = lv[0];
Harald Welte03740842009-06-10 23:11:52 +0800906 char *info = uu->info;
907 int info_len = sizeof(uu->info);
Harald Welteb8a18b52009-06-10 12:08:54 +0800908 int i;
909
910 if (in_len < 1)
911 return -EINVAL;
912
Harald Welte03740842009-06-10 23:11:52 +0800913 uu->proto = lv[1];
Harald Welteb8a18b52009-06-10 12:08:54 +0800914
915 for (i = 2; i <= in_len; i++) {
916 info_len--;
917 if (info_len <= 1)
918 break;
919 *info++ = lv[i];
920 }
921 if (info_len >= 1)
922 *info++ = '\0';
923
924 return 0;
925}
926
927/* encode 'useruser' */
Harald Welte03740842009-06-10 23:11:52 +0800928static int encode_useruser(struct msgb *msg, int lv_only,
929 const struct gsm_mncc_useruser *uu)
Harald Welteb8a18b52009-06-10 12:08:54 +0800930{
931 u_int8_t lv[GSM_MAX_USERUSER + 2];
932
Harald Welte03740842009-06-10 23:11:52 +0800933 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welteb8a18b52009-06-10 12:08:54 +0800934 return -EINVAL;
935
Harald Welte03740842009-06-10 23:11:52 +0800936 lv[0] = 1 + strlen(uu->info);
937 lv[1] = uu->proto;
938 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welteb8a18b52009-06-10 12:08:54 +0800939 if (lv_only)
940 msgb_lv_put(msg, lv[0], lv+1);
941 else
942 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
943
944 return 0;
945}
946
947/* decode 'ss version' */
Harald Welte03740842009-06-10 23:11:52 +0800948static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welteb8a18b52009-06-10 12:08:54 +0800949 const u_int8_t *lv)
950{
951 u_int8_t in_len = lv[0];
952
Harald Welte03740842009-06-10 23:11:52 +0800953 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800954 return -EINVAL;
955
Harald Welte03740842009-06-10 23:11:52 +0800956 memcpy(ssv->info, lv + 1, in_len);
957 ssv->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800958
959 return 0;
960}
961
962/* encode 'more data' */
963static int encode_more(struct msgb *msg)
964{
965 u_int8_t *ie;
966
967 ie = msgb_put(msg, 1);
968 ie[0] = GSM48_IE_MORE_DATA;
969
970 return 0;
971}
972
Harald Welte59b04682009-06-10 05:40:52 +0800973struct msgb *gsm48_msgb_alloc(void)
974{
Harald Welte9cfc9352009-06-26 19:39:35 +0200975 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
976 "GSM 04.08");
Harald Welte59b04682009-06-10 05:40:52 +0800977}
978
Harald Welte36fe2e82009-07-23 21:13:03 +0200979int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800980{
Harald Welte36fe2e82009-07-23 21:13:03 +0200981 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
982
983 /* if we get passed a transaction reference, do some common
984 * work that the caller no longer has to do */
985 if (trans) {
Harald Welte4861c822009-07-23 21:21:14 +0200986 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte36fe2e82009-07-23 21:13:03 +0200987 msg->lchan = trans->lchan;
988 }
989
Harald Welte59b04682009-06-10 05:40:52 +0800990 if (msg->lchan) {
991 msg->trx = msg->lchan->ts->trx;
992
Harald Welte03740842009-06-10 23:11:52 +0800993 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
994 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
995 "Sending '%s' to MS.\n", msg->trx->bts->nr,
996 msg->trx->nr, msg->lchan->ts->nr,
997 gh->proto_discr & 0xf0,
998 cc_msg_names[gh->msg_type & 0x3f]);
999 else
1000 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1001 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1002 msg->trx->nr, msg->lchan->ts->nr,
1003 gh->proto_discr, gh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001004 }
1005
1006 msg->l3h = msg->data;
1007
1008 return rsl_data_request(msg, 0);
1009}
1010
Harald Welte59b04682009-06-10 05:40:52 +08001011/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
1012int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
1013{
1014 struct msgb *msg = gsm48_msgb_alloc();
1015 struct gsm48_hdr *gh;
1016
1017 msg->lchan = lchan;
1018
1019 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1020 gh->proto_discr = GSM48_PDISC_MM;
1021 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
1022 gh->data[0] = cause;
1023
1024 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1025
Harald Welte36fe2e82009-07-23 21:13:03 +02001026 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001027}
1028
1029/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
1030int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
1031{
1032 struct gsm_bts *bts = lchan->ts->trx->bts;
1033 struct msgb *msg = gsm48_msgb_alloc();
1034 struct gsm48_hdr *gh;
1035 struct gsm48_loc_area_id *lai;
1036 u_int8_t *mid;
1037 int ret;
1038
1039 msg->lchan = lchan;
1040
1041 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1042 gh->proto_discr = GSM48_PDISC_MM;
1043 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1044
1045 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
1046 gsm0408_generate_lai(lai, bts->network->country_code,
1047 bts->network->network_code, bts->location_area_code);
1048
1049 mid = msgb_put(msg, MID_TMSI_LEN);
1050 generate_mid_from_tmsi(mid, tmsi);
1051
1052 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1053
Harald Welte36fe2e82009-07-23 21:13:03 +02001054 ret = gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001055
1056 ret = gsm48_tx_mm_info(lchan);
1057
1058 return ret;
1059}
1060
1061static char bcd2char(u_int8_t bcd)
1062{
1063 if (bcd < 0xa)
1064 return '0' + bcd;
1065 else
1066 return 'A' + (bcd - 0xa);
1067}
1068
1069/* Convert Mobile Identity (10.5.1.4) to string */
1070static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1071{
1072 int i;
1073 u_int8_t mi_type;
1074 char *str_cur = string;
1075 u_int32_t tmsi;
1076
1077 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1078
1079 switch (mi_type) {
1080 case GSM_MI_TYPE_NONE:
1081 break;
1082 case GSM_MI_TYPE_TMSI:
1083 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1084 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1085 memcpy(&tmsi, &mi[1], 4);
1086 tmsi = ntohl(tmsi);
1087 return snprintf(string, str_len, "%u", tmsi);
1088 }
1089 break;
1090 case GSM_MI_TYPE_IMSI:
1091 case GSM_MI_TYPE_IMEI:
1092 case GSM_MI_TYPE_IMEISV:
1093 *str_cur++ = bcd2char(mi[0] >> 4);
1094
1095 for (i = 1; i < mi_len; i++) {
1096 if (str_cur + 2 >= string + str_len)
1097 return str_cur - string;
1098 *str_cur++ = bcd2char(mi[i] & 0xf);
1099 /* skip last nibble in last input byte when GSM_EVEN */
1100 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1101 *str_cur++ = bcd2char(mi[i] >> 4);
1102 }
1103 break;
1104 default:
1105 break;
1106 }
1107 *str_cur++ = '\0';
1108
1109 return str_cur - string;
1110}
1111
1112/* Transmit Chapter 9.2.10 Identity Request */
1113static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1114{
1115 struct msgb *msg = gsm48_msgb_alloc();
1116 struct gsm48_hdr *gh;
1117
1118 msg->lchan = lchan;
1119
1120 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1121 gh->proto_discr = GSM48_PDISC_MM;
1122 gh->msg_type = GSM48_MT_MM_ID_REQ;
1123 gh->data[0] = id_type;
1124
Harald Welte36fe2e82009-07-23 21:13:03 +02001125 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001126}
1127
1128#define MI_SIZE 32
1129
1130/* Parse Chapter 9.2.11 Identity Response */
1131static int mm_rx_id_resp(struct msgb *msg)
1132{
1133 struct gsm48_hdr *gh = msgb_l3(msg);
1134 struct gsm_lchan *lchan = msg->lchan;
Harald Welteaae7a522009-07-23 19:21:02 +02001135 struct gsm_bts *bts = lchan->ts->trx->bts;
1136 struct gsm_network *net = bts->network;
Harald Welte59b04682009-06-10 05:40:52 +08001137 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1138 char mi_string[MI_SIZE];
1139
1140 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
1141 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
1142 mi_type, mi_string);
1143
Harald Welte59b04682009-06-10 05:40:52 +08001144 switch (mi_type) {
1145 case GSM_MI_TYPE_IMSI:
1146 if (!lchan->subscr)
Harald Welteaae7a522009-07-23 19:21:02 +02001147 lchan->subscr = db_create_subscriber(net, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001148 if (lchan->loc_operation)
1149 lchan->loc_operation->waiting_for_imsi = 0;
1150 break;
1151 case GSM_MI_TYPE_IMEI:
1152 case GSM_MI_TYPE_IMEISV:
1153 /* update subscribe <-> IMEI mapping */
1154 if (lchan->subscr)
1155 db_subscriber_assoc_imei(lchan->subscr, mi_string);
1156 if (lchan->loc_operation)
1157 lchan->loc_operation->waiting_for_imei = 0;
1158 break;
1159 }
1160
1161 /* Check if we can let the mobile station enter */
1162 return gsm0408_authorize(lchan, msg);
1163}
1164
1165
1166static void loc_upd_rej_cb(void *data)
1167{
1168 struct gsm_lchan *lchan = data;
1169
1170 release_loc_updating_req(lchan);
1171 gsm0408_loc_upd_rej(lchan, reject_cause);
1172 lchan_auto_release(lchan);
1173}
1174
1175static void schedule_reject(struct gsm_lchan *lchan)
1176{
1177 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1178 lchan->loc_operation->updating_timer.data = lchan;
1179 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
1180}
1181
1182static const char *lupd_name(u_int8_t type)
1183{
1184 switch (type) {
1185 case GSM48_LUPD_NORMAL:
1186 return "NORMAL";
1187 case GSM48_LUPD_PERIODIC:
1188 return "PEROIDOC";
1189 case GSM48_LUPD_IMSI_ATT:
1190 return "IMSI ATTACH";
1191 default:
1192 return "UNKNOWN";
1193 }
1194}
1195
1196#define MI_SIZE 32
1197/* Chapter 9.2.15: Receive Location Updating Request */
1198static int mm_rx_loc_upd_req(struct msgb *msg)
1199{
1200 struct gsm48_hdr *gh = msgb_l3(msg);
1201 struct gsm48_loc_upd_req *lu;
Harald Welte03740842009-06-10 23:11:52 +08001202 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001203 struct gsm_lchan *lchan = msg->lchan;
Harald Welteaae7a522009-07-23 19:21:02 +02001204 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001205 u_int8_t mi_type;
1206 char mi_string[MI_SIZE];
1207 int rc;
1208
1209 lu = (struct gsm48_loc_upd_req *) gh->data;
1210
1211 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
1212
1213 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1214
Harald Welte79639662009-06-27 02:58:43 +02001215 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte59b04682009-06-10 05:40:52 +08001216 lupd_name(lu->type));
1217
1218 /*
1219 * Pseudo Spoof detection: Just drop a second/concurrent
1220 * location updating request.
1221 */
1222 if (lchan->loc_operation) {
Harald Welte79639662009-06-27 02:58:43 +02001223 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Harald Welte59b04682009-06-10 05:40:52 +08001224 lchan->loc_operation);
1225 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1226 return 0;
1227 }
1228
1229 allocate_loc_updating_req(lchan);
1230
1231 switch (mi_type) {
1232 case GSM_MI_TYPE_IMSI:
Harald Welte79639662009-06-27 02:58:43 +02001233 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001234 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001235 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1236 lchan->loc_operation->waiting_for_imei = 1;
1237
1238 /* look up subscriber based on IMSI */
Harald Welteaae7a522009-07-23 19:21:02 +02001239 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001240 break;
1241 case GSM_MI_TYPE_TMSI:
Harald Welte79639662009-06-27 02:58:43 +02001242 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001243 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001244 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1245 lchan->loc_operation->waiting_for_imei = 1;
1246
1247 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteaae7a522009-07-23 19:21:02 +02001248 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001249 if (!subscr) {
1250 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte59b04682009-06-10 05:40:52 +08001251 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
1252 lchan->loc_operation->waiting_for_imsi = 1;
1253 }
1254 break;
1255 case GSM_MI_TYPE_IMEI:
1256 case GSM_MI_TYPE_IMEISV:
1257 /* no sim card... FIXME: what to do ? */
Harald Welte79639662009-06-27 02:58:43 +02001258 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001259 break;
1260 default:
Harald Welte79639662009-06-27 02:58:43 +02001261 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001262 break;
1263 }
1264
Harald Welteccd69362009-07-04 10:18:00 +02001265 /* schedule the reject timer */
1266 schedule_reject(lchan);
1267
Harald Welte03740842009-06-10 23:11:52 +08001268 if (!subscr) {
Harald Welte79639662009-06-27 02:58:43 +02001269 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte03740842009-06-10 23:11:52 +08001270 /* FIXME: request id? close channel? */
1271 return -EINVAL;
1272 }
1273
Harald Welte59b04682009-06-10 05:40:52 +08001274 lchan->subscr = subscr;
1275
Harald Welteccd69362009-07-04 10:18:00 +02001276 /* check if we can let the subscriber into our network immediately
1277 * or if we need to wait for identity responses. */
Harald Welte59b04682009-06-10 05:40:52 +08001278 return gsm0408_authorize(lchan, msg);
1279}
1280
Harald Welteca745e22009-07-29 12:10:35 +02001281/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte59b04682009-06-10 05:40:52 +08001282int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1283{
1284 struct msgb *msg = gsm48_msgb_alloc();
1285 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1286 struct gsm48_chan_mode_modify *cmm =
1287 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
1288 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
1289
1290 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
1291
1292 lchan->tch_mode = mode;
1293 msg->lchan = lchan;
1294 gh->proto_discr = GSM48_PDISC_RR;
1295 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1296
1297 /* fill the channel information element, this code
1298 * should probably be shared with rsl_rx_chan_rqd() */
1299 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
1300 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
1301 cmm->chan_desc.h0.h = 0;
1302 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1303 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1304 cmm->mode = mode;
1305
Harald Welte36fe2e82009-07-23 21:13:03 +02001306 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001307}
1308
Harald Welte03740842009-06-10 23:11:52 +08001309#if 0
1310static u_int8_t to_bcd8(u_int8_t val)
1311{
1312 return ((val / 10) << 4) | (val % 10);
1313}
1314#endif
1315
Harald Welte59b04682009-06-10 05:40:52 +08001316/* Section 9.2.15a */
1317int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1318{
1319 struct msgb *msg = gsm48_msgb_alloc();
1320 struct gsm48_hdr *gh;
1321 struct gsm_network *net = lchan->ts->trx->bts->network;
1322 u_int8_t *ptr8;
1323 u_int16_t *ptr16;
1324 int name_len;
1325 int i;
Harald Welte03740842009-06-10 23:11:52 +08001326#if 0
1327 time_t cur_t;
1328 struct tm* cur_time;
1329 int tz15min;
1330#endif
Harald Welte59b04682009-06-10 05:40:52 +08001331
1332 msg->lchan = lchan;
1333
1334 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1335 gh->proto_discr = GSM48_PDISC_MM;
1336 gh->msg_type = GSM48_MT_MM_INFO;
1337
1338 if (net->name_long) {
1339 name_len = strlen(net->name_long);
1340 /* 10.5.3.5a */
1341 ptr8 = msgb_put(msg, 3);
1342 ptr8[0] = GSM48_IE_NAME_LONG;
1343 ptr8[1] = name_len*2 +1;
1344 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1345
1346 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1347 for (i = 0; i < name_len; i++)
1348 ptr16[i] = htons(net->name_long[i]);
1349
1350 /* FIXME: Use Cell Broadcast, not UCS-2, since
1351 * UCS-2 is only supported by later revisions of the spec */
1352 }
1353
1354 if (net->name_short) {
1355 name_len = strlen(net->name_short);
1356 /* 10.5.3.5a */
1357 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Weltef6284712009-07-19 17:51:36 +02001358 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Welte59b04682009-06-10 05:40:52 +08001359 ptr8[1] = name_len*2 + 1;
1360 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1361
1362 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1363 for (i = 0; i < name_len; i++)
1364 ptr16[i] = htons(net->name_short[i]);
1365 }
1366
1367#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001368 /* Section 10.5.3.9 */
1369 cur_t = time(NULL);
Harald Welte03740842009-06-10 23:11:52 +08001370 cur_time = gmtime(&cur_t);
Harald Welte59b04682009-06-10 05:40:52 +08001371 ptr8 = msgb_put(msg, 8);
1372 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1373 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1374 ptr8[2] = to_bcd8(cur_time->tm_mon);
1375 ptr8[3] = to_bcd8(cur_time->tm_mday);
1376 ptr8[4] = to_bcd8(cur_time->tm_hour);
1377 ptr8[5] = to_bcd8(cur_time->tm_min);
1378 ptr8[6] = to_bcd8(cur_time->tm_sec);
1379 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1380 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte03740842009-06-10 23:11:52 +08001381 ptr8[7] = to_bcd8(tz15min);
Harald Welte59b04682009-06-10 05:40:52 +08001382 if (tz15min < 0)
Harald Welte03740842009-06-10 23:11:52 +08001383 ptr8[7] |= 0x80;
Harald Welte59b04682009-06-10 05:40:52 +08001384#endif
1385
Harald Welte36fe2e82009-07-23 21:13:03 +02001386 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001387}
1388
1389static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1390{
1391 DEBUGP(DMM, "-> CM SERVICE ACK\n");
1392 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
1393}
1394
1395/* 9.2.6 CM service reject */
1396static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1397 enum gsm48_reject_value value)
1398{
1399 struct msgb *msg = gsm48_msgb_alloc();
1400 struct gsm48_hdr *gh;
1401
1402 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1403
1404 msg->lchan = lchan;
1405 use_lchan(lchan);
1406
1407 gh->proto_discr = GSM48_PDISC_MM;
1408 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1409 gh->data[0] = value;
1410 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1411
Harald Welte36fe2e82009-07-23 21:13:03 +02001412 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001413}
1414
1415
1416/*
1417 * Handle CM Service Requests
1418 * a) Verify that the packet is long enough to contain the information
1419 * we require otherwsie reject with INCORRECT_MESSAGE
1420 * b) Try to parse the TMSI. If we do not have one reject
1421 * c) Check that we know the subscriber with the TMSI otherwise reject
1422 * with a HLR cause
1423 * d) Set the subscriber on the gsm_lchan and accept
1424 */
1425static int gsm48_rx_mm_serv_req(struct msgb *msg)
1426{
1427 u_int8_t mi_type;
1428 char mi_string[MI_SIZE];
1429
Harald Welteaae7a522009-07-23 19:21:02 +02001430 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001431 struct gsm_subscriber *subscr;
1432 struct gsm48_hdr *gh = msgb_l3(msg);
1433 struct gsm48_service_request *req =
1434 (struct gsm48_service_request *)gh->data;
1435 /* unfortunately in Phase1 the classmar2 length is variable */
1436 u_int8_t classmark2_len = gh->data[1];
1437 u_int8_t *classmark2 = gh->data+2;
1438 u_int8_t mi_len = *(classmark2 + classmark2_len);
1439 u_int8_t *mi = (classmark2 + classmark2_len + 1);
1440
1441 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
1442 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
1443 DEBUGPC(DMM, "wrong sized message\n");
1444 return gsm48_tx_mm_serv_rej(msg->lchan,
1445 GSM48_REJECT_INCORRECT_MESSAGE);
1446 }
1447
1448 if (msg->data_len < req->mi_len + 6) {
1449 DEBUGPC(DMM, "does not fit in packet\n");
1450 return gsm48_tx_mm_serv_rej(msg->lchan,
1451 GSM48_REJECT_INCORRECT_MESSAGE);
1452 }
1453
1454 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1455 if (mi_type != GSM_MI_TYPE_TMSI) {
1456 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
1457 return gsm48_tx_mm_serv_rej(msg->lchan,
1458 GSM48_REJECT_INCORRECT_MESSAGE);
1459 }
1460
1461 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1462 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
1463 req->cm_service_type, mi_type, mi_string);
1464
Harald Welteaae7a522009-07-23 19:21:02 +02001465 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001466
1467 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
1468 if (!subscr)
1469 return gsm48_tx_mm_serv_rej(msg->lchan,
1470 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1471
1472 if (!msg->lchan->subscr)
1473 msg->lchan->subscr = subscr;
1474 else if (msg->lchan->subscr != subscr) {
1475 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1476 subscr_put(subscr);
1477 }
1478
Harald Weltef6845a72009-07-05 14:08:13 +02001479 subscr->equipment.classmark2_len = classmark2_len;
1480 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1481 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001482
1483 return gsm48_tx_mm_serv_ack(msg->lchan);
1484}
1485
1486static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1487{
Harald Welteaae7a522009-07-23 19:21:02 +02001488 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001489 struct gsm48_hdr *gh = msgb_l3(msg);
1490 struct gsm48_imsi_detach_ind *idi =
1491 (struct gsm48_imsi_detach_ind *) gh->data;
1492 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1493 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001494 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001495
1496 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1497 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1498 mi_type, mi_string);
1499
1500 switch (mi_type) {
1501 case GSM_MI_TYPE_TMSI:
Harald Welteaae7a522009-07-23 19:21:02 +02001502 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001503 break;
1504 case GSM_MI_TYPE_IMSI:
Harald Welteaae7a522009-07-23 19:21:02 +02001505 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001506 break;
1507 case GSM_MI_TYPE_IMEI:
1508 case GSM_MI_TYPE_IMEISV:
1509 /* no sim card... FIXME: what to do ? */
1510 DEBUGPC(DMM, "unimplemented mobile identity type\n");
1511 break;
1512 default:
1513 DEBUGPC(DMM, "unknown mobile identity type\n");
1514 break;
1515 }
1516
1517 if (subscr) {
1518 subscr_update(subscr, msg->trx->bts,
1519 GSM_SUBSCRIBER_UPDATE_DETACHED);
1520 DEBUGP(DMM, "Subscriber: %s\n",
1521 subscr->name ? subscr->name : subscr->imsi);
1522 subscr_put(subscr);
1523 } else
1524 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1525
Harald Welte59b04682009-06-10 05:40:52 +08001526 return 0;
1527}
1528
1529static int gsm48_rx_mm_status(struct msgb *msg)
1530{
1531 struct gsm48_hdr *gh = msgb_l3(msg);
1532
1533 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1534
1535 return 0;
1536}
1537
1538/* Receive a GSM 04.08 Mobility Management (MM) message */
1539static int gsm0408_rcv_mm(struct msgb *msg)
1540{
1541 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte03740842009-06-10 23:11:52 +08001542 int rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08001543
1544 switch (gh->msg_type & 0xbf) {
1545 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Welte79639662009-06-27 02:58:43 +02001546 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte59b04682009-06-10 05:40:52 +08001547 rc = mm_rx_loc_upd_req(msg);
1548 break;
1549 case GSM48_MT_MM_ID_RESP:
1550 rc = mm_rx_id_resp(msg);
1551 break;
1552 case GSM48_MT_MM_CM_SERV_REQ:
1553 rc = gsm48_rx_mm_serv_req(msg);
1554 break;
1555 case GSM48_MT_MM_STATUS:
1556 rc = gsm48_rx_mm_status(msg);
1557 break;
1558 case GSM48_MT_MM_TMSI_REALL_COMPL:
1559 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1560 msg->lchan->subscr ?
1561 msg->lchan->subscr->imsi :
1562 "unknown subscriber");
1563 break;
1564 case GSM48_MT_MM_IMSI_DETACH_IND:
1565 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1566 break;
1567 case GSM48_MT_MM_CM_REEST_REQ:
1568 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1569 break;
1570 case GSM48_MT_MM_AUTH_RESP:
1571 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
1572 break;
1573 default:
1574 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1575 gh->msg_type);
1576 break;
1577 }
1578
1579 return rc;
1580}
1581
1582/* Receive a PAGING RESPONSE message from the MS */
1583static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1584{
Harald Welteaae7a522009-07-23 19:21:02 +02001585 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001586 struct gsm48_hdr *gh = msgb_l3(msg);
1587 u_int8_t *classmark2_lv = gh->data + 1;
1588 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1589 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
1590 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001591 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001592 struct paging_signal_data sig_data;
1593 int rc = 0;
1594
1595 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
1596 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1597 mi_type, mi_string);
1598 switch (mi_type) {
1599 case GSM_MI_TYPE_TMSI:
Harald Welteaae7a522009-07-23 19:21:02 +02001600 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001601 break;
1602 case GSM_MI_TYPE_IMSI:
Harald Welteaae7a522009-07-23 19:21:02 +02001603 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001604 break;
1605 }
1606
1607 if (!subscr) {
1608 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1609 /* FIXME: request id? close channel? */
1610 return -EINVAL;
1611 }
1612 DEBUGP(DRR, "<- Channel was requested by %s\n",
1613 subscr->name ? subscr->name : subscr->imsi);
1614
Harald Weltef6845a72009-07-05 14:08:13 +02001615 subscr->equipment.classmark2_len = *classmark2_lv;
1616 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1617 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001618
1619 if (!msg->lchan->subscr) {
1620 msg->lchan->subscr = subscr;
1621 } else if (msg->lchan->subscr != subscr) {
1622 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1623 subscr_put(subscr);
1624 return -EINVAL;
1625 } else {
1626 DEBUGP(DRR, "<- Channel already owned by us\n");
1627 subscr_put(subscr);
1628 subscr = msg->lchan->subscr;
1629 }
1630
1631 sig_data.subscr = subscr;
1632 sig_data.bts = msg->lchan->ts->trx->bts;
1633 sig_data.lchan = msg->lchan;
1634
1635 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Welte876312f2009-06-10 11:21:55 +08001636
1637 /* Stop paging on the bts we received the paging response */
Harald Welte59b04682009-06-10 05:40:52 +08001638 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
1639
1640 /* FIXME: somehow signal the completion of the PAGING to
1641 * the entity that requested the paging */
1642
1643 return rc;
1644}
1645
1646static int gsm48_rx_rr_classmark(struct msgb *msg)
1647{
1648 struct gsm48_hdr *gh = msgb_l3(msg);
1649 struct gsm_subscriber *subscr = msg->lchan->subscr;
1650 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1651 u_int8_t cm2_len, cm3_len = 0;
1652 u_int8_t *cm2, *cm3 = NULL;
1653
1654 DEBUGP(DRR, "CLASSMARK CHANGE ");
1655
1656 /* classmark 2 */
1657 cm2_len = gh->data[0];
1658 cm2 = &gh->data[1];
1659 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1660
1661 if (payload_len > cm2_len + 1) {
1662 /* we must have a classmark3 */
1663 if (gh->data[cm2_len+1] != 0x20) {
1664 DEBUGPC(DRR, "ERR CM3 TAG\n");
1665 return -EINVAL;
1666 }
1667 if (cm2_len > 3) {
1668 DEBUGPC(DRR, "CM2 too long!\n");
1669 return -EINVAL;
1670 }
1671
1672 cm3_len = gh->data[cm2_len+2];
1673 cm3 = &gh->data[cm2_len+3];
1674 if (cm3_len > 14) {
1675 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1676 return -EINVAL;
1677 }
1678 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1679 }
1680 if (subscr) {
Harald Weltef6845a72009-07-05 14:08:13 +02001681 subscr->equipment.classmark2_len = cm2_len;
1682 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Welte59b04682009-06-10 05:40:52 +08001683 if (cm3) {
Harald Weltef6845a72009-07-05 14:08:13 +02001684 subscr->equipment.classmark3_len = cm3_len;
1685 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Welte59b04682009-06-10 05:40:52 +08001686 }
Harald Weltef6845a72009-07-05 14:08:13 +02001687 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001688 }
1689
Harald Welte59b04682009-06-10 05:40:52 +08001690 return 0;
1691}
1692
1693static int gsm48_rx_rr_status(struct msgb *msg)
1694{
1695 struct gsm48_hdr *gh = msgb_l3(msg);
1696
1697 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1698 rr_cause_name(gh->data[0]));
1699
1700 return 0;
1701}
1702
1703static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1704{
1705 struct gsm48_hdr *gh = msgb_l3(msg);
1706 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1707 static struct gsm_meas_rep meas_rep;
1708
Harald Welte02993682009-06-27 02:53:10 +02001709 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Welte59b04682009-06-10 05:40:52 +08001710 parse_meas_rep(&meas_rep, gh->data, payload_len);
1711 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte02993682009-06-27 02:53:10 +02001712 DEBUGPC(DMEAS, "DTX ");
Harald Welte59b04682009-06-10 05:40:52 +08001713 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte02993682009-06-27 02:53:10 +02001714 DEBUGPC(DMEAS, "BA1 ");
Harald Welte59b04682009-06-10 05:40:52 +08001715 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte02993682009-06-27 02:53:10 +02001716 DEBUGPC(DMEAS, "NOT VALID ");
Harald Welte59b04682009-06-10 05:40:52 +08001717 else
Harald Welte02993682009-06-27 02:53:10 +02001718 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Welte59b04682009-06-10 05:40:52 +08001719 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1720 meas_rep.rxqual_sub);
1721
Harald Welte02993682009-06-27 02:53:10 +02001722 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Welte59b04682009-06-10 05:40:52 +08001723
1724 /* FIXME: put the results somwhere */
1725
1726 return 0;
1727}
1728
1729/* Receive a GSM 04.08 Radio Resource (RR) message */
1730static int gsm0408_rcv_rr(struct msgb *msg)
1731{
1732 struct gsm48_hdr *gh = msgb_l3(msg);
1733 int rc = 0;
1734
1735 switch (gh->msg_type) {
1736 case GSM48_MT_RR_CLSM_CHG:
1737 rc = gsm48_rx_rr_classmark(msg);
1738 break;
1739 case GSM48_MT_RR_GPRS_SUSP_REQ:
1740 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1741 break;
1742 case GSM48_MT_RR_PAG_RESP:
1743 rc = gsm48_rr_rx_pag_resp(msg);
1744 break;
1745 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1746 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welteca745e22009-07-29 12:10:35 +02001747 /* We've successfully modified the MS side of the channel,
1748 * now go on to modify the BTS side of the channel */
Harald Welte59b04682009-06-10 05:40:52 +08001749 rc = rsl_chan_mode_modify_req(msg->lchan);
1750 break;
1751 case GSM48_MT_RR_STATUS:
1752 rc = gsm48_rx_rr_status(msg);
1753 break;
1754 case GSM48_MT_RR_MEAS_REP:
1755 rc = gsm48_rx_rr_meas_rep(msg);
1756 break;
1757 default:
1758 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1759 gh->msg_type);
1760 break;
1761 }
1762
1763 return rc;
1764}
1765
1766/* 7.1.7 and 9.1.7 Channel release*/
1767int gsm48_send_rr_release(struct gsm_lchan *lchan)
1768{
1769 struct msgb *msg = gsm48_msgb_alloc();
1770 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1771 u_int8_t *cause;
1772
1773 msg->lchan = lchan;
1774 gh->proto_discr = GSM48_PDISC_RR;
1775 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1776
1777 cause = msgb_put(msg, 1);
1778 cause[0] = GSM48_RR_CAUSE_NORMAL;
1779
1780 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1781 lchan->nr, lchan->type);
1782
Harald Welteafe3c232009-07-19 18:36:49 +02001783 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001784 gsm48_sendmsg(msg, NULL);
Harald Welteafe3c232009-07-19 18:36:49 +02001785
1786 /* Deactivate the SACCH on the BTS side */
1787 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001788}
1789
1790/* Call Control */
1791
1792/* The entire call control code is written in accordance with Figure 7.10c
1793 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1794 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1795 * it for voice */
1796
Harald Welte03740842009-06-10 23:11:52 +08001797static void new_cc_state(struct gsm_trans *trans, int state)
1798{
1799 if (state > 31 || state < 0)
1800 return;
1801
1802 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltea54b48d2009-07-23 18:56:43 +02001803 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001804
Harald Weltea54b48d2009-07-23 18:56:43 +02001805 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001806}
1807
1808static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001809{
1810 struct msgb *msg = gsm48_msgb_alloc();
1811 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1812 u_int8_t *cause, *call_state;
1813
Harald Welte59b04682009-06-10 05:40:52 +08001814 gh->msg_type = GSM48_MT_CC_STATUS;
1815
1816 cause = msgb_put(msg, 3);
1817 cause[0] = 2;
1818 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1819 cause[2] = 0x80 | 30; /* response to status inquiry */
1820
1821 call_state = msgb_put(msg, 1);
1822 call_state[0] = 0xc0 | 0x00;
1823
Harald Welte36fe2e82009-07-23 21:13:03 +02001824 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001825}
1826
1827static int gsm48_tx_simple(struct gsm_lchan *lchan,
1828 u_int8_t pdisc, u_int8_t msg_type)
1829{
1830 struct msgb *msg = gsm48_msgb_alloc();
1831 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1832
1833 msg->lchan = lchan;
1834
1835 gh->proto_discr = pdisc;
1836 gh->msg_type = msg_type;
1837
Harald Welte36fe2e82009-07-23 21:13:03 +02001838 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001839}
1840
Harald Welte03740842009-06-10 23:11:52 +08001841static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1842{
Harald Weltea54b48d2009-07-23 18:56:43 +02001843 if (bsc_timer_pending(&trans->cc.timer)) {
1844 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1845 bsc_del_timer(&trans->cc.timer);
1846 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001847 }
1848}
1849
1850static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1851 int msg_type, struct gsm_mncc *mncc)
1852{
1853 struct msgb *msg;
1854
1855 if (trans)
1856 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02001857 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08001858 "Sending '%s' to MNCC.\n",
1859 trans->lchan->ts->trx->bts->nr,
1860 trans->lchan->ts->trx->nr,
1861 trans->lchan->ts->nr, trans->transaction_id,
1862 (trans->subscr)?(trans->subscr->extension):"-",
1863 get_mncc_name(msg_type));
1864 else
1865 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1866 "Sending '%s' to MNCC.\n",
1867 (trans->subscr)?(trans->subscr->extension):"-",
1868 get_mncc_name(msg_type));
1869 else
1870 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1871 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1872
1873 mncc->msg_type = msg_type;
1874
Harald Welte9cfc9352009-06-26 19:39:35 +02001875 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08001876 if (!msg)
1877 return -ENOMEM;
1878 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1879 msgb_enqueue(&net->upqueue, msg);
1880
1881 return 0;
1882}
1883
1884int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1885 u_int32_t callref, int location, int value)
1886{
1887 struct gsm_mncc rel;
1888
Harald Weltecb0595f2009-06-12 01:54:08 +08001889 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08001890 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001891 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08001892 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1893}
1894
Harald Weltea54b48d2009-07-23 18:56:43 +02001895/* Call Control Specific transaction release.
1896 * gets called by trans_free, DO NOT CALL YOURSELF! */
1897void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08001898{
Harald Welte03740842009-06-10 23:11:52 +08001899 gsm48_stop_cc_timer(trans);
1900
1901 /* send release to L4, if callref still exists */
1902 if (trans->callref) {
1903 /* Ressource unavailable */
Harald Welte8dd09d62009-07-23 19:06:52 +02001904 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001905 GSM48_CAUSE_LOC_PRN_S_LU,
1906 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08001907 }
Harald Weltea54b48d2009-07-23 18:56:43 +02001908 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08001909 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltea54b48d2009-07-23 18:56:43 +02001910 if (trans->lchan)
1911 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08001912}
1913
1914static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1915
Harald Welte59b04682009-06-10 05:40:52 +08001916/* call-back from paging the B-end of the connection */
1917static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
1918 struct msgb *msg, void *_lchan, void *param)
1919{
1920 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08001921 struct gsm_subscriber *subscr = param;
1922 struct gsm_trans *transt, *tmp;
1923 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02001924
Harald Welte59b04682009-06-10 05:40:52 +08001925 if (hooknum != GSM_HOOK_RR_PAGING)
1926 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08001927
1928 if (!subscr)
1929 return -EINVAL;
1930 net = subscr->net;
1931 if (!net) {
1932 DEBUGP(DCC, "Error Network not set!\n");
1933 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001934 }
1935
Harald Welte03740842009-06-10 23:11:52 +08001936 /* check all tranactions (without lchan) for subscriber */
1937 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1938 if (transt->subscr != subscr || transt->lchan)
1939 continue;
1940 switch (event) {
1941 case GSM_PAGING_SUCCEEDED:
1942 if (!lchan) // paranoid
1943 break;
1944 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1945 subscr->extension);
1946 /* Assign lchan */
1947 if (!transt->lchan) {
1948 transt->lchan = lchan;
1949 use_lchan(lchan);
1950 }
1951 /* send SETUP request to called party */
Harald Weltea54b48d2009-07-23 18:56:43 +02001952 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08001953 break;
1954 case GSM_PAGING_EXPIRED:
1955 DEBUGP(DCC, "Paging subscr %s expired!\n",
1956 subscr->extension);
1957 /* Temporarily out of order */
Harald Welte8dd09d62009-07-23 19:06:52 +02001958 mncc_release_ind(transt->subscr->net, transt,
1959 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001960 GSM48_CAUSE_LOC_PRN_S_LU,
1961 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08001962 transt->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02001963 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08001964 break;
1965 }
1966 }
Harald Welte59b04682009-06-10 05:40:52 +08001967 return 0;
1968}
1969
Harald Welte3c062072009-07-28 18:25:29 +02001970/* some other part of the code sends us a signal */
1971static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
1972 void *handler_data, void *signal_data)
1973{
1974 struct gsm_lchan *lchan = signal_data;
1975 struct gsm_bts_trx_ts *ts;
1976 int rc;
1977
1978 if (subsys != SS_ABISIP)
1979 return 0;
1980
1981 /* in case we use direct BTS-to-BTS RTP */
1982 if (ipacc_rtp_direct)
1983 return 0;
1984
1985 ts = lchan->ts;
1986
1987 switch (signal) {
1988 case S_ABISIP_BIND_ACK:
1989 /* the BTS has successfully bound a TCH to a local ip/port,
1990 * which means we can connect our UDP socket to it */
1991 if (ts->abis_ip.rtp_socket) {
1992 rtp_socket_free(ts->abis_ip.rtp_socket);
1993 ts->abis_ip.rtp_socket = NULL;
1994 }
1995
1996 ts->abis_ip.rtp_socket = rtp_socket_create();
1997 if (!ts->abis_ip.rtp_socket)
1998 goto out_err;
1999
2000 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2001 ts->abis_ip.bound_ip,
2002 ts->abis_ip.bound_port);
2003 if (rc < 0)
2004 goto out_err;
2005 break;
2006 case S_ABISIP_DISC_IND:
2007 /* the BTS tells us a RTP stream has been disconnected */
2008 if (ts->abis_ip.rtp_socket) {
2009 rtp_socket_free(ts->abis_ip.rtp_socket);
2010 ts->abis_ip.rtp_socket = NULL;
2011 }
2012 break;
2013 }
2014
2015 return 0;
2016out_err:
2017 /* FIXME: do something */
2018 return 0;
2019}
2020
2021/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2022static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2023{
2024 struct gsm_bts_trx_ts *ts = lchan->ts;
2025 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2026 int rc;
2027
2028 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2029 ntohs(rs->rtp.sin_local.sin_port),
2030 ts->abis_ip.conn_id,
2031 /* FIXME: use RTP payload of bound socket, not BTS*/
2032 ts->abis_ip.rtp_payload2);
2033
2034 return rc;
2035}
2036
Harald Welte59b04682009-06-10 05:40:52 +08002037/* map two ipaccess RTP streams onto each other */
2038static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2039{
2040 struct gsm_bts *bts = lchan->ts->trx->bts;
2041 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2042 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002043 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002044
2045 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2046 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2047 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2048
2049 if (bts->type != remote_bts->type) {
2050 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2051 return -EINVAL;
2052 }
2053
2054 switch (bts->type) {
2055 case GSM_BTS_TYPE_NANOBTS_900:
2056 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002057 if (!ipacc_rtp_direct) {
2058 /* connect the TCH's to our RTP proxy */
2059 rc = ipacc_connect_proxy_bind(lchan);
2060 if (rc < 0)
2061 return rc;
2062 rc = ipacc_connect_proxy_bind(remote_lchan);
2063
2064 /* connect them with each other */
2065 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2066 remote_lchan->ts->abis_ip.rtp_socket);
2067 } else {
2068 /* directly connect TCH RTP streams to each other */
2069 ts = remote_lchan->ts;
2070 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2071 ts->abis_ip.bound_port,
2072 lchan->ts->abis_ip.conn_id,
2073 ts->abis_ip.rtp_payload2);
2074 if (rc < 0)
2075 return rc;
2076 ts = lchan->ts;
2077 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2078 ts->abis_ip.bound_port,
2079 remote_lchan->ts->abis_ip.conn_id,
2080 ts->abis_ip.rtp_payload2);
2081 }
Harald Welte59b04682009-06-10 05:40:52 +08002082 break;
2083 case GSM_BTS_TYPE_BS11:
2084 trau_mux_map_lchan(lchan, remote_lchan);
2085 break;
2086 default:
2087 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002088 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002089 break;
2090 }
2091
2092 return 0;
2093}
2094
Harald Welte03740842009-06-10 23:11:52 +08002095/* bridge channels of two transactions */
2096static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002097{
Harald Weltea54b48d2009-07-23 18:56:43 +02002098 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2099 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002100
Harald Welte03740842009-06-10 23:11:52 +08002101 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002102 return -EIO;
2103
Harald Welte03740842009-06-10 23:11:52 +08002104 if (!trans1->lchan || !trans2->lchan)
2105 return -EIO;
2106
2107 /* through-connect channel */
2108 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002109}
2110
Harald Welte03740842009-06-10 23:11:52 +08002111/* enable receive of channels to upqueue */
2112static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2113{
2114 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002115
Harald Welte03740842009-06-10 23:11:52 +08002116 /* Find callref */
Harald Weltea54b48d2009-07-23 18:56:43 +02002117 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002118 if (!trans)
2119 return -EIO;
2120 if (!trans->lchan)
2121 return 0;
2122
2123 // todo IPACCESS
2124 if (enable)
2125 return trau_recv_lchan(trans->lchan, data->callref);
2126 return trau_mux_unmap(NULL, data->callref);
2127}
2128
2129/* send a frame to channel */
2130static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2131{
2132 struct gsm_trans *trans;
2133
2134 /* Find callref */
Harald Weltea54b48d2009-07-23 18:56:43 +02002135 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002136 if (!trans)
2137 return -EIO;
2138 if (!trans->lchan)
2139 return 0;
2140 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2141 trans->lchan->type != GSM_LCHAN_TCH_H)
2142 return 0;
2143
2144 // todo IPACCESS
2145 return trau_send_lchan(trans->lchan,
2146 (struct decoded_trau_frame *)frame->data);
2147}
2148
2149
2150static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2151{
2152 DEBUGP(DCC, "-> STATUS ENQ\n");
2153 return gsm48_cc_tx_status(trans, msg);
2154}
2155
2156static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2157static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2158
2159static void gsm48_cc_timeout(void *arg)
2160{
2161 struct gsm_trans *trans = arg;
2162 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002163 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2164 int mo_location = GSM48_CAUSE_LOC_USER;
2165 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2166 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002167 struct gsm_mncc mo_rel, l4_rel;
2168
2169 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2170 mo_rel.callref = trans->callref;
2171 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2172 l4_rel.callref = trans->callref;
2173
Harald Weltea54b48d2009-07-23 18:56:43 +02002174 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002175 case 0x303:
2176 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002177 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002178 break;
2179 case 0x310:
2180 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002181 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002182 break;
2183 case 0x313:
2184 disconnect = 1;
2185 /* unknown, did not find it in the specs */
2186 break;
2187 case 0x301:
2188 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002189 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002190 break;
2191 case 0x308:
Harald Weltea54b48d2009-07-23 18:56:43 +02002192 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002193 /* restart T308 a second time */
Harald Weltea54b48d2009-07-23 18:56:43 +02002194 gsm48_cc_tx_release(trans, &trans->cc.msg);
2195 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002196 break; /* stay in release state */
2197 }
Harald Weltea54b48d2009-07-23 18:56:43 +02002198 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002199 return;
2200// release = 1;
2201// l4_cause = 14;
2202// break;
2203 case 0x306:
2204 release = 1;
Harald Weltea54b48d2009-07-23 18:56:43 +02002205 mo_cause = trans->cc.msg.cause.value;
2206 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002207 break;
2208 case 0x323:
2209 disconnect = 1;
2210 break;
2211 default:
2212 release = 1;
2213 }
2214
2215 if (release && trans->callref) {
2216 /* process release towards layer 4 */
Harald Welte8dd09d62009-07-23 19:06:52 +02002217 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002218 l4_location, l4_cause);
2219 trans->callref = 0;
2220 }
2221
2222 if (disconnect && trans->callref) {
2223 /* process disconnect towards layer 4 */
2224 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte8dd09d62009-07-23 19:06:52 +02002225 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002226 }
2227
2228 /* process disconnect towards mobile station */
2229 if (disconnect || release) {
2230 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltea54b48d2009-07-23 18:56:43 +02002231 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2232 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2233 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002234 mo_rel.cause.diag_len = 3;
2235
2236 if (disconnect)
2237 gsm48_cc_tx_disconnect(trans, &mo_rel);
2238 if (release)
2239 gsm48_cc_tx_release(trans, &mo_rel);
2240 }
2241
2242}
2243
2244static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2245 int sec, int micro)
2246{
2247 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltea54b48d2009-07-23 18:56:43 +02002248 trans->cc.timer.cb = gsm48_cc_timeout;
2249 trans->cc.timer.data = trans;
2250 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2251 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002252}
2253
2254static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2255{
2256 struct gsm48_hdr *gh = msgb_l3(msg);
2257 u_int8_t msg_type = gh->msg_type & 0xbf;
2258 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2259 struct tlv_parsed tp;
2260 struct gsm_mncc setup;
2261
2262 memset(&setup, 0, sizeof(struct gsm_mncc));
2263 setup.callref = trans->callref;
2264 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2265 /* emergency setup is identified by msg_type */
2266 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2267 setup.emergency = 1;
2268
2269 /* use subscriber as calling party number */
2270 if (trans->subscr) {
2271 setup.fields |= MNCC_F_CALLING;
2272 strncpy(setup.calling.number, trans->subscr->extension,
2273 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002274 strncpy(setup.imsi, trans->subscr->imsi,
2275 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002276 }
2277 /* bearer capability */
2278 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2279 setup.fields |= MNCC_F_BEARER_CAP;
2280 decode_bearer_cap(&setup.bearer_cap,
2281 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2282 }
2283 /* facility */
2284 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2285 setup.fields |= MNCC_F_FACILITY;
2286 decode_facility(&setup.facility,
2287 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2288 }
2289 /* called party bcd number */
2290 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2291 setup.fields |= MNCC_F_CALLED;
2292 decode_called(&setup.called,
2293 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2294 }
2295 /* user-user */
2296 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2297 setup.fields |= MNCC_F_USERUSER;
2298 decode_useruser(&setup.useruser,
2299 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2300 }
2301 /* ss-version */
2302 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2303 setup.fields |= MNCC_F_SSVERSION;
2304 decode_ssversion(&setup.ssversion,
2305 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2306 }
2307 /* CLIR suppression */
2308 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2309 setup.clir.sup = 1;
2310 /* CLIR invocation */
2311 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2312 setup.clir.inv = 1;
2313 /* cc cap */
2314 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2315 setup.fields |= MNCC_F_CCCAP;
2316 decode_cccap(&setup.cccap,
2317 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2318 }
2319
Harald Welte03740842009-06-10 23:11:52 +08002320 new_cc_state(trans, GSM_CSTATE_INITIATED);
2321
2322 /* indicate setup to MNCC */
Harald Welte8dd09d62009-07-23 19:06:52 +02002323 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002324
Harald Welteca745e22009-07-29 12:10:35 +02002325 /* MNCC code will modify the channel asynchronously, we should
2326 * ipaccess-bind only after the modification has been made to the
2327 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002328 return 0;
2329}
2330
2331static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002332{
2333 struct msgb *msg = gsm48_msgb_alloc();
2334 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002335 struct gsm_mncc *setup = arg;
Harald Welte419c0472009-07-23 21:36:44 +02002336 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002337
2338 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2339
Harald Welte03740842009-06-10 23:11:52 +08002340 /* transaction id must not be assigned */
2341 if (trans->transaction_id != 0xff) { /* unasssigned */
2342 DEBUGP(DCC, "TX Setup with assigned transaction. "
2343 "This is not allowed!\n");
2344 /* Temporarily out of order */
Harald Welte8dd09d62009-07-23 19:06:52 +02002345 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002346 GSM48_CAUSE_LOC_PRN_S_LU,
2347 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002348 trans->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02002349 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002350 return rc;
2351 }
2352
2353 /* Get free transaction_id */
Harald Welte419c0472009-07-23 21:36:44 +02002354 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2355 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002356 /* no free transaction ID */
Harald Welte8dd09d62009-07-23 19:06:52 +02002357 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002358 GSM48_CAUSE_LOC_PRN_S_LU,
2359 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002360 trans->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02002361 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002362 return rc;
2363 }
Harald Welte419c0472009-07-23 21:36:44 +02002364 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002365
Harald Welte59b04682009-06-10 05:40:52 +08002366 gh->msg_type = GSM48_MT_CC_SETUP;
2367
Harald Welte03740842009-06-10 23:11:52 +08002368 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002369
Harald Welte03740842009-06-10 23:11:52 +08002370 /* bearer capability */
2371 if (setup->fields & MNCC_F_BEARER_CAP)
2372 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2373 /* facility */
2374 if (setup->fields & MNCC_F_FACILITY)
2375 encode_facility(msg, 0, &setup->facility);
2376 /* progress */
2377 if (setup->fields & MNCC_F_PROGRESS)
2378 encode_progress(msg, 0, &setup->progress);
2379 /* calling party BCD number */
2380 if (setup->fields & MNCC_F_CALLING)
2381 encode_calling(msg, &setup->calling);
2382 /* called party BCD number */
2383 if (setup->fields & MNCC_F_CALLED)
2384 encode_called(msg, &setup->called);
2385 /* user-user */
2386 if (setup->fields & MNCC_F_USERUSER)
2387 encode_useruser(msg, 0, &setup->useruser);
2388 /* redirecting party BCD number */
2389 if (setup->fields & MNCC_F_REDIRECTING)
2390 encode_redirecting(msg, &setup->redirecting);
2391 /* signal */
2392 if (setup->fields & MNCC_F_SIGNAL)
2393 encode_signal(msg, setup->signal);
2394
2395 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002396
Harald Welte36fe2e82009-07-23 21:13:03 +02002397 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002398}
2399
Harald Welte03740842009-06-10 23:11:52 +08002400static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2401{
2402 struct gsm48_hdr *gh = msgb_l3(msg);
2403 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2404 struct tlv_parsed tp;
2405 struct gsm_mncc call_conf;
2406
2407 gsm48_stop_cc_timer(trans);
2408 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2409
2410 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2411 call_conf.callref = trans->callref;
2412 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2413#if 0
2414 /* repeat */
2415 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2416 call_conf.repeat = 1;
2417 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2418 call_conf.repeat = 2;
2419#endif
2420 /* bearer capability */
2421 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2422 call_conf.fields |= MNCC_F_BEARER_CAP;
2423 decode_bearer_cap(&call_conf.bearer_cap,
2424 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2425 }
2426 /* cause */
2427 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2428 call_conf.fields |= MNCC_F_CAUSE;
2429 decode_cause(&call_conf.cause,
2430 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2431 }
2432 /* cc cap */
2433 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2434 call_conf.fields |= MNCC_F_CCCAP;
2435 decode_cccap(&call_conf.cccap,
2436 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2437 }
2438
2439 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2440
Harald Welte8dd09d62009-07-23 19:06:52 +02002441 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2442 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002443}
2444
2445static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2446{
2447 struct gsm_mncc *proceeding = arg;
2448 struct msgb *msg = gsm48_msgb_alloc();
2449 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2450
Harald Welte03740842009-06-10 23:11:52 +08002451 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2452
2453 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2454
2455 /* bearer capability */
2456 if (proceeding->fields & MNCC_F_BEARER_CAP)
2457 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2458 /* facility */
2459 if (proceeding->fields & MNCC_F_FACILITY)
2460 encode_facility(msg, 0, &proceeding->facility);
2461 /* progress */
2462 if (proceeding->fields & MNCC_F_PROGRESS)
2463 encode_progress(msg, 0, &proceeding->progress);
2464
Harald Welte36fe2e82009-07-23 21:13:03 +02002465 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002466}
2467
2468static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2469{
2470 struct gsm48_hdr *gh = msgb_l3(msg);
2471 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2472 struct tlv_parsed tp;
2473 struct gsm_mncc alerting;
2474
2475 gsm48_stop_cc_timer(trans);
2476 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2477
2478 memset(&alerting, 0, sizeof(struct gsm_mncc));
2479 alerting.callref = trans->callref;
2480 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2481 /* facility */
2482 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2483 alerting.fields |= MNCC_F_FACILITY;
2484 decode_facility(&alerting.facility,
2485 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2486 }
2487
2488 /* progress */
2489 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2490 alerting.fields |= MNCC_F_PROGRESS;
2491 decode_progress(&alerting.progress,
2492 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2493 }
2494 /* ss-version */
2495 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2496 alerting.fields |= MNCC_F_SSVERSION;
2497 decode_ssversion(&alerting.ssversion,
2498 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2499 }
2500
2501 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2502
Harald Welte8dd09d62009-07-23 19:06:52 +02002503 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2504 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002505}
2506
2507static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2508{
2509 struct gsm_mncc *alerting = arg;
2510 struct msgb *msg = gsm48_msgb_alloc();
2511 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2512
Harald Welte03740842009-06-10 23:11:52 +08002513 gh->msg_type = GSM48_MT_CC_ALERTING;
2514
2515 /* facility */
2516 if (alerting->fields & MNCC_F_FACILITY)
2517 encode_facility(msg, 0, &alerting->facility);
2518 /* progress */
2519 if (alerting->fields & MNCC_F_PROGRESS)
2520 encode_progress(msg, 0, &alerting->progress);
2521 /* user-user */
2522 if (alerting->fields & MNCC_F_USERUSER)
2523 encode_useruser(msg, 0, &alerting->useruser);
2524
2525 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2526
Harald Welte36fe2e82009-07-23 21:13:03 +02002527 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002528}
2529
2530static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2531{
2532 struct gsm_mncc *progress = arg;
2533 struct msgb *msg = gsm48_msgb_alloc();
2534 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2535
Harald Welte03740842009-06-10 23:11:52 +08002536 gh->msg_type = GSM48_MT_CC_PROGRESS;
2537
2538 /* progress */
2539 encode_progress(msg, 1, &progress->progress);
2540 /* user-user */
2541 if (progress->fields & MNCC_F_USERUSER)
2542 encode_useruser(msg, 0, &progress->useruser);
2543
Harald Welte36fe2e82009-07-23 21:13:03 +02002544 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002545}
2546
2547static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2548{
2549 struct gsm_mncc *connect = arg;
2550 struct msgb *msg = gsm48_msgb_alloc();
2551 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2552
Harald Welte03740842009-06-10 23:11:52 +08002553 gh->msg_type = GSM48_MT_CC_CONNECT;
2554
2555 gsm48_stop_cc_timer(trans);
2556 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2557
2558 /* facility */
2559 if (connect->fields & MNCC_F_FACILITY)
2560 encode_facility(msg, 0, &connect->facility);
2561 /* progress */
2562 if (connect->fields & MNCC_F_PROGRESS)
2563 encode_progress(msg, 0, &connect->progress);
2564 /* connected number */
2565 if (connect->fields & MNCC_F_CONNECTED)
2566 encode_connected(msg, &connect->connected);
2567 /* user-user */
2568 if (connect->fields & MNCC_F_USERUSER)
2569 encode_useruser(msg, 0, &connect->useruser);
2570
2571 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2572
Harald Welte36fe2e82009-07-23 21:13:03 +02002573 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002574}
2575
2576static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2577{
2578 struct gsm48_hdr *gh = msgb_l3(msg);
2579 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2580 struct tlv_parsed tp;
2581 struct gsm_mncc connect;
2582
2583 gsm48_stop_cc_timer(trans);
2584
2585 memset(&connect, 0, sizeof(struct gsm_mncc));
2586 connect.callref = trans->callref;
2587 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2588 /* use subscriber as connected party number */
2589 if (trans->subscr) {
2590 connect.fields |= MNCC_F_CONNECTED;
2591 strncpy(connect.connected.number, trans->subscr->extension,
2592 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002593 strncpy(connect.imsi, trans->subscr->imsi,
2594 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002595 }
2596 /* facility */
2597 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2598 connect.fields |= MNCC_F_FACILITY;
2599 decode_facility(&connect.facility,
2600 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2601 }
2602 /* user-user */
2603 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2604 connect.fields |= MNCC_F_USERUSER;
2605 decode_useruser(&connect.useruser,
2606 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2607 }
2608 /* ss-version */
2609 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2610 connect.fields |= MNCC_F_SSVERSION;
2611 decode_ssversion(&connect.ssversion,
2612 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2613 }
2614
2615 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2616
Harald Welte8dd09d62009-07-23 19:06:52 +02002617 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002618}
2619
2620
2621static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2622{
2623 struct gsm_mncc connect_ack;
2624
2625 gsm48_stop_cc_timer(trans);
2626
2627 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2628
2629 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2630 connect_ack.callref = trans->callref;
Harald Welte8dd09d62009-07-23 19:06:52 +02002631 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002632 &connect_ack);
2633}
2634
2635static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2636{
2637 struct msgb *msg = gsm48_msgb_alloc();
2638 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2639
Harald Welte03740842009-06-10 23:11:52 +08002640 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2641
2642 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2643
Harald Welte36fe2e82009-07-23 21:13:03 +02002644 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002645}
2646
2647static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2648{
2649 struct gsm48_hdr *gh = msgb_l3(msg);
2650 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2651 struct tlv_parsed tp;
2652 struct gsm_mncc disc;
2653
2654 gsm48_stop_cc_timer(trans);
2655
2656 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2657
2658 memset(&disc, 0, sizeof(struct gsm_mncc));
2659 disc.callref = trans->callref;
2660 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2661 /* cause */
2662 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2663 disc.fields |= MNCC_F_CAUSE;
2664 decode_cause(&disc.cause,
2665 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2666 }
2667 /* facility */
2668 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2669 disc.fields |= MNCC_F_FACILITY;
2670 decode_facility(&disc.facility,
2671 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2672 }
2673 /* user-user */
2674 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2675 disc.fields |= MNCC_F_USERUSER;
2676 decode_useruser(&disc.useruser,
2677 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2678 }
2679 /* ss-version */
2680 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2681 disc.fields |= MNCC_F_SSVERSION;
2682 decode_ssversion(&disc.ssversion,
2683 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2684 }
2685
Harald Welte8dd09d62009-07-23 19:06:52 +02002686 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002687
2688}
2689
Harald Weltebbc636a2009-06-11 14:23:20 +08002690static struct gsm_mncc_cause default_cause = {
2691 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2692 .coding = 0,
2693 .rec = 0,
2694 .rec_val = 0,
2695 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2696 .diag_len = 0,
2697 .diag = { 0 },
2698};
Harald Welte03740842009-06-10 23:11:52 +08002699
2700static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2701{
2702 struct gsm_mncc *disc = arg;
2703 struct msgb *msg = gsm48_msgb_alloc();
2704 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2705
Harald Welte03740842009-06-10 23:11:52 +08002706 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2707
2708 gsm48_stop_cc_timer(trans);
2709 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2710
2711 /* cause */
2712 if (disc->fields & MNCC_F_CAUSE)
2713 encode_cause(msg, 1, &disc->cause);
2714 else
2715 encode_cause(msg, 1, &default_cause);
2716
2717 /* facility */
2718 if (disc->fields & MNCC_F_FACILITY)
2719 encode_facility(msg, 0, &disc->facility);
2720 /* progress */
2721 if (disc->fields & MNCC_F_PROGRESS)
2722 encode_progress(msg, 0, &disc->progress);
2723 /* user-user */
2724 if (disc->fields & MNCC_F_USERUSER)
2725 encode_useruser(msg, 0, &disc->useruser);
2726
2727 /* store disconnect cause for T306 expiry */
Harald Weltea54b48d2009-07-23 18:56:43 +02002728 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002729
2730 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2731
Harald Welte36fe2e82009-07-23 21:13:03 +02002732 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002733}
2734
2735static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2736{
2737 struct gsm48_hdr *gh = msgb_l3(msg);
2738 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2739 struct tlv_parsed tp;
2740 struct gsm_mncc rel;
2741 int rc;
2742
2743 gsm48_stop_cc_timer(trans);
2744
2745 memset(&rel, 0, sizeof(struct gsm_mncc));
2746 rel.callref = trans->callref;
2747 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2748 /* cause */
2749 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2750 rel.fields |= MNCC_F_CAUSE;
2751 decode_cause(&rel.cause,
2752 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2753 }
2754 /* facility */
2755 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2756 rel.fields |= MNCC_F_FACILITY;
2757 decode_facility(&rel.facility,
2758 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2759 }
2760 /* user-user */
2761 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2762 rel.fields |= MNCC_F_USERUSER;
2763 decode_useruser(&rel.useruser,
2764 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2765 }
2766 /* ss-version */
2767 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2768 rel.fields |= MNCC_F_SSVERSION;
2769 decode_ssversion(&rel.ssversion,
2770 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2771 }
2772
Harald Weltea54b48d2009-07-23 18:56:43 +02002773 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002774 /* release collision 5.4.5 */
Harald Welte8dd09d62009-07-23 19:06:52 +02002775 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002776 } else {
Harald Welte8dd09d62009-07-23 19:06:52 +02002777 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002778 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte8dd09d62009-07-23 19:06:52 +02002779 GSM48_MT_CC_RELEASE_COMPL);
2780 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002781 }
2782
2783 new_cc_state(trans, GSM_CSTATE_NULL);
2784
2785 trans->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02002786 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002787
2788 return rc;
2789}
2790
2791static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2792{
2793 struct gsm_mncc *rel = arg;
2794 struct msgb *msg = gsm48_msgb_alloc();
2795 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2796
Harald Welte03740842009-06-10 23:11:52 +08002797 gh->msg_type = GSM48_MT_CC_RELEASE;
2798
2799 trans->callref = 0;
2800
2801 gsm48_stop_cc_timer(trans);
2802 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2803
2804 /* cause */
2805 if (rel->fields & MNCC_F_CAUSE)
2806 encode_cause(msg, 0, &rel->cause);
2807 /* facility */
2808 if (rel->fields & MNCC_F_FACILITY)
2809 encode_facility(msg, 0, &rel->facility);
2810 /* user-user */
2811 if (rel->fields & MNCC_F_USERUSER)
2812 encode_useruser(msg, 0, &rel->useruser);
2813
Harald Weltea54b48d2009-07-23 18:56:43 +02002814 trans->cc.T308_second = 0;
2815 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002816
Harald Weltea54b48d2009-07-23 18:56:43 +02002817 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002818 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2819
Harald Welte36fe2e82009-07-23 21:13:03 +02002820 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002821}
2822
2823static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2824{
2825 struct gsm48_hdr *gh = msgb_l3(msg);
2826 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2827 struct tlv_parsed tp;
2828 struct gsm_mncc rel;
2829 int rc = 0;
2830
2831 gsm48_stop_cc_timer(trans);
2832
2833 memset(&rel, 0, sizeof(struct gsm_mncc));
2834 rel.callref = trans->callref;
2835 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2836 /* cause */
2837 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2838 rel.fields |= MNCC_F_CAUSE;
2839 decode_cause(&rel.cause,
2840 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2841 }
2842 /* facility */
2843 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2844 rel.fields |= MNCC_F_FACILITY;
2845 decode_facility(&rel.facility,
2846 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2847 }
2848 /* user-user */
2849 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2850 rel.fields |= MNCC_F_USERUSER;
2851 decode_useruser(&rel.useruser,
2852 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2853 }
2854 /* ss-version */
2855 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2856 rel.fields |= MNCC_F_SSVERSION;
2857 decode_ssversion(&rel.ssversion,
2858 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2859 }
2860
2861 if (trans->callref) {
Harald Weltea54b48d2009-07-23 18:56:43 +02002862 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08002863 case GSM_CSTATE_CALL_PRESENT:
Harald Welte8dd09d62009-07-23 19:06:52 +02002864 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002865 MNCC_REJ_IND, &rel);
2866 break;
2867 case GSM_CSTATE_RELEASE_REQ:
Harald Welte8dd09d62009-07-23 19:06:52 +02002868 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002869 MNCC_REL_CNF, &rel);
2870 break;
2871 default:
Harald Welte8dd09d62009-07-23 19:06:52 +02002872 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002873 MNCC_REL_IND, &rel);
2874 }
2875 }
2876
2877 trans->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02002878 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002879
2880 return rc;
2881}
2882
2883static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2884{
2885 struct gsm_mncc *rel = arg;
2886 struct msgb *msg = gsm48_msgb_alloc();
2887 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2888
Harald Welte03740842009-06-10 23:11:52 +08002889 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2890
2891 trans->callref = 0;
2892
2893 gsm48_stop_cc_timer(trans);
2894
2895 /* cause */
2896 if (rel->fields & MNCC_F_CAUSE)
2897 encode_cause(msg, 0, &rel->cause);
2898 /* facility */
2899 if (rel->fields & MNCC_F_FACILITY)
2900 encode_facility(msg, 0, &rel->facility);
2901 /* user-user */
2902 if (rel->fields & MNCC_F_USERUSER)
2903 encode_useruser(msg, 0, &rel->useruser);
2904
Harald Weltea54b48d2009-07-23 18:56:43 +02002905 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002906
Harald Welte36fe2e82009-07-23 21:13:03 +02002907 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002908}
2909
2910static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2911{
2912 struct gsm48_hdr *gh = msgb_l3(msg);
2913 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2914 struct tlv_parsed tp;
2915 struct gsm_mncc fac;
2916
2917 memset(&fac, 0, sizeof(struct gsm_mncc));
2918 fac.callref = trans->callref;
2919 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2920 /* facility */
2921 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2922 fac.fields |= MNCC_F_FACILITY;
2923 decode_facility(&fac.facility,
2924 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2925 }
2926 /* ss-version */
2927 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2928 fac.fields |= MNCC_F_SSVERSION;
2929 decode_ssversion(&fac.ssversion,
2930 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2931 }
2932
Harald Welte8dd09d62009-07-23 19:06:52 +02002933 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08002934}
2935
2936static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2937{
2938 struct gsm_mncc *fac = arg;
2939 struct msgb *msg = gsm48_msgb_alloc();
2940 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2941
Harald Welte03740842009-06-10 23:11:52 +08002942 gh->msg_type = GSM48_MT_CC_FACILITY;
2943
2944 /* facility */
2945 encode_facility(msg, 1, &fac->facility);
2946
Harald Welte36fe2e82009-07-23 21:13:03 +02002947 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002948}
2949
2950static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2951{
2952 struct gsm_mncc hold;
2953
2954 memset(&hold, 0, sizeof(struct gsm_mncc));
2955 hold.callref = trans->callref;
Harald Welte8dd09d62009-07-23 19:06:52 +02002956 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08002957}
2958
2959static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2960{
2961 struct msgb *msg = gsm48_msgb_alloc();
2962 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2963
Harald Welte03740842009-06-10 23:11:52 +08002964 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2965
Harald Welte36fe2e82009-07-23 21:13:03 +02002966 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002967}
2968
2969static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2970{
2971 struct gsm_mncc *hold_rej = arg;
2972 struct msgb *msg = gsm48_msgb_alloc();
2973 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2974
Harald Welte03740842009-06-10 23:11:52 +08002975 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2976
2977 /* cause */
2978 if (hold_rej->fields & MNCC_F_CAUSE)
2979 encode_cause(msg, 1, &hold_rej->cause);
2980 else
2981 encode_cause(msg, 1, &default_cause);
2982
Harald Welte36fe2e82009-07-23 21:13:03 +02002983 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002984}
2985
2986static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2987{
2988 struct gsm_mncc retrieve;
2989
2990 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2991 retrieve.callref = trans->callref;
Harald Welte8dd09d62009-07-23 19:06:52 +02002992 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2993 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08002994}
2995
2996static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2997{
2998 struct msgb *msg = gsm48_msgb_alloc();
2999 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3000
Harald Welte03740842009-06-10 23:11:52 +08003001 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3002
Harald Welte36fe2e82009-07-23 21:13:03 +02003003 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003004}
3005
3006static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3007{
3008 struct gsm_mncc *retrieve_rej = arg;
3009 struct msgb *msg = gsm48_msgb_alloc();
3010 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3011
Harald Welte03740842009-06-10 23:11:52 +08003012 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3013
3014 /* cause */
3015 if (retrieve_rej->fields & MNCC_F_CAUSE)
3016 encode_cause(msg, 1, &retrieve_rej->cause);
3017 else
3018 encode_cause(msg, 1, &default_cause);
3019
Harald Welte36fe2e82009-07-23 21:13:03 +02003020 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003021}
3022
3023static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3024{
3025 struct gsm48_hdr *gh = msgb_l3(msg);
3026 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3027 struct tlv_parsed tp;
3028 struct gsm_mncc dtmf;
3029
3030 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3031 dtmf.callref = trans->callref;
3032 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3033 /* keypad facility */
3034 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3035 dtmf.fields |= MNCC_F_KEYPAD;
3036 decode_keypad(&dtmf.keypad,
3037 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3038 }
3039
Harald Welte8dd09d62009-07-23 19:06:52 +02003040 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003041}
3042
3043static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3044{
3045 struct gsm_mncc *dtmf = arg;
3046 struct msgb *msg = gsm48_msgb_alloc();
3047 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3048
Harald Welte03740842009-06-10 23:11:52 +08003049 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3050
3051 /* keypad */
3052 if (dtmf->fields & MNCC_F_KEYPAD)
3053 encode_keypad(msg, dtmf->keypad);
3054
Harald Welte36fe2e82009-07-23 21:13:03 +02003055 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003056}
3057
3058static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3059{
3060 struct gsm_mncc *dtmf = arg;
3061 struct msgb *msg = gsm48_msgb_alloc();
3062 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3063
Harald Welte03740842009-06-10 23:11:52 +08003064 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3065
3066 /* cause */
3067 if (dtmf->fields & MNCC_F_CAUSE)
3068 encode_cause(msg, 1, &dtmf->cause);
3069 else
3070 encode_cause(msg, 1, &default_cause);
3071
Harald Welte36fe2e82009-07-23 21:13:03 +02003072 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003073}
3074
3075static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3076{
3077 struct msgb *msg = gsm48_msgb_alloc();
3078 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3079
Harald Welte03740842009-06-10 23:11:52 +08003080 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3081
Harald Welte36fe2e82009-07-23 21:13:03 +02003082 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003083}
3084
3085static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3086{
3087 struct gsm_mncc dtmf;
3088
3089 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3090 dtmf.callref = trans->callref;
3091
Harald Welte8dd09d62009-07-23 19:06:52 +02003092 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003093}
3094
3095static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3096{
3097 struct gsm48_hdr *gh = msgb_l3(msg);
3098 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3099 struct tlv_parsed tp;
3100 struct gsm_mncc modify;
3101
3102 memset(&modify, 0, sizeof(struct gsm_mncc));
3103 modify.callref = trans->callref;
3104 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3105 /* bearer capability */
3106 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3107 modify.fields |= MNCC_F_BEARER_CAP;
3108 decode_bearer_cap(&modify.bearer_cap,
3109 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3110 }
3111
3112 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3113
Harald Welte8dd09d62009-07-23 19:06:52 +02003114 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003115}
3116
3117static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3118{
3119 struct gsm_mncc *modify = arg;
3120 struct msgb *msg = gsm48_msgb_alloc();
3121 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3122
Harald Welte03740842009-06-10 23:11:52 +08003123 gh->msg_type = GSM48_MT_CC_MODIFY;
3124
3125 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3126
3127 /* bearer capability */
3128 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3129
3130 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3131
Harald Welte36fe2e82009-07-23 21:13:03 +02003132 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003133}
3134
3135static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3136{
3137 struct gsm48_hdr *gh = msgb_l3(msg);
3138 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3139 struct tlv_parsed tp;
3140 struct gsm_mncc modify;
3141
3142 gsm48_stop_cc_timer(trans);
3143
3144 memset(&modify, 0, sizeof(struct gsm_mncc));
3145 modify.callref = trans->callref;
3146 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3147 /* bearer capability */
3148 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3149 modify.fields |= MNCC_F_BEARER_CAP;
3150 decode_bearer_cap(&modify.bearer_cap,
3151 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3152 }
3153
3154 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3155
Harald Welte8dd09d62009-07-23 19:06:52 +02003156 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003157}
3158
3159static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3160{
3161 struct gsm_mncc *modify = arg;
3162 struct msgb *msg = gsm48_msgb_alloc();
3163 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3164
Harald Welte03740842009-06-10 23:11:52 +08003165 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3166
3167 /* bearer capability */
3168 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3169
3170 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3171
Harald Welte36fe2e82009-07-23 21:13:03 +02003172 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003173}
3174
3175static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3176{
3177 struct gsm48_hdr *gh = msgb_l3(msg);
3178 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3179 struct tlv_parsed tp;
3180 struct gsm_mncc modify;
3181
3182 gsm48_stop_cc_timer(trans);
3183
3184 memset(&modify, 0, sizeof(struct gsm_mncc));
3185 modify.callref = trans->callref;
3186 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3187 /* bearer capability */
3188 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3189 modify.fields |= GSM48_IE_BEARER_CAP;
3190 decode_bearer_cap(&modify.bearer_cap,
3191 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3192 }
3193 /* cause */
3194 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3195 modify.fields |= MNCC_F_CAUSE;
3196 decode_cause(&modify.cause,
3197 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3198 }
3199
3200 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3201
Harald Welte8dd09d62009-07-23 19:06:52 +02003202 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003203}
3204
3205static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3206{
3207 struct gsm_mncc *modify = arg;
3208 struct msgb *msg = gsm48_msgb_alloc();
3209 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3210
Harald Welte03740842009-06-10 23:11:52 +08003211 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3212
3213 /* bearer capability */
3214 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3215 /* cause */
3216 encode_cause(msg, 1, &modify->cause);
3217
3218 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3219
Harald Welte36fe2e82009-07-23 21:13:03 +02003220 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003221}
3222
3223static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3224{
3225 struct gsm_mncc *notify = arg;
3226 struct msgb *msg = gsm48_msgb_alloc();
3227 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3228
Harald Welte03740842009-06-10 23:11:52 +08003229 gh->msg_type = GSM48_MT_CC_NOTIFY;
3230
3231 /* notify */
3232 encode_notify(msg, notify->notify);
3233
Harald Welte36fe2e82009-07-23 21:13:03 +02003234 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003235}
3236
3237static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3238{
3239 struct gsm48_hdr *gh = msgb_l3(msg);
3240 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3241// struct tlv_parsed tp;
3242 struct gsm_mncc notify;
3243
3244 memset(&notify, 0, sizeof(struct gsm_mncc));
3245 notify.callref = trans->callref;
3246// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3247 if (payload_len >= 1)
3248 decode_notify(&notify.notify, gh->data);
3249
Harald Welte8dd09d62009-07-23 19:06:52 +02003250 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003251}
3252
3253static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3254{
3255 struct gsm_mncc *user = arg;
3256 struct msgb *msg = gsm48_msgb_alloc();
3257 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3258
Harald Welte03740842009-06-10 23:11:52 +08003259 gh->msg_type = GSM48_MT_CC_USER_INFO;
3260
3261 /* user-user */
3262 if (user->fields & MNCC_F_USERUSER)
3263 encode_useruser(msg, 1, &user->useruser);
3264 /* more data */
3265 if (user->more)
3266 encode_more(msg);
3267
Harald Welte36fe2e82009-07-23 21:13:03 +02003268 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003269}
3270
3271static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3272{
3273 struct gsm48_hdr *gh = msgb_l3(msg);
3274 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3275 struct tlv_parsed tp;
3276 struct gsm_mncc user;
3277
3278 memset(&user, 0, sizeof(struct gsm_mncc));
3279 user.callref = trans->callref;
3280 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3281 /* user-user */
3282 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3283 user.fields |= MNCC_F_USERUSER;
3284 decode_useruser(&user.useruser,
3285 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3286 }
3287 /* more data */
3288 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3289 user.more = 1;
3290
Harald Welte8dd09d62009-07-23 19:06:52 +02003291 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003292}
3293
3294static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3295{
3296 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003297 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003298
Harald Welteca745e22009-07-29 12:10:35 +02003299 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3300 if (rc < 0)
3301 return rc;
3302
3303 /* FIXME: we not only need to do this after mode modify, but
3304 * also after channel activation */
3305 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3306 mode->lchan_mode != GSM48_CMODE_SIGN)
3307 rc = rsl_ipacc_bind(trans->lchan);
3308
3309 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003310}
3311
3312static struct downstate {
3313 u_int32_t states;
3314 int type;
3315 int (*rout) (struct gsm_trans *trans, void *arg);
3316} downstatelist[] = {
3317 /* mobile originating call establishment */
3318 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3319 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3320 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3321 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3322 {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 */
3323 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3324 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3325 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3326 /* mobile terminating call establishment */
3327 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3328 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3329 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3330 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3331 /* signalling during call */
3332 {SBIT(GSM_CSTATE_ACTIVE),
3333 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3334 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3335 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3336 {ALL_STATES,
3337 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3338 {ALL_STATES,
3339 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3340 {ALL_STATES,
3341 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3342 {SBIT(GSM_CSTATE_ACTIVE),
3343 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3344 {SBIT(GSM_CSTATE_ACTIVE),
3345 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3346 {SBIT(GSM_CSTATE_ACTIVE),
3347 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3348 {SBIT(GSM_CSTATE_ACTIVE),
3349 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3350 {SBIT(GSM_CSTATE_ACTIVE),
3351 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3352 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3353 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3354 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3355 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3356 {SBIT(GSM_CSTATE_ACTIVE),
3357 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3358 /* clearing */
3359 {SBIT(GSM_CSTATE_INITIATED),
3360 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3361 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3362 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3363 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3364 MNCC_REL_REQ, gsm48_cc_tx_release},
3365 /* special */
3366 {ALL_STATES,
3367 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3368};
3369
3370#define DOWNSLLEN \
3371 (sizeof(downstatelist) / sizeof(struct downstate))
3372
3373
3374int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3375{
3376 int i, j, k, l, rc = 0;
3377 struct gsm_trans *trans = NULL, *transt;
3378 struct gsm_subscriber *subscr;
3379 struct gsm_lchan *lchan = NULL, *lchant;
3380 struct gsm_bts *bts = NULL;
3381 struct gsm_bts_trx *trx;
3382 struct gsm_bts_trx_ts *ts;
3383 struct gsm_mncc *data = arg, rel;
3384
3385 /* handle special messages */
3386 switch(msg_type) {
3387 case MNCC_BRIDGE:
3388 return tch_bridge(net, arg);
3389 case MNCC_FRAME_DROP:
3390 return tch_recv(net, arg, 0);
3391 case MNCC_FRAME_RECV:
3392 return tch_recv(net, arg, 1);
3393 case GSM_TRAU_FRAME:
3394 return tch_frame(net, arg);
3395 }
3396
3397 memset(&rel, 0, sizeof(struct gsm_mncc));
3398 rel.callref = data->callref;
3399
3400 /* Find callref */
Harald Weltea54b48d2009-07-23 18:56:43 +02003401 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003402
3403 /* Callref unknown */
3404 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003405 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003406 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3407 "Received '%s' from MNCC with "
3408 "unknown callref %d\n", data->called.number,
3409 get_mncc_name(msg_type), data->callref);
3410 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003411 return mncc_release_ind(net, NULL, data->callref,
3412 GSM48_CAUSE_LOC_PRN_S_LU,
3413 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003414 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003415 if (!data->called.number[0] && !data->imsi[0]) {
3416 DEBUGP(DCC, "(bts - trx - ts - ti) "
3417 "Received '%s' from MNCC with "
3418 "no number or IMSI\n", get_mncc_name(msg_type));
3419 /* Invalid number */
3420 return mncc_release_ind(net, NULL, data->callref,
3421 GSM48_CAUSE_LOC_PRN_S_LU,
3422 GSM48_CC_CAUSE_INV_NR_FORMAT);
3423 }
Harald Welte03740842009-06-10 23:11:52 +08003424 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003425 if (data->called.number[0])
Harald Welteaae7a522009-07-23 19:21:02 +02003426 subscr = subscr_get_by_extension(net,
3427 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003428 else
Harald Welteaae7a522009-07-23 19:21:02 +02003429 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003430 /* If subscriber is not found */
3431 if (!subscr) {
3432 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3433 "Received '%s' from MNCC with "
3434 "unknown subscriber %s\n", data->called.number,
3435 get_mncc_name(msg_type), data->called.number);
3436 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003437 return mncc_release_ind(net, NULL, data->callref,
3438 GSM48_CAUSE_LOC_PRN_S_LU,
3439 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003440 }
3441 /* If subscriber is not "attached" */
3442 if (!subscr->lac) {
3443 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3444 "Received '%s' from MNCC with "
3445 "detached subscriber %s\n", data->called.number,
3446 get_mncc_name(msg_type), data->called.number);
3447 subscr_put(subscr);
3448 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003449 return mncc_release_ind(net, NULL, data->callref,
3450 GSM48_CAUSE_LOC_PRN_S_LU,
3451 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003452 }
3453 /* Create transaction */
Harald Weltea54b48d2009-07-23 18:56:43 +02003454 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3455 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003456 DEBUGP(DCC, "No memory for trans.\n");
3457 subscr_put(subscr);
3458 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003459 mncc_release_ind(net, NULL, data->callref,
3460 GSM48_CAUSE_LOC_PRN_S_LU,
3461 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003462 return -ENOMEM;
3463 }
Harald Welte03740842009-06-10 23:11:52 +08003464 /* Find lchan */
3465 for (i = 0; i < net->num_bts; i++) {
Harald Weltee712a5f2009-06-21 16:17:15 +02003466 bts = gsm_bts_num(net, i);
Harald Welte03740842009-06-10 23:11:52 +08003467 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee712a5f2009-06-21 16:17:15 +02003468 trx = gsm_bts_trx_num(bts, j);
Harald Welte03740842009-06-10 23:11:52 +08003469 for (k = 0; k < TRX_NR_TS; k++) {
3470 ts = &trx->ts[k];
3471 for (l = 0; l < TS_MAX_LCHAN; l++) {
3472 lchant = &ts->lchan[l];
3473 if (lchant->subscr == subscr) {
3474 lchan = lchant;
3475 break;
3476 }
3477 }
3478 }
3479 }
3480 }
3481
3482 /* If subscriber has no lchan */
3483 if (!lchan) {
3484 /* find transaction with this subscriber already paging */
3485 llist_for_each_entry(transt, &net->trans_list, entry) {
3486 /* Transaction of our lchan? */
3487 if (transt == trans ||
3488 transt->subscr != subscr)
3489 continue;
3490 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3491 "Received '%s' from MNCC with "
3492 "unallocated channel, paging already "
3493 "started.\n", bts->nr,
3494 data->called.number,
3495 get_mncc_name(msg_type));
3496 return 0;
3497 }
3498 /* store setup informations until paging was successfull */
Harald Weltea54b48d2009-07-23 18:56:43 +02003499 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08003500 /* start paging subscriber on all BTS with her location */
3501 subscr->net = net;
3502 bts = NULL;
3503 do {
3504 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3505 if (!bts)
3506 break;
3507 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3508 "Received '%s' from MNCC with "
3509 "unallocated channel, paging.\n",
3510 bts->nr, data->called.number,
3511 get_mncc_name(msg_type));
3512 /* Trigger paging */
Harald Weltecb0595f2009-06-12 01:54:08 +08003513 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte03740842009-06-10 23:11:52 +08003514 setup_trig_pag_evt, subscr);
3515 } while (1);
3516 return 0;
3517 }
3518 /* Assign lchan */
3519 trans->lchan = lchan;
3520 use_lchan(lchan);
3521 }
3522 lchan = trans->lchan;
3523
3524 /* if paging did not respond yet */
3525 if (!lchan) {
3526 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3527 "Received '%s' from MNCC in paging state\n",
3528 (trans->subscr)?(trans->subscr->extension):"-",
3529 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003530 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3531 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003532 if (msg_type == MNCC_REL_REQ)
3533 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3534 else
3535 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3536 trans->callref = 0;
Harald Weltea54b48d2009-07-23 18:56:43 +02003537 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003538 return rc;
3539 }
3540
3541 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3542 "Received '%s' from MNCC in state %d (%s)\n",
3543 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3544 trans->transaction_id,
3545 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltea54b48d2009-07-23 18:56:43 +02003546 get_mncc_name(msg_type), trans->cc.state,
3547 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003548
3549 /* Find function for current state and message */
3550 for (i = 0; i < DOWNSLLEN; i++)
3551 if ((msg_type == downstatelist[i].type)
Harald Weltea54b48d2009-07-23 18:56:43 +02003552 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003553 break;
3554 if (i == DOWNSLLEN) {
3555 DEBUGP(DCC, "Message unhandled at this state.\n");
3556 return 0;
3557 }
3558
3559 rc = downstatelist[i].rout(trans, arg);
3560
3561 return rc;
3562}
3563
3564
3565static struct datastate {
3566 u_int32_t states;
3567 int type;
3568 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3569} datastatelist[] = {
3570 /* mobile originating call establishment */
3571 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3572 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3573 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3574 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3575 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3576 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3577 /* mobile terminating call establishment */
3578 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3579 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3580 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3581 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3582 {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 */
3583 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3584 /* signalling during call */
3585 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3586 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3587 {SBIT(GSM_CSTATE_ACTIVE),
3588 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3589 {ALL_STATES,
3590 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3591 {ALL_STATES,
3592 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3593 {ALL_STATES,
3594 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3595 {SBIT(GSM_CSTATE_ACTIVE),
3596 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3597 {SBIT(GSM_CSTATE_ACTIVE),
3598 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3599 {SBIT(GSM_CSTATE_ACTIVE),
3600 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3601 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3602 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3603 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3604 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3605 {SBIT(GSM_CSTATE_ACTIVE),
3606 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3607 /* clearing */
3608 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3609 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3610 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3611 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3612 {ALL_STATES, /* 5.4.3.4 */
3613 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3614};
3615
3616#define DATASLLEN \
3617 (sizeof(datastatelist) / sizeof(struct datastate))
3618
Harald Welte59b04682009-06-10 05:40:52 +08003619static int gsm0408_rcv_cc(struct msgb *msg)
3620{
3621 struct gsm48_hdr *gh = msgb_l3(msg);
3622 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003623 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003624 struct gsm_lchan *lchan = msg->lchan;
Harald Weltea54b48d2009-07-23 18:56:43 +02003625 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003626 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003627
Harald Welte03740842009-06-10 23:11:52 +08003628 if (msg_type & 0x80) {
3629 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3630 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003631 }
Harald Welte03740842009-06-10 23:11:52 +08003632
3633 /* Find transaction */
Harald Weltea54b48d2009-07-23 18:56:43 +02003634 trans = trans_find_by_id(lchan, transaction_id);
3635
Harald Welte4861c822009-07-23 21:21:14 +02003636 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003637 "Received '%s' from MS in state %d (%s)\n",
3638 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3639 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltea54b48d2009-07-23 18:56:43 +02003640 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3641 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003642
3643 /* Create transaction */
3644 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003645 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003646 "creating new trans.\n", transaction_id);
3647 /* Create transaction */
Harald Weltea54b48d2009-07-23 18:56:43 +02003648 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3649 transaction_id, new_callref++);
3650 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003651 DEBUGP(DCC, "No memory for trans.\n");
3652 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003653 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003654 GSM48_MT_CC_RELEASE_COMPL);
3655 return -ENOMEM;
3656 }
Harald Welte03740842009-06-10 23:11:52 +08003657 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003658 trans->lchan = lchan;
3659 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003660 }
3661
3662 /* find function for current state and message */
3663 for (i = 0; i < DATASLLEN; i++)
3664 if ((msg_type == datastatelist[i].type)
Harald Weltea54b48d2009-07-23 18:56:43 +02003665 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003666 break;
3667 if (i == DATASLLEN) {
3668 DEBUGP(DCC, "Message unhandled at this state.\n");
3669 return 0;
3670 }
3671
3672 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003673
3674 return rc;
3675}
3676
3677/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3678int gsm0408_rcvmsg(struct msgb *msg)
3679{
3680 struct gsm48_hdr *gh = msgb_l3(msg);
3681 u_int8_t pdisc = gh->proto_discr & 0x0f;
3682 int rc = 0;
3683
3684 switch (pdisc) {
3685 case GSM48_PDISC_CC:
3686 rc = gsm0408_rcv_cc(msg);
3687 break;
3688 case GSM48_PDISC_MM:
3689 rc = gsm0408_rcv_mm(msg);
3690 break;
3691 case GSM48_PDISC_RR:
3692 rc = gsm0408_rcv_rr(msg);
3693 break;
3694 case GSM48_PDISC_SMS:
3695 rc = gsm0411_rcv_sms(msg);
3696 break;
3697 case GSM48_PDISC_MM_GPRS:
3698 case GSM48_PDISC_SM_GPRS:
3699 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3700 pdisc);
3701 break;
3702 default:
3703 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3704 pdisc);
3705 break;
3706 }
3707
3708 return rc;
3709}
3710
Harald Welte59b04682009-06-10 05:40:52 +08003711/* Section 9.1.8 / Table 9.9 */
3712struct chreq {
3713 u_int8_t val;
3714 u_int8_t mask;
3715 enum chreq_type type;
3716};
3717
3718/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3719static const struct chreq chreq_type_neci1[] = {
3720 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3721 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3722 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3723 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3724 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3725 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3726 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3727 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3728 { 0x10, 0xf0, CHREQ_T_SDCCH },
3729 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3730 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3731 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3732};
3733
3734/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3735static const struct chreq chreq_type_neci0[] = {
3736 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3737 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3738 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3739 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3740 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3741 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3742 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3743 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3744};
3745
3746static const enum gsm_chan_t ctype_by_chreq[] = {
3747 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3748 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3749 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3750 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3751 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3752 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3753 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3754 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3755 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3756 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3757 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3758 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3759};
3760
3761static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3762 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3763 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3764 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3765 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3766 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3767 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3768 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3769 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3770 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3771 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3772 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3773 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3774};
3775
3776enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3777{
3778 int i;
3779 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3780
3781 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3782 const struct chreq *chr = &chreq_type_neci0[i];
3783 if ((ra & chr->mask) == chr->val)
3784 return ctype_by_chreq[chr->type];
3785 }
3786 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3787 return GSM_LCHAN_SDCCH;
3788}
3789
3790enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3791{
3792 int i;
3793 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3794
3795 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3796 const struct chreq *chr = &chreq_type_neci0[i];
3797 if ((ra & chr->mask) == chr->val)
3798 return reason_by_chreq[chr->type];
3799 }
3800 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3801 return GSM_CHREQ_REASON_OTHER;
3802}
Harald Welte03740842009-06-10 23:11:52 +08003803
3804/* dequeue messages to layer 4 */
3805int bsc_upqueue(struct gsm_network *net)
3806{
3807 struct gsm_mncc *mncc;
3808 struct msgb *msg;
3809 int work = 0;
3810
3811 if (net)
3812 while ((msg = msgb_dequeue(&net->upqueue))) {
3813 mncc = (struct gsm_mncc *)msg->data;
3814 if (net->mncc_recv)
3815 net->mncc_recv(net, mncc->msg_type, mncc);
3816 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003817 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003818 }
3819
3820 return work;
3821}
Harald Weltea54b48d2009-07-23 18:56:43 +02003822
Harald Welte3c062072009-07-28 18:25:29 +02003823/*
3824 * This will be ran by the linker when loading the DSO. We use it to
3825 * do system initialization, e.g. registration of signal handlers.
3826 */
3827static __attribute__((constructor)) void on_dso_load_0408(void)
3828{
3829 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3830 "loc_updating_oper");
3831 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3832 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3833}