blob: b753e0d8d2970de7cdcc7b61df0966c342cba035 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <time.h>
31#include <netinet/in.h>
32
33#include <openbsc/db.h>
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
42#include <openbsc/chan_alloc.h>
43#include <openbsc/paging.h>
44#include <openbsc/signal.h>
45#include <openbsc/trau_frame.h>
46#include <openbsc/trau_mux.h>
Harald Welte3c062072009-07-28 18:25:29 +020047#include <openbsc/rtp_proxy.h>
Harald Weltea8379772009-06-20 22:36:41 +020048#include <openbsc/talloc.h>
Harald Weltec2189a62009-07-23 18:56:43 +020049#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080050
51#define GSM48_ALLOC_SIZE 1024
52#define GSM48_ALLOC_HEADROOM 128
53
Harald Welteb8a18b52009-06-10 12:08:54 +080054#define GSM_MAX_FACILITY 128
55#define GSM_MAX_SSVERSION 128
56#define GSM_MAX_USERUSER 128
57
Harald Weltea8379772009-06-20 22:36:41 +020058static void *tall_locop_ctx;
Harald Weltea8379772009-06-20 22:36:41 +020059
Harald Welte3c062072009-07-28 18:25:29 +020060/* should ip.access BTS use direct RTP streams between each other (1),
61 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
62int ipacc_rtp_direct = 1;
63
Harald Welte59b04682009-06-10 05:40:52 +080064static const struct tlv_definition rsl_att_tlvdef = {
65 .def = {
66 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
67 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
69 [GSM48_IE_UTC] = { TLV_TYPE_TV },
70 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
71 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
72
73 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
74 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
75 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
76 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
77 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
78 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
79 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welteb8a18b52009-06-10 12:08:54 +080080 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte59b04682009-06-10 05:40:52 +080081 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
82 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welteb8a18b52009-06-10 12:08:54 +080083 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
84 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte59b04682009-06-10 05:40:52 +080085 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
86 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
89 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
91 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
92 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
94 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
95 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
96 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
98 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welteb8a18b52009-06-10 12:08:54 +080099 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
100 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte59b04682009-06-10 05:40:52 +0800101 /* FIXME: more elements */
102 },
103};
104
105static const char *rr_cause_names[] = {
106 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
107 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
108 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
109 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
110 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
111 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
112 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
113 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
114 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
115 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
116 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
117 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
118 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
119 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
120 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
121 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
122 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
123};
124
Harald Welte03740842009-06-10 23:11:52 +0800125static const char *cc_state_names[] = {
126 "NULL",
127 "INITIATED",
128 "illegal state 2",
129 "MO_CALL_PROC",
130 "CALL_DELIVERED",
131 "illegal state 5",
132 "CALL_PRESENT",
133 "CALL_RECEIVED",
134 "CONNECT_REQUEST",
135 "MO_TERM_CALL_CONF",
136 "ACTIVE",
137 "DISCONNECT_REQ",
138 "DISCONNECT_IND",
139 "illegal state 13",
140 "illegal state 14",
141 "illegal state 15",
142 "illegal state 16",
143 "illegal state 17",
144 "illegal state 18",
145 "RELEASE_REQ",
146 "illegal state 20",
147 "illegal state 21",
148 "illegal state 22",
149 "illegal state 23",
150 "illegal state 24",
151 "illegal state 25",
152 "MO_ORIG_MODIFY",
153 "MO_TERM_MODIFY",
154 "CONNECT_IND",
155 "illegal state 29",
156 "illegal state 30",
157 "illegal state 31",
158};
159
160static const char *cc_msg_names[] = {
161 "unknown 0x00",
162 "ALERTING",
163 "CALL_PROC",
164 "PROGRESS",
165 "ESTAB",
166 "SETUP",
167 "ESTAB_CONF",
168 "CONNECT",
169 "CALL_CONF",
170 "START_CC",
171 "unknown 0x0a",
172 "RECALL",
173 "unknown 0x0c",
174 "unknown 0x0d",
175 "EMERG_SETUP",
176 "CONNECT_ACK",
177 "USER_INFO",
178 "unknown 0x11",
179 "unknown 0x12",
180 "MODIFY_REJECT",
181 "unknown 0x14",
182 "unknown 0x15",
183 "unknown 0x16",
184 "MODIFY",
185 "HOLD",
186 "HOLD_ACK",
187 "HOLD_REJ",
188 "unknown 0x1b",
189 "RETR",
190 "RETR_ACK",
191 "RETR_REJ",
192 "MODIFY_COMPL",
193 "unknown 0x20",
194 "unknown 0x21",
195 "unknown 0x22",
196 "unknown 0x23",
197 "unknown 0x24",
198 "DISCONNECT",
199 "unknown 0x26",
200 "unknown 0x27",
201 "unknown 0x28",
202 "unknown 0x29",
203 "RELEASE_COMPL",
204 "unknown 0x2b",
205 "unknown 0x2c",
206 "RELEASE",
207 "unknown 0x2e",
208 "unknown 0x2f",
209 "unknown 0x30",
210 "STOP_DTMF",
211 "STOP_DTMF_ACK",
212 "unknown 0x33",
213 "STATUS_ENQ",
214 "START_DTMF",
215 "START_DTMF_ACK",
216 "START_DTMF_REJ",
217 "unknown 0x38",
218 "CONG_CTRL",
219 "FACILITY",
220 "unknown 0x3b",
221 "STATUS",
222 "unknown 0x3c",
223 "NOTIFY",
224 "unknown 0x3f",
225};
226
Harald Welte59b04682009-06-10 05:40:52 +0800227static char strbuf[64];
228
229static const char *rr_cause_name(u_int8_t cause)
230{
231 if (cause < ARRAY_SIZE(rr_cause_names) &&
232 rr_cause_names[cause])
233 return rr_cause_names[cause];
234
235 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
236 return strbuf;
237}
238
239static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
240 int len)
241{
242 memset(rep, 0, sizeof(*rep));
243
244 if (data[0] & 0x80)
245 rep->flags |= MEAS_REP_F_BA1;
246 if (data[0] & 0x40)
247 rep->flags |= MEAS_REP_F_DTX;
Harald Welteba6589d2009-07-05 04:05:44 +0200248 if ((data[1] & 0x40) == 0x00)
Harald Welte59b04682009-06-10 05:40:52 +0800249 rep->flags |= MEAS_REP_F_VALID;
250
251 rep->rxlev_full = data[0] & 0x3f;
252 rep->rxlev_sub = data[1] & 0x3f;
253 rep->rxqual_full = (data[3] >> 4) & 0x7;
254 rep->rxqual_sub = (data[3] >> 1) & 0x7;
255 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
256 if (rep->num_cell < 1)
257 return;
258
259 /* an encoding nightmare in perfection */
260
261 rep->cell[0].rxlev = data[4] & 0x3f;
262 rep->cell[0].bcch_freq = data[5] >> 2;
263 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
264 if (rep->num_cell < 2)
265 return;
266
267 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
268 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
269 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
270 if (rep->num_cell < 3)
271 return;
272
273 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
274 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
275 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
276 if (rep->num_cell < 4)
277 return;
278
279 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
280 rep->cell[3].bcch_freq = data[11] & 0x1f;
281 rep->cell[3].bsic = data[12] >> 2;
282 if (rep->num_cell < 5)
283 return;
284
285 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
286 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
287 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
288 if (rep->num_cell < 6)
289 return;
290
291 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
292 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
293 rep->cell[5].bsic = data[16] & 0x3f;
294}
295
296int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
297static int gsm48_tx_simple(struct gsm_lchan *lchan,
298 u_int8_t pdisc, u_int8_t msg_type);
299static void schedule_reject(struct gsm_lchan *lchan);
300
301struct gsm_lai {
302 u_int16_t mcc;
303 u_int16_t mnc;
304 u_int16_t lac;
305};
306
307static int authorize_everonye = 0;
308void gsm0408_allow_everyone(int everyone)
309{
310 printf("Allowing everyone?\n");
311 authorize_everonye = everyone;
312}
313
314static int reject_cause = 0;
315void gsm0408_set_reject_cause(int cause)
316{
317 reject_cause = cause;
318}
319
Harald Welte03740842009-06-10 23:11:52 +0800320static u_int32_t new_callref = 0x80000001;
321
Harald Welte59b04682009-06-10 05:40:52 +0800322static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
323 struct gsm_subscriber *subscriber)
324{
325 if (!subscriber)
326 return 0;
327
328 /*
329 * Do not send accept yet as more information should arrive. Some
330 * phones will not send us the information and we will have to check
331 * what we want to do with that.
332 */
333 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
334 return 0;
335
336 if (authorize_everonye)
337 return 1;
338
339 return subscriber->authorized;
340}
341
342static void release_loc_updating_req(struct gsm_lchan *lchan)
343{
344 if (!lchan->loc_operation)
345 return;
346
347 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Weltea8379772009-06-20 22:36:41 +0200348 talloc_free(lchan->loc_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800349 lchan->loc_operation = 0;
350 put_lchan(lchan);
351}
352
353static void allocate_loc_updating_req(struct gsm_lchan *lchan)
354{
355 use_lchan(lchan);
356 release_loc_updating_req(lchan);
357
Harald Welte857e00d2009-06-26 20:25:23 +0200358 lchan->loc_operation = talloc_zero(tall_locop_ctx,
359 struct gsm_loc_updating_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800360}
361
362static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
363{
364 u_int32_t tmsi;
365
366 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
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 Weltec2189a62009-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 Weltec2189a62009-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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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 Welte75350412009-07-23 18:46:00 +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",
Harald Welte68b7df22009-08-08 16:03:15 +02001613 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Harald Welte59b04682009-06-10 05:40:52 +08001614
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 Welte39274f42009-07-29 15:41:29 +02001749 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte59b04682009-06-10 05:40:52 +08001750 rc = rsl_chan_mode_modify_req(msg->lchan);
1751 break;
1752 case GSM48_MT_RR_STATUS:
1753 rc = gsm48_rx_rr_status(msg);
1754 break;
1755 case GSM48_MT_RR_MEAS_REP:
1756 rc = gsm48_rx_rr_meas_rep(msg);
1757 break;
1758 default:
1759 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1760 gh->msg_type);
1761 break;
1762 }
1763
1764 return rc;
1765}
1766
1767/* 7.1.7 and 9.1.7 Channel release*/
1768int gsm48_send_rr_release(struct gsm_lchan *lchan)
1769{
1770 struct msgb *msg = gsm48_msgb_alloc();
1771 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1772 u_int8_t *cause;
1773
1774 msg->lchan = lchan;
1775 gh->proto_discr = GSM48_PDISC_RR;
1776 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1777
1778 cause = msgb_put(msg, 1);
1779 cause[0] = GSM48_RR_CAUSE_NORMAL;
1780
1781 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1782 lchan->nr, lchan->type);
1783
Harald Welteafe3c232009-07-19 18:36:49 +02001784 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001785 gsm48_sendmsg(msg, NULL);
Harald Welte68b7df22009-08-08 16:03:15 +02001786 /* FIXME: Start Timer T3109 */
Harald Welteafe3c232009-07-19 18:36:49 +02001787
1788 /* Deactivate the SACCH on the BTS side */
1789 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001790}
1791
1792/* Call Control */
1793
1794/* The entire call control code is written in accordance with Figure 7.10c
1795 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1796 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1797 * it for voice */
1798
Harald Welte03740842009-06-10 23:11:52 +08001799static void new_cc_state(struct gsm_trans *trans, int state)
1800{
1801 if (state > 31 || state < 0)
1802 return;
1803
1804 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltec2189a62009-07-23 18:56:43 +02001805 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001806
Harald Weltec2189a62009-07-23 18:56:43 +02001807 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001808}
1809
1810static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001811{
1812 struct msgb *msg = gsm48_msgb_alloc();
1813 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1814 u_int8_t *cause, *call_state;
1815
Harald Welte59b04682009-06-10 05:40:52 +08001816 gh->msg_type = GSM48_MT_CC_STATUS;
1817
1818 cause = msgb_put(msg, 3);
1819 cause[0] = 2;
1820 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1821 cause[2] = 0x80 | 30; /* response to status inquiry */
1822
1823 call_state = msgb_put(msg, 1);
1824 call_state[0] = 0xc0 | 0x00;
1825
Harald Welte36fe2e82009-07-23 21:13:03 +02001826 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001827}
1828
1829static int gsm48_tx_simple(struct gsm_lchan *lchan,
1830 u_int8_t pdisc, u_int8_t msg_type)
1831{
1832 struct msgb *msg = gsm48_msgb_alloc();
1833 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1834
1835 msg->lchan = lchan;
1836
1837 gh->proto_discr = pdisc;
1838 gh->msg_type = msg_type;
1839
Harald Welte36fe2e82009-07-23 21:13:03 +02001840 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001841}
1842
Harald Welte03740842009-06-10 23:11:52 +08001843static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1844{
Harald Weltec2189a62009-07-23 18:56:43 +02001845 if (bsc_timer_pending(&trans->cc.timer)) {
1846 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1847 bsc_del_timer(&trans->cc.timer);
1848 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001849 }
1850}
1851
1852static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1853 int msg_type, struct gsm_mncc *mncc)
1854{
1855 struct msgb *msg;
1856
1857 if (trans)
1858 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02001859 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08001860 "Sending '%s' to MNCC.\n",
1861 trans->lchan->ts->trx->bts->nr,
1862 trans->lchan->ts->trx->nr,
1863 trans->lchan->ts->nr, trans->transaction_id,
1864 (trans->subscr)?(trans->subscr->extension):"-",
1865 get_mncc_name(msg_type));
1866 else
1867 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1868 "Sending '%s' to MNCC.\n",
1869 (trans->subscr)?(trans->subscr->extension):"-",
1870 get_mncc_name(msg_type));
1871 else
1872 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1873 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1874
1875 mncc->msg_type = msg_type;
1876
Harald Welte9cfc9352009-06-26 19:39:35 +02001877 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08001878 if (!msg)
1879 return -ENOMEM;
1880 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1881 msgb_enqueue(&net->upqueue, msg);
1882
1883 return 0;
1884}
1885
1886int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1887 u_int32_t callref, int location, int value)
1888{
1889 struct gsm_mncc rel;
1890
Harald Weltecb0595f2009-06-12 01:54:08 +08001891 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08001892 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001893 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08001894 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1895}
1896
Harald Weltec2189a62009-07-23 18:56:43 +02001897/* Call Control Specific transaction release.
1898 * gets called by trans_free, DO NOT CALL YOURSELF! */
1899void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08001900{
Harald Welte03740842009-06-10 23:11:52 +08001901 gsm48_stop_cc_timer(trans);
1902
1903 /* send release to L4, if callref still exists */
1904 if (trans->callref) {
1905 /* Ressource unavailable */
Harald Welte0abe5a62009-07-23 19:06:52 +02001906 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001907 GSM48_CAUSE_LOC_PRN_S_LU,
1908 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08001909 }
Harald Weltec2189a62009-07-23 18:56:43 +02001910 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08001911 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltec2189a62009-07-23 18:56:43 +02001912 if (trans->lchan)
1913 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08001914}
1915
1916static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1917
Harald Welte59b04682009-06-10 05:40:52 +08001918/* call-back from paging the B-end of the connection */
1919static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
1920 struct msgb *msg, void *_lchan, void *param)
1921{
1922 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08001923 struct gsm_subscriber *subscr = param;
1924 struct gsm_trans *transt, *tmp;
1925 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02001926
Harald Welte59b04682009-06-10 05:40:52 +08001927 if (hooknum != GSM_HOOK_RR_PAGING)
1928 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08001929
1930 if (!subscr)
1931 return -EINVAL;
1932 net = subscr->net;
1933 if (!net) {
1934 DEBUGP(DCC, "Error Network not set!\n");
1935 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001936 }
1937
Harald Welte03740842009-06-10 23:11:52 +08001938 /* check all tranactions (without lchan) for subscriber */
1939 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1940 if (transt->subscr != subscr || transt->lchan)
1941 continue;
1942 switch (event) {
1943 case GSM_PAGING_SUCCEEDED:
1944 if (!lchan) // paranoid
1945 break;
1946 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1947 subscr->extension);
1948 /* Assign lchan */
1949 if (!transt->lchan) {
1950 transt->lchan = lchan;
1951 use_lchan(lchan);
1952 }
1953 /* send SETUP request to called party */
Harald Weltec2189a62009-07-23 18:56:43 +02001954 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08001955 break;
1956 case GSM_PAGING_EXPIRED:
1957 DEBUGP(DCC, "Paging subscr %s expired!\n",
1958 subscr->extension);
1959 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02001960 mncc_release_ind(transt->subscr->net, transt,
1961 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001962 GSM48_CAUSE_LOC_PRN_S_LU,
1963 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08001964 transt->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02001965 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08001966 break;
1967 }
1968 }
Harald Welte59b04682009-06-10 05:40:52 +08001969 return 0;
1970}
1971
Harald Welte3c062072009-07-28 18:25:29 +02001972/* some other part of the code sends us a signal */
1973static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
1974 void *handler_data, void *signal_data)
1975{
1976 struct gsm_lchan *lchan = signal_data;
1977 struct gsm_bts_trx_ts *ts;
1978 int rc;
1979
1980 if (subsys != SS_ABISIP)
1981 return 0;
1982
1983 /* in case we use direct BTS-to-BTS RTP */
1984 if (ipacc_rtp_direct)
1985 return 0;
1986
1987 ts = lchan->ts;
1988
1989 switch (signal) {
1990 case S_ABISIP_BIND_ACK:
1991 /* the BTS has successfully bound a TCH to a local ip/port,
1992 * which means we can connect our UDP socket to it */
1993 if (ts->abis_ip.rtp_socket) {
1994 rtp_socket_free(ts->abis_ip.rtp_socket);
1995 ts->abis_ip.rtp_socket = NULL;
1996 }
1997
1998 ts->abis_ip.rtp_socket = rtp_socket_create();
1999 if (!ts->abis_ip.rtp_socket)
2000 goto out_err;
2001
2002 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2003 ts->abis_ip.bound_ip,
2004 ts->abis_ip.bound_port);
2005 if (rc < 0)
2006 goto out_err;
2007 break;
2008 case S_ABISIP_DISC_IND:
2009 /* the BTS tells us a RTP stream has been disconnected */
2010 if (ts->abis_ip.rtp_socket) {
2011 rtp_socket_free(ts->abis_ip.rtp_socket);
2012 ts->abis_ip.rtp_socket = NULL;
2013 }
2014 break;
2015 }
2016
2017 return 0;
2018out_err:
2019 /* FIXME: do something */
2020 return 0;
2021}
2022
2023/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2024static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2025{
2026 struct gsm_bts_trx_ts *ts = lchan->ts;
2027 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2028 int rc;
2029
2030 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2031 ntohs(rs->rtp.sin_local.sin_port),
2032 ts->abis_ip.conn_id,
2033 /* FIXME: use RTP payload of bound socket, not BTS*/
2034 ts->abis_ip.rtp_payload2);
2035
2036 return rc;
2037}
2038
Harald Welte59b04682009-06-10 05:40:52 +08002039/* map two ipaccess RTP streams onto each other */
2040static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2041{
2042 struct gsm_bts *bts = lchan->ts->trx->bts;
2043 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2044 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002045 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002046
2047 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2048 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2049 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2050
2051 if (bts->type != remote_bts->type) {
2052 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2053 return -EINVAL;
2054 }
2055
2056 switch (bts->type) {
2057 case GSM_BTS_TYPE_NANOBTS_900:
2058 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002059 if (!ipacc_rtp_direct) {
2060 /* connect the TCH's to our RTP proxy */
2061 rc = ipacc_connect_proxy_bind(lchan);
2062 if (rc < 0)
2063 return rc;
2064 rc = ipacc_connect_proxy_bind(remote_lchan);
2065
2066 /* connect them with each other */
2067 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2068 remote_lchan->ts->abis_ip.rtp_socket);
2069 } else {
2070 /* directly connect TCH RTP streams to each other */
2071 ts = remote_lchan->ts;
2072 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2073 ts->abis_ip.bound_port,
2074 lchan->ts->abis_ip.conn_id,
2075 ts->abis_ip.rtp_payload2);
2076 if (rc < 0)
2077 return rc;
2078 ts = lchan->ts;
2079 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2080 ts->abis_ip.bound_port,
2081 remote_lchan->ts->abis_ip.conn_id,
2082 ts->abis_ip.rtp_payload2);
2083 }
Harald Welte59b04682009-06-10 05:40:52 +08002084 break;
2085 case GSM_BTS_TYPE_BS11:
2086 trau_mux_map_lchan(lchan, remote_lchan);
2087 break;
2088 default:
2089 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002090 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002091 break;
2092 }
2093
2094 return 0;
2095}
2096
Harald Welte03740842009-06-10 23:11:52 +08002097/* bridge channels of two transactions */
2098static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002099{
Harald Weltec2189a62009-07-23 18:56:43 +02002100 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2101 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002102
Harald Welte03740842009-06-10 23:11:52 +08002103 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002104 return -EIO;
2105
Harald Welte03740842009-06-10 23:11:52 +08002106 if (!trans1->lchan || !trans2->lchan)
2107 return -EIO;
2108
2109 /* through-connect channel */
2110 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002111}
2112
Harald Welte03740842009-06-10 23:11:52 +08002113/* enable receive of channels to upqueue */
2114static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2115{
2116 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002117
Harald Welte03740842009-06-10 23:11:52 +08002118 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002119 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002120 if (!trans)
2121 return -EIO;
2122 if (!trans->lchan)
2123 return 0;
2124
2125 // todo IPACCESS
2126 if (enable)
2127 return trau_recv_lchan(trans->lchan, data->callref);
2128 return trau_mux_unmap(NULL, data->callref);
2129}
2130
2131/* send a frame to channel */
2132static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2133{
2134 struct gsm_trans *trans;
2135
2136 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002137 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002138 if (!trans)
2139 return -EIO;
2140 if (!trans->lchan)
2141 return 0;
2142 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2143 trans->lchan->type != GSM_LCHAN_TCH_H)
2144 return 0;
2145
2146 // todo IPACCESS
2147 return trau_send_lchan(trans->lchan,
2148 (struct decoded_trau_frame *)frame->data);
2149}
2150
2151
2152static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2153{
2154 DEBUGP(DCC, "-> STATUS ENQ\n");
2155 return gsm48_cc_tx_status(trans, msg);
2156}
2157
2158static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2159static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2160
2161static void gsm48_cc_timeout(void *arg)
2162{
2163 struct gsm_trans *trans = arg;
2164 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002165 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2166 int mo_location = GSM48_CAUSE_LOC_USER;
2167 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2168 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002169 struct gsm_mncc mo_rel, l4_rel;
2170
2171 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2172 mo_rel.callref = trans->callref;
2173 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2174 l4_rel.callref = trans->callref;
2175
Harald Weltec2189a62009-07-23 18:56:43 +02002176 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002177 case 0x303:
2178 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002179 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002180 break;
2181 case 0x310:
2182 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002183 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002184 break;
2185 case 0x313:
2186 disconnect = 1;
2187 /* unknown, did not find it in the specs */
2188 break;
2189 case 0x301:
2190 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002191 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002192 break;
2193 case 0x308:
Harald Weltec2189a62009-07-23 18:56:43 +02002194 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002195 /* restart T308 a second time */
Harald Weltec2189a62009-07-23 18:56:43 +02002196 gsm48_cc_tx_release(trans, &trans->cc.msg);
2197 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002198 break; /* stay in release state */
2199 }
Harald Weltec2189a62009-07-23 18:56:43 +02002200 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002201 return;
2202// release = 1;
2203// l4_cause = 14;
2204// break;
2205 case 0x306:
2206 release = 1;
Harald Weltec2189a62009-07-23 18:56:43 +02002207 mo_cause = trans->cc.msg.cause.value;
2208 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002209 break;
2210 case 0x323:
2211 disconnect = 1;
2212 break;
2213 default:
2214 release = 1;
2215 }
2216
2217 if (release && trans->callref) {
2218 /* process release towards layer 4 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002219 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002220 l4_location, l4_cause);
2221 trans->callref = 0;
2222 }
2223
2224 if (disconnect && trans->callref) {
2225 /* process disconnect towards layer 4 */
2226 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte0abe5a62009-07-23 19:06:52 +02002227 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002228 }
2229
2230 /* process disconnect towards mobile station */
2231 if (disconnect || release) {
2232 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltec2189a62009-07-23 18:56:43 +02002233 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2234 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2235 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002236 mo_rel.cause.diag_len = 3;
2237
2238 if (disconnect)
2239 gsm48_cc_tx_disconnect(trans, &mo_rel);
2240 if (release)
2241 gsm48_cc_tx_release(trans, &mo_rel);
2242 }
2243
2244}
2245
2246static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2247 int sec, int micro)
2248{
2249 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltec2189a62009-07-23 18:56:43 +02002250 trans->cc.timer.cb = gsm48_cc_timeout;
2251 trans->cc.timer.data = trans;
2252 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2253 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002254}
2255
2256static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2257{
2258 struct gsm48_hdr *gh = msgb_l3(msg);
2259 u_int8_t msg_type = gh->msg_type & 0xbf;
2260 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2261 struct tlv_parsed tp;
2262 struct gsm_mncc setup;
2263
2264 memset(&setup, 0, sizeof(struct gsm_mncc));
2265 setup.callref = trans->callref;
2266 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2267 /* emergency setup is identified by msg_type */
2268 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2269 setup.emergency = 1;
2270
2271 /* use subscriber as calling party number */
2272 if (trans->subscr) {
2273 setup.fields |= MNCC_F_CALLING;
2274 strncpy(setup.calling.number, trans->subscr->extension,
2275 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002276 strncpy(setup.imsi, trans->subscr->imsi,
2277 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002278 }
2279 /* bearer capability */
2280 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2281 setup.fields |= MNCC_F_BEARER_CAP;
2282 decode_bearer_cap(&setup.bearer_cap,
2283 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2284 }
2285 /* facility */
2286 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2287 setup.fields |= MNCC_F_FACILITY;
2288 decode_facility(&setup.facility,
2289 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2290 }
2291 /* called party bcd number */
2292 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2293 setup.fields |= MNCC_F_CALLED;
2294 decode_called(&setup.called,
2295 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2296 }
2297 /* user-user */
2298 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2299 setup.fields |= MNCC_F_USERUSER;
2300 decode_useruser(&setup.useruser,
2301 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2302 }
2303 /* ss-version */
2304 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2305 setup.fields |= MNCC_F_SSVERSION;
2306 decode_ssversion(&setup.ssversion,
2307 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2308 }
2309 /* CLIR suppression */
2310 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2311 setup.clir.sup = 1;
2312 /* CLIR invocation */
2313 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2314 setup.clir.inv = 1;
2315 /* cc cap */
2316 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2317 setup.fields |= MNCC_F_CCCAP;
2318 decode_cccap(&setup.cccap,
2319 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2320 }
2321
Harald Welte03740842009-06-10 23:11:52 +08002322 new_cc_state(trans, GSM_CSTATE_INITIATED);
2323
2324 /* indicate setup to MNCC */
Harald Welte0abe5a62009-07-23 19:06:52 +02002325 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002326
Harald Welteca745e22009-07-29 12:10:35 +02002327 /* MNCC code will modify the channel asynchronously, we should
2328 * ipaccess-bind only after the modification has been made to the
2329 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002330 return 0;
2331}
2332
2333static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002334{
2335 struct msgb *msg = gsm48_msgb_alloc();
2336 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002337 struct gsm_mncc *setup = arg;
Harald Welte165fc332009-07-23 21:36:44 +02002338 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002339
2340 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2341
Harald Welte03740842009-06-10 23:11:52 +08002342 /* transaction id must not be assigned */
2343 if (trans->transaction_id != 0xff) { /* unasssigned */
2344 DEBUGP(DCC, "TX Setup with assigned transaction. "
2345 "This is not allowed!\n");
2346 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002347 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002348 GSM48_CAUSE_LOC_PRN_S_LU,
2349 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002350 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002351 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002352 return rc;
2353 }
2354
2355 /* Get free transaction_id */
Harald Welte165fc332009-07-23 21:36:44 +02002356 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2357 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002358 /* no free transaction ID */
Harald Welte0abe5a62009-07-23 19:06:52 +02002359 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002360 GSM48_CAUSE_LOC_PRN_S_LU,
2361 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002362 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002363 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002364 return rc;
2365 }
Harald Welte165fc332009-07-23 21:36:44 +02002366 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002367
Harald Welte59b04682009-06-10 05:40:52 +08002368 gh->msg_type = GSM48_MT_CC_SETUP;
2369
Harald Welte03740842009-06-10 23:11:52 +08002370 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002371
Harald Welte03740842009-06-10 23:11:52 +08002372 /* bearer capability */
2373 if (setup->fields & MNCC_F_BEARER_CAP)
2374 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2375 /* facility */
2376 if (setup->fields & MNCC_F_FACILITY)
2377 encode_facility(msg, 0, &setup->facility);
2378 /* progress */
2379 if (setup->fields & MNCC_F_PROGRESS)
2380 encode_progress(msg, 0, &setup->progress);
2381 /* calling party BCD number */
2382 if (setup->fields & MNCC_F_CALLING)
2383 encode_calling(msg, &setup->calling);
2384 /* called party BCD number */
2385 if (setup->fields & MNCC_F_CALLED)
2386 encode_called(msg, &setup->called);
2387 /* user-user */
2388 if (setup->fields & MNCC_F_USERUSER)
2389 encode_useruser(msg, 0, &setup->useruser);
2390 /* redirecting party BCD number */
2391 if (setup->fields & MNCC_F_REDIRECTING)
2392 encode_redirecting(msg, &setup->redirecting);
2393 /* signal */
2394 if (setup->fields & MNCC_F_SIGNAL)
2395 encode_signal(msg, setup->signal);
2396
2397 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002398
Harald Welte36fe2e82009-07-23 21:13:03 +02002399 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002400}
2401
Harald Welte03740842009-06-10 23:11:52 +08002402static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2403{
2404 struct gsm48_hdr *gh = msgb_l3(msg);
2405 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2406 struct tlv_parsed tp;
2407 struct gsm_mncc call_conf;
2408
2409 gsm48_stop_cc_timer(trans);
2410 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2411
2412 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2413 call_conf.callref = trans->callref;
2414 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2415#if 0
2416 /* repeat */
2417 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2418 call_conf.repeat = 1;
2419 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2420 call_conf.repeat = 2;
2421#endif
2422 /* bearer capability */
2423 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2424 call_conf.fields |= MNCC_F_BEARER_CAP;
2425 decode_bearer_cap(&call_conf.bearer_cap,
2426 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2427 }
2428 /* cause */
2429 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2430 call_conf.fields |= MNCC_F_CAUSE;
2431 decode_cause(&call_conf.cause,
2432 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2433 }
2434 /* cc cap */
2435 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2436 call_conf.fields |= MNCC_F_CCCAP;
2437 decode_cccap(&call_conf.cccap,
2438 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2439 }
2440
2441 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2442
Harald Welte0abe5a62009-07-23 19:06:52 +02002443 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2444 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002445}
2446
2447static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2448{
2449 struct gsm_mncc *proceeding = arg;
2450 struct msgb *msg = gsm48_msgb_alloc();
2451 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2452
Harald Welte03740842009-06-10 23:11:52 +08002453 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2454
2455 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2456
2457 /* bearer capability */
2458 if (proceeding->fields & MNCC_F_BEARER_CAP)
2459 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2460 /* facility */
2461 if (proceeding->fields & MNCC_F_FACILITY)
2462 encode_facility(msg, 0, &proceeding->facility);
2463 /* progress */
2464 if (proceeding->fields & MNCC_F_PROGRESS)
2465 encode_progress(msg, 0, &proceeding->progress);
2466
Harald Welte36fe2e82009-07-23 21:13:03 +02002467 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002468}
2469
2470static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2471{
2472 struct gsm48_hdr *gh = msgb_l3(msg);
2473 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2474 struct tlv_parsed tp;
2475 struct gsm_mncc alerting;
2476
2477 gsm48_stop_cc_timer(trans);
2478 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2479
2480 memset(&alerting, 0, sizeof(struct gsm_mncc));
2481 alerting.callref = trans->callref;
2482 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2483 /* facility */
2484 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2485 alerting.fields |= MNCC_F_FACILITY;
2486 decode_facility(&alerting.facility,
2487 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2488 }
2489
2490 /* progress */
2491 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2492 alerting.fields |= MNCC_F_PROGRESS;
2493 decode_progress(&alerting.progress,
2494 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2495 }
2496 /* ss-version */
2497 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2498 alerting.fields |= MNCC_F_SSVERSION;
2499 decode_ssversion(&alerting.ssversion,
2500 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2501 }
2502
2503 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2504
Harald Welte0abe5a62009-07-23 19:06:52 +02002505 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2506 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002507}
2508
2509static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2510{
2511 struct gsm_mncc *alerting = arg;
2512 struct msgb *msg = gsm48_msgb_alloc();
2513 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2514
Harald Welte03740842009-06-10 23:11:52 +08002515 gh->msg_type = GSM48_MT_CC_ALERTING;
2516
2517 /* facility */
2518 if (alerting->fields & MNCC_F_FACILITY)
2519 encode_facility(msg, 0, &alerting->facility);
2520 /* progress */
2521 if (alerting->fields & MNCC_F_PROGRESS)
2522 encode_progress(msg, 0, &alerting->progress);
2523 /* user-user */
2524 if (alerting->fields & MNCC_F_USERUSER)
2525 encode_useruser(msg, 0, &alerting->useruser);
2526
2527 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2528
Harald Welte36fe2e82009-07-23 21:13:03 +02002529 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002530}
2531
2532static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2533{
2534 struct gsm_mncc *progress = arg;
2535 struct msgb *msg = gsm48_msgb_alloc();
2536 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2537
Harald Welte03740842009-06-10 23:11:52 +08002538 gh->msg_type = GSM48_MT_CC_PROGRESS;
2539
2540 /* progress */
2541 encode_progress(msg, 1, &progress->progress);
2542 /* user-user */
2543 if (progress->fields & MNCC_F_USERUSER)
2544 encode_useruser(msg, 0, &progress->useruser);
2545
Harald Welte36fe2e82009-07-23 21:13:03 +02002546 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002547}
2548
2549static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2550{
2551 struct gsm_mncc *connect = arg;
2552 struct msgb *msg = gsm48_msgb_alloc();
2553 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2554
Harald Welte03740842009-06-10 23:11:52 +08002555 gh->msg_type = GSM48_MT_CC_CONNECT;
2556
2557 gsm48_stop_cc_timer(trans);
2558 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2559
2560 /* facility */
2561 if (connect->fields & MNCC_F_FACILITY)
2562 encode_facility(msg, 0, &connect->facility);
2563 /* progress */
2564 if (connect->fields & MNCC_F_PROGRESS)
2565 encode_progress(msg, 0, &connect->progress);
2566 /* connected number */
2567 if (connect->fields & MNCC_F_CONNECTED)
2568 encode_connected(msg, &connect->connected);
2569 /* user-user */
2570 if (connect->fields & MNCC_F_USERUSER)
2571 encode_useruser(msg, 0, &connect->useruser);
2572
2573 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2574
Harald Welte36fe2e82009-07-23 21:13:03 +02002575 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002576}
2577
2578static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2579{
2580 struct gsm48_hdr *gh = msgb_l3(msg);
2581 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2582 struct tlv_parsed tp;
2583 struct gsm_mncc connect;
2584
2585 gsm48_stop_cc_timer(trans);
2586
2587 memset(&connect, 0, sizeof(struct gsm_mncc));
2588 connect.callref = trans->callref;
2589 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2590 /* use subscriber as connected party number */
2591 if (trans->subscr) {
2592 connect.fields |= MNCC_F_CONNECTED;
2593 strncpy(connect.connected.number, trans->subscr->extension,
2594 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002595 strncpy(connect.imsi, trans->subscr->imsi,
2596 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002597 }
2598 /* facility */
2599 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2600 connect.fields |= MNCC_F_FACILITY;
2601 decode_facility(&connect.facility,
2602 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2603 }
2604 /* user-user */
2605 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2606 connect.fields |= MNCC_F_USERUSER;
2607 decode_useruser(&connect.useruser,
2608 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2609 }
2610 /* ss-version */
2611 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2612 connect.fields |= MNCC_F_SSVERSION;
2613 decode_ssversion(&connect.ssversion,
2614 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2615 }
2616
2617 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2618
Harald Welte0abe5a62009-07-23 19:06:52 +02002619 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002620}
2621
2622
2623static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2624{
2625 struct gsm_mncc connect_ack;
2626
2627 gsm48_stop_cc_timer(trans);
2628
2629 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2630
2631 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2632 connect_ack.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002633 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002634 &connect_ack);
2635}
2636
2637static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2638{
2639 struct msgb *msg = gsm48_msgb_alloc();
2640 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2641
Harald Welte03740842009-06-10 23:11:52 +08002642 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2643
2644 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2645
Harald Welte36fe2e82009-07-23 21:13:03 +02002646 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002647}
2648
2649static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2650{
2651 struct gsm48_hdr *gh = msgb_l3(msg);
2652 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2653 struct tlv_parsed tp;
2654 struct gsm_mncc disc;
2655
2656 gsm48_stop_cc_timer(trans);
2657
2658 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2659
2660 memset(&disc, 0, sizeof(struct gsm_mncc));
2661 disc.callref = trans->callref;
2662 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2663 /* cause */
2664 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2665 disc.fields |= MNCC_F_CAUSE;
2666 decode_cause(&disc.cause,
2667 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2668 }
2669 /* facility */
2670 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2671 disc.fields |= MNCC_F_FACILITY;
2672 decode_facility(&disc.facility,
2673 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2674 }
2675 /* user-user */
2676 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2677 disc.fields |= MNCC_F_USERUSER;
2678 decode_useruser(&disc.useruser,
2679 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2680 }
2681 /* ss-version */
2682 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2683 disc.fields |= MNCC_F_SSVERSION;
2684 decode_ssversion(&disc.ssversion,
2685 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2686 }
2687
Harald Welte0abe5a62009-07-23 19:06:52 +02002688 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002689
2690}
2691
Harald Weltebbc636a2009-06-11 14:23:20 +08002692static struct gsm_mncc_cause default_cause = {
2693 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2694 .coding = 0,
2695 .rec = 0,
2696 .rec_val = 0,
2697 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2698 .diag_len = 0,
2699 .diag = { 0 },
2700};
Harald Welte03740842009-06-10 23:11:52 +08002701
2702static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2703{
2704 struct gsm_mncc *disc = arg;
2705 struct msgb *msg = gsm48_msgb_alloc();
2706 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2707
Harald Welte03740842009-06-10 23:11:52 +08002708 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2709
2710 gsm48_stop_cc_timer(trans);
2711 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2712
2713 /* cause */
2714 if (disc->fields & MNCC_F_CAUSE)
2715 encode_cause(msg, 1, &disc->cause);
2716 else
2717 encode_cause(msg, 1, &default_cause);
2718
2719 /* facility */
2720 if (disc->fields & MNCC_F_FACILITY)
2721 encode_facility(msg, 0, &disc->facility);
2722 /* progress */
2723 if (disc->fields & MNCC_F_PROGRESS)
2724 encode_progress(msg, 0, &disc->progress);
2725 /* user-user */
2726 if (disc->fields & MNCC_F_USERUSER)
2727 encode_useruser(msg, 0, &disc->useruser);
2728
2729 /* store disconnect cause for T306 expiry */
Harald Weltec2189a62009-07-23 18:56:43 +02002730 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002731
2732 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2733
Harald Welte36fe2e82009-07-23 21:13:03 +02002734 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002735}
2736
2737static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2738{
2739 struct gsm48_hdr *gh = msgb_l3(msg);
2740 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2741 struct tlv_parsed tp;
2742 struct gsm_mncc rel;
2743 int rc;
2744
2745 gsm48_stop_cc_timer(trans);
2746
2747 memset(&rel, 0, sizeof(struct gsm_mncc));
2748 rel.callref = trans->callref;
2749 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2750 /* cause */
2751 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2752 rel.fields |= MNCC_F_CAUSE;
2753 decode_cause(&rel.cause,
2754 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2755 }
2756 /* facility */
2757 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2758 rel.fields |= MNCC_F_FACILITY;
2759 decode_facility(&rel.facility,
2760 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2761 }
2762 /* user-user */
2763 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2764 rel.fields |= MNCC_F_USERUSER;
2765 decode_useruser(&rel.useruser,
2766 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2767 }
2768 /* ss-version */
2769 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2770 rel.fields |= MNCC_F_SSVERSION;
2771 decode_ssversion(&rel.ssversion,
2772 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2773 }
2774
Harald Weltec2189a62009-07-23 18:56:43 +02002775 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002776 /* release collision 5.4.5 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002777 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002778 } else {
Harald Welte0abe5a62009-07-23 19:06:52 +02002779 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002780 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte0abe5a62009-07-23 19:06:52 +02002781 GSM48_MT_CC_RELEASE_COMPL);
2782 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002783 }
2784
2785 new_cc_state(trans, GSM_CSTATE_NULL);
2786
2787 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002788 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002789
2790 return rc;
2791}
2792
2793static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2794{
2795 struct gsm_mncc *rel = arg;
2796 struct msgb *msg = gsm48_msgb_alloc();
2797 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2798
Harald Welte03740842009-06-10 23:11:52 +08002799 gh->msg_type = GSM48_MT_CC_RELEASE;
2800
2801 trans->callref = 0;
2802
2803 gsm48_stop_cc_timer(trans);
2804 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2805
2806 /* cause */
2807 if (rel->fields & MNCC_F_CAUSE)
2808 encode_cause(msg, 0, &rel->cause);
2809 /* facility */
2810 if (rel->fields & MNCC_F_FACILITY)
2811 encode_facility(msg, 0, &rel->facility);
2812 /* user-user */
2813 if (rel->fields & MNCC_F_USERUSER)
2814 encode_useruser(msg, 0, &rel->useruser);
2815
Harald Weltec2189a62009-07-23 18:56:43 +02002816 trans->cc.T308_second = 0;
2817 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002818
Harald Weltec2189a62009-07-23 18:56:43 +02002819 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002820 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2821
Harald Welte36fe2e82009-07-23 21:13:03 +02002822 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002823}
2824
2825static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2826{
2827 struct gsm48_hdr *gh = msgb_l3(msg);
2828 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2829 struct tlv_parsed tp;
2830 struct gsm_mncc rel;
2831 int rc = 0;
2832
2833 gsm48_stop_cc_timer(trans);
2834
2835 memset(&rel, 0, sizeof(struct gsm_mncc));
2836 rel.callref = trans->callref;
2837 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2838 /* cause */
2839 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2840 rel.fields |= MNCC_F_CAUSE;
2841 decode_cause(&rel.cause,
2842 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2843 }
2844 /* facility */
2845 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2846 rel.fields |= MNCC_F_FACILITY;
2847 decode_facility(&rel.facility,
2848 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2849 }
2850 /* user-user */
2851 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2852 rel.fields |= MNCC_F_USERUSER;
2853 decode_useruser(&rel.useruser,
2854 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2855 }
2856 /* ss-version */
2857 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2858 rel.fields |= MNCC_F_SSVERSION;
2859 decode_ssversion(&rel.ssversion,
2860 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2861 }
2862
2863 if (trans->callref) {
Harald Weltec2189a62009-07-23 18:56:43 +02002864 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08002865 case GSM_CSTATE_CALL_PRESENT:
Harald Welte0abe5a62009-07-23 19:06:52 +02002866 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002867 MNCC_REJ_IND, &rel);
2868 break;
2869 case GSM_CSTATE_RELEASE_REQ:
Harald Welte0abe5a62009-07-23 19:06:52 +02002870 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002871 MNCC_REL_CNF, &rel);
2872 break;
2873 default:
Harald Welte0abe5a62009-07-23 19:06:52 +02002874 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002875 MNCC_REL_IND, &rel);
2876 }
2877 }
2878
2879 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002880 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002881
2882 return rc;
2883}
2884
2885static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2886{
2887 struct gsm_mncc *rel = arg;
2888 struct msgb *msg = gsm48_msgb_alloc();
2889 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2890
Harald Welte03740842009-06-10 23:11:52 +08002891 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2892
2893 trans->callref = 0;
2894
2895 gsm48_stop_cc_timer(trans);
2896
2897 /* cause */
2898 if (rel->fields & MNCC_F_CAUSE)
2899 encode_cause(msg, 0, &rel->cause);
2900 /* facility */
2901 if (rel->fields & MNCC_F_FACILITY)
2902 encode_facility(msg, 0, &rel->facility);
2903 /* user-user */
2904 if (rel->fields & MNCC_F_USERUSER)
2905 encode_useruser(msg, 0, &rel->useruser);
2906
Harald Weltec2189a62009-07-23 18:56:43 +02002907 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002908
Harald Welte36fe2e82009-07-23 21:13:03 +02002909 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002910}
2911
2912static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2913{
2914 struct gsm48_hdr *gh = msgb_l3(msg);
2915 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2916 struct tlv_parsed tp;
2917 struct gsm_mncc fac;
2918
2919 memset(&fac, 0, sizeof(struct gsm_mncc));
2920 fac.callref = trans->callref;
2921 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2922 /* facility */
2923 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2924 fac.fields |= MNCC_F_FACILITY;
2925 decode_facility(&fac.facility,
2926 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2927 }
2928 /* ss-version */
2929 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2930 fac.fields |= MNCC_F_SSVERSION;
2931 decode_ssversion(&fac.ssversion,
2932 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2933 }
2934
Harald Welte0abe5a62009-07-23 19:06:52 +02002935 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08002936}
2937
2938static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2939{
2940 struct gsm_mncc *fac = arg;
2941 struct msgb *msg = gsm48_msgb_alloc();
2942 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2943
Harald Welte03740842009-06-10 23:11:52 +08002944 gh->msg_type = GSM48_MT_CC_FACILITY;
2945
2946 /* facility */
2947 encode_facility(msg, 1, &fac->facility);
2948
Harald Welte36fe2e82009-07-23 21:13:03 +02002949 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002950}
2951
2952static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2953{
2954 struct gsm_mncc hold;
2955
2956 memset(&hold, 0, sizeof(struct gsm_mncc));
2957 hold.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002958 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08002959}
2960
2961static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2962{
2963 struct msgb *msg = gsm48_msgb_alloc();
2964 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2965
Harald Welte03740842009-06-10 23:11:52 +08002966 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2967
Harald Welte36fe2e82009-07-23 21:13:03 +02002968 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002969}
2970
2971static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2972{
2973 struct gsm_mncc *hold_rej = arg;
2974 struct msgb *msg = gsm48_msgb_alloc();
2975 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2976
Harald Welte03740842009-06-10 23:11:52 +08002977 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2978
2979 /* cause */
2980 if (hold_rej->fields & MNCC_F_CAUSE)
2981 encode_cause(msg, 1, &hold_rej->cause);
2982 else
2983 encode_cause(msg, 1, &default_cause);
2984
Harald Welte36fe2e82009-07-23 21:13:03 +02002985 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002986}
2987
2988static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2989{
2990 struct gsm_mncc retrieve;
2991
2992 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2993 retrieve.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002994 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2995 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08002996}
2997
2998static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2999{
3000 struct msgb *msg = gsm48_msgb_alloc();
3001 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3002
Harald Welte03740842009-06-10 23:11:52 +08003003 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3004
Harald Welte36fe2e82009-07-23 21:13:03 +02003005 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003006}
3007
3008static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3009{
3010 struct gsm_mncc *retrieve_rej = arg;
3011 struct msgb *msg = gsm48_msgb_alloc();
3012 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3013
Harald Welte03740842009-06-10 23:11:52 +08003014 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3015
3016 /* cause */
3017 if (retrieve_rej->fields & MNCC_F_CAUSE)
3018 encode_cause(msg, 1, &retrieve_rej->cause);
3019 else
3020 encode_cause(msg, 1, &default_cause);
3021
Harald Welte36fe2e82009-07-23 21:13:03 +02003022 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003023}
3024
3025static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3026{
3027 struct gsm48_hdr *gh = msgb_l3(msg);
3028 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3029 struct tlv_parsed tp;
3030 struct gsm_mncc dtmf;
3031
3032 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3033 dtmf.callref = trans->callref;
3034 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3035 /* keypad facility */
3036 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3037 dtmf.fields |= MNCC_F_KEYPAD;
3038 decode_keypad(&dtmf.keypad,
3039 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3040 }
3041
Harald Welte0abe5a62009-07-23 19:06:52 +02003042 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003043}
3044
3045static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3046{
3047 struct gsm_mncc *dtmf = arg;
3048 struct msgb *msg = gsm48_msgb_alloc();
3049 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3050
Harald Welte03740842009-06-10 23:11:52 +08003051 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3052
3053 /* keypad */
3054 if (dtmf->fields & MNCC_F_KEYPAD)
3055 encode_keypad(msg, dtmf->keypad);
3056
Harald Welte36fe2e82009-07-23 21:13:03 +02003057 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003058}
3059
3060static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3061{
3062 struct gsm_mncc *dtmf = arg;
3063 struct msgb *msg = gsm48_msgb_alloc();
3064 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3065
Harald Welte03740842009-06-10 23:11:52 +08003066 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3067
3068 /* cause */
3069 if (dtmf->fields & MNCC_F_CAUSE)
3070 encode_cause(msg, 1, &dtmf->cause);
3071 else
3072 encode_cause(msg, 1, &default_cause);
3073
Harald Welte36fe2e82009-07-23 21:13:03 +02003074 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003075}
3076
3077static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3078{
3079 struct msgb *msg = gsm48_msgb_alloc();
3080 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3081
Harald Welte03740842009-06-10 23:11:52 +08003082 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3083
Harald Welte36fe2e82009-07-23 21:13:03 +02003084 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003085}
3086
3087static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3088{
3089 struct gsm_mncc dtmf;
3090
3091 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3092 dtmf.callref = trans->callref;
3093
Harald Welte0abe5a62009-07-23 19:06:52 +02003094 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003095}
3096
3097static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3098{
3099 struct gsm48_hdr *gh = msgb_l3(msg);
3100 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3101 struct tlv_parsed tp;
3102 struct gsm_mncc modify;
3103
3104 memset(&modify, 0, sizeof(struct gsm_mncc));
3105 modify.callref = trans->callref;
3106 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3107 /* bearer capability */
3108 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3109 modify.fields |= MNCC_F_BEARER_CAP;
3110 decode_bearer_cap(&modify.bearer_cap,
3111 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3112 }
3113
3114 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3115
Harald Welte0abe5a62009-07-23 19:06:52 +02003116 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003117}
3118
3119static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3120{
3121 struct gsm_mncc *modify = arg;
3122 struct msgb *msg = gsm48_msgb_alloc();
3123 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3124
Harald Welte03740842009-06-10 23:11:52 +08003125 gh->msg_type = GSM48_MT_CC_MODIFY;
3126
3127 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3128
3129 /* bearer capability */
3130 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3131
3132 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3133
Harald Welte36fe2e82009-07-23 21:13:03 +02003134 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003135}
3136
3137static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3138{
3139 struct gsm48_hdr *gh = msgb_l3(msg);
3140 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3141 struct tlv_parsed tp;
3142 struct gsm_mncc modify;
3143
3144 gsm48_stop_cc_timer(trans);
3145
3146 memset(&modify, 0, sizeof(struct gsm_mncc));
3147 modify.callref = trans->callref;
3148 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3149 /* bearer capability */
3150 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3151 modify.fields |= MNCC_F_BEARER_CAP;
3152 decode_bearer_cap(&modify.bearer_cap,
3153 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3154 }
3155
3156 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3157
Harald Welte0abe5a62009-07-23 19:06:52 +02003158 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003159}
3160
3161static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3162{
3163 struct gsm_mncc *modify = arg;
3164 struct msgb *msg = gsm48_msgb_alloc();
3165 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3166
Harald Welte03740842009-06-10 23:11:52 +08003167 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3168
3169 /* bearer capability */
3170 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3171
3172 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3173
Harald Welte36fe2e82009-07-23 21:13:03 +02003174 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003175}
3176
3177static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3178{
3179 struct gsm48_hdr *gh = msgb_l3(msg);
3180 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3181 struct tlv_parsed tp;
3182 struct gsm_mncc modify;
3183
3184 gsm48_stop_cc_timer(trans);
3185
3186 memset(&modify, 0, sizeof(struct gsm_mncc));
3187 modify.callref = trans->callref;
3188 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3189 /* bearer capability */
3190 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3191 modify.fields |= GSM48_IE_BEARER_CAP;
3192 decode_bearer_cap(&modify.bearer_cap,
3193 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3194 }
3195 /* cause */
3196 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3197 modify.fields |= MNCC_F_CAUSE;
3198 decode_cause(&modify.cause,
3199 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3200 }
3201
3202 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3203
Harald Welte0abe5a62009-07-23 19:06:52 +02003204 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003205}
3206
3207static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3208{
3209 struct gsm_mncc *modify = arg;
3210 struct msgb *msg = gsm48_msgb_alloc();
3211 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3212
Harald Welte03740842009-06-10 23:11:52 +08003213 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3214
3215 /* bearer capability */
3216 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3217 /* cause */
3218 encode_cause(msg, 1, &modify->cause);
3219
3220 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3221
Harald Welte36fe2e82009-07-23 21:13:03 +02003222 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003223}
3224
3225static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3226{
3227 struct gsm_mncc *notify = arg;
3228 struct msgb *msg = gsm48_msgb_alloc();
3229 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3230
Harald Welte03740842009-06-10 23:11:52 +08003231 gh->msg_type = GSM48_MT_CC_NOTIFY;
3232
3233 /* notify */
3234 encode_notify(msg, notify->notify);
3235
Harald Welte36fe2e82009-07-23 21:13:03 +02003236 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003237}
3238
3239static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3240{
3241 struct gsm48_hdr *gh = msgb_l3(msg);
3242 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3243// struct tlv_parsed tp;
3244 struct gsm_mncc notify;
3245
3246 memset(&notify, 0, sizeof(struct gsm_mncc));
3247 notify.callref = trans->callref;
3248// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3249 if (payload_len >= 1)
3250 decode_notify(&notify.notify, gh->data);
3251
Harald Welte0abe5a62009-07-23 19:06:52 +02003252 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003253}
3254
3255static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3256{
3257 struct gsm_mncc *user = arg;
3258 struct msgb *msg = gsm48_msgb_alloc();
3259 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3260
Harald Welte03740842009-06-10 23:11:52 +08003261 gh->msg_type = GSM48_MT_CC_USER_INFO;
3262
3263 /* user-user */
3264 if (user->fields & MNCC_F_USERUSER)
3265 encode_useruser(msg, 1, &user->useruser);
3266 /* more data */
3267 if (user->more)
3268 encode_more(msg);
3269
Harald Welte36fe2e82009-07-23 21:13:03 +02003270 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003271}
3272
3273static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3274{
3275 struct gsm48_hdr *gh = msgb_l3(msg);
3276 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3277 struct tlv_parsed tp;
3278 struct gsm_mncc user;
3279
3280 memset(&user, 0, sizeof(struct gsm_mncc));
3281 user.callref = trans->callref;
3282 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3283 /* user-user */
3284 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3285 user.fields |= MNCC_F_USERUSER;
3286 decode_useruser(&user.useruser,
3287 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3288 }
3289 /* more data */
3290 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3291 user.more = 1;
3292
Harald Welte0abe5a62009-07-23 19:06:52 +02003293 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003294}
3295
3296static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3297{
3298 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003299 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003300
Harald Welteca745e22009-07-29 12:10:35 +02003301 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3302 if (rc < 0)
3303 return rc;
3304
3305 /* FIXME: we not only need to do this after mode modify, but
3306 * also after channel activation */
3307 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3308 mode->lchan_mode != GSM48_CMODE_SIGN)
3309 rc = rsl_ipacc_bind(trans->lchan);
3310
3311 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003312}
3313
3314static struct downstate {
3315 u_int32_t states;
3316 int type;
3317 int (*rout) (struct gsm_trans *trans, void *arg);
3318} downstatelist[] = {
3319 /* mobile originating call establishment */
3320 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3321 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3322 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3323 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3324 {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 */
3325 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3326 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3327 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3328 /* mobile terminating call establishment */
3329 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3330 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3331 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3332 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3333 /* signalling during call */
3334 {SBIT(GSM_CSTATE_ACTIVE),
3335 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3336 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3337 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3338 {ALL_STATES,
3339 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3340 {ALL_STATES,
3341 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3342 {ALL_STATES,
3343 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3344 {SBIT(GSM_CSTATE_ACTIVE),
3345 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3346 {SBIT(GSM_CSTATE_ACTIVE),
3347 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3348 {SBIT(GSM_CSTATE_ACTIVE),
3349 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3350 {SBIT(GSM_CSTATE_ACTIVE),
3351 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3352 {SBIT(GSM_CSTATE_ACTIVE),
3353 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3354 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3355 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3356 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3357 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3358 {SBIT(GSM_CSTATE_ACTIVE),
3359 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3360 /* clearing */
3361 {SBIT(GSM_CSTATE_INITIATED),
3362 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3363 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3364 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3365 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3366 MNCC_REL_REQ, gsm48_cc_tx_release},
3367 /* special */
3368 {ALL_STATES,
3369 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3370};
3371
3372#define DOWNSLLEN \
3373 (sizeof(downstatelist) / sizeof(struct downstate))
3374
3375
3376int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3377{
3378 int i, j, k, l, rc = 0;
3379 struct gsm_trans *trans = NULL, *transt;
3380 struct gsm_subscriber *subscr;
3381 struct gsm_lchan *lchan = NULL, *lchant;
3382 struct gsm_bts *bts = NULL;
3383 struct gsm_bts_trx *trx;
3384 struct gsm_bts_trx_ts *ts;
3385 struct gsm_mncc *data = arg, rel;
3386
3387 /* handle special messages */
3388 switch(msg_type) {
3389 case MNCC_BRIDGE:
3390 return tch_bridge(net, arg);
3391 case MNCC_FRAME_DROP:
3392 return tch_recv(net, arg, 0);
3393 case MNCC_FRAME_RECV:
3394 return tch_recv(net, arg, 1);
3395 case GSM_TRAU_FRAME:
3396 return tch_frame(net, arg);
3397 }
3398
3399 memset(&rel, 0, sizeof(struct gsm_mncc));
3400 rel.callref = data->callref;
3401
3402 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02003403 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003404
3405 /* Callref unknown */
3406 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003407 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003408 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3409 "Received '%s' from MNCC with "
3410 "unknown callref %d\n", data->called.number,
3411 get_mncc_name(msg_type), data->callref);
3412 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003413 return mncc_release_ind(net, NULL, data->callref,
3414 GSM48_CAUSE_LOC_PRN_S_LU,
3415 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003416 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003417 if (!data->called.number[0] && !data->imsi[0]) {
3418 DEBUGP(DCC, "(bts - trx - ts - ti) "
3419 "Received '%s' from MNCC with "
3420 "no number or IMSI\n", get_mncc_name(msg_type));
3421 /* Invalid number */
3422 return mncc_release_ind(net, NULL, data->callref,
3423 GSM48_CAUSE_LOC_PRN_S_LU,
3424 GSM48_CC_CAUSE_INV_NR_FORMAT);
3425 }
Harald Welte03740842009-06-10 23:11:52 +08003426 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003427 if (data->called.number[0])
Harald Welte75350412009-07-23 18:46:00 +02003428 subscr = subscr_get_by_extension(net,
3429 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003430 else
Harald Welte75350412009-07-23 18:46:00 +02003431 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003432 /* If subscriber is not found */
3433 if (!subscr) {
3434 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3435 "Received '%s' from MNCC with "
3436 "unknown subscriber %s\n", data->called.number,
3437 get_mncc_name(msg_type), data->called.number);
3438 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003439 return mncc_release_ind(net, NULL, data->callref,
3440 GSM48_CAUSE_LOC_PRN_S_LU,
3441 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003442 }
3443 /* If subscriber is not "attached" */
3444 if (!subscr->lac) {
3445 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3446 "Received '%s' from MNCC with "
3447 "detached subscriber %s\n", data->called.number,
3448 get_mncc_name(msg_type), data->called.number);
3449 subscr_put(subscr);
3450 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003451 return mncc_release_ind(net, NULL, data->callref,
3452 GSM48_CAUSE_LOC_PRN_S_LU,
3453 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003454 }
3455 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003456 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3457 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003458 DEBUGP(DCC, "No memory for trans.\n");
3459 subscr_put(subscr);
3460 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003461 mncc_release_ind(net, NULL, data->callref,
3462 GSM48_CAUSE_LOC_PRN_S_LU,
3463 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003464 return -ENOMEM;
3465 }
Harald Welte03740842009-06-10 23:11:52 +08003466 /* Find lchan */
3467 for (i = 0; i < net->num_bts; i++) {
Harald Weltee712a5f2009-06-21 16:17:15 +02003468 bts = gsm_bts_num(net, i);
Harald Welte03740842009-06-10 23:11:52 +08003469 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee712a5f2009-06-21 16:17:15 +02003470 trx = gsm_bts_trx_num(bts, j);
Harald Welte03740842009-06-10 23:11:52 +08003471 for (k = 0; k < TRX_NR_TS; k++) {
3472 ts = &trx->ts[k];
3473 for (l = 0; l < TS_MAX_LCHAN; l++) {
3474 lchant = &ts->lchan[l];
3475 if (lchant->subscr == subscr) {
3476 lchan = lchant;
3477 break;
3478 }
3479 }
3480 }
3481 }
3482 }
3483
3484 /* If subscriber has no lchan */
3485 if (!lchan) {
3486 /* find transaction with this subscriber already paging */
3487 llist_for_each_entry(transt, &net->trans_list, entry) {
3488 /* Transaction of our lchan? */
3489 if (transt == trans ||
3490 transt->subscr != subscr)
3491 continue;
3492 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3493 "Received '%s' from MNCC with "
3494 "unallocated channel, paging already "
3495 "started.\n", bts->nr,
3496 data->called.number,
3497 get_mncc_name(msg_type));
3498 return 0;
3499 }
3500 /* store setup informations until paging was successfull */
Harald Weltec2189a62009-07-23 18:56:43 +02003501 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte2a3a81b2009-08-01 19:31:47 +02003502 /* Trigger paging */
3503 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3504 setup_trig_pag_evt, subscr);
Harald Welte03740842009-06-10 23:11:52 +08003505 return 0;
3506 }
3507 /* Assign lchan */
3508 trans->lchan = lchan;
3509 use_lchan(lchan);
3510 }
3511 lchan = trans->lchan;
3512
3513 /* if paging did not respond yet */
3514 if (!lchan) {
3515 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3516 "Received '%s' from MNCC in paging state\n",
3517 (trans->subscr)?(trans->subscr->extension):"-",
3518 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003519 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3520 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003521 if (msg_type == MNCC_REL_REQ)
3522 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3523 else
3524 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3525 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003526 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003527 return rc;
3528 }
3529
3530 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3531 "Received '%s' from MNCC in state %d (%s)\n",
3532 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3533 trans->transaction_id,
3534 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003535 get_mncc_name(msg_type), trans->cc.state,
3536 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003537
3538 /* Find function for current state and message */
3539 for (i = 0; i < DOWNSLLEN; i++)
3540 if ((msg_type == downstatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003541 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003542 break;
3543 if (i == DOWNSLLEN) {
3544 DEBUGP(DCC, "Message unhandled at this state.\n");
3545 return 0;
3546 }
3547
3548 rc = downstatelist[i].rout(trans, arg);
3549
3550 return rc;
3551}
3552
3553
3554static struct datastate {
3555 u_int32_t states;
3556 int type;
3557 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3558} datastatelist[] = {
3559 /* mobile originating call establishment */
3560 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3561 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3562 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3563 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3564 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3565 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3566 /* mobile terminating call establishment */
3567 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3568 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3569 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3570 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3571 {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 */
3572 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3573 /* signalling during call */
3574 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3575 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3576 {SBIT(GSM_CSTATE_ACTIVE),
3577 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3578 {ALL_STATES,
3579 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3580 {ALL_STATES,
3581 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3582 {ALL_STATES,
3583 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3584 {SBIT(GSM_CSTATE_ACTIVE),
3585 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3586 {SBIT(GSM_CSTATE_ACTIVE),
3587 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3588 {SBIT(GSM_CSTATE_ACTIVE),
3589 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3590 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3591 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3592 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3593 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3594 {SBIT(GSM_CSTATE_ACTIVE),
3595 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3596 /* clearing */
3597 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3598 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3599 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3600 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3601 {ALL_STATES, /* 5.4.3.4 */
3602 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3603};
3604
3605#define DATASLLEN \
3606 (sizeof(datastatelist) / sizeof(struct datastate))
3607
Harald Welte59b04682009-06-10 05:40:52 +08003608static int gsm0408_rcv_cc(struct msgb *msg)
3609{
3610 struct gsm48_hdr *gh = msgb_l3(msg);
3611 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003612 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003613 struct gsm_lchan *lchan = msg->lchan;
Harald Weltec2189a62009-07-23 18:56:43 +02003614 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003615 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003616
Harald Welte03740842009-06-10 23:11:52 +08003617 if (msg_type & 0x80) {
3618 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3619 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003620 }
Harald Welte03740842009-06-10 23:11:52 +08003621
3622 /* Find transaction */
Harald Welte0d824162009-07-23 21:58:40 +02003623 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltec2189a62009-07-23 18:56:43 +02003624
Harald Welte4861c822009-07-23 21:21:14 +02003625 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003626 "Received '%s' from MS in state %d (%s)\n",
3627 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3628 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003629 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3630 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003631
3632 /* Create transaction */
3633 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003634 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003635 "creating new trans.\n", transaction_id);
3636 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003637 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3638 transaction_id, new_callref++);
3639 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003640 DEBUGP(DCC, "No memory for trans.\n");
3641 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003642 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003643 GSM48_MT_CC_RELEASE_COMPL);
3644 return -ENOMEM;
3645 }
Harald Welte03740842009-06-10 23:11:52 +08003646 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003647 trans->lchan = lchan;
3648 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003649 }
3650
3651 /* find function for current state and message */
3652 for (i = 0; i < DATASLLEN; i++)
3653 if ((msg_type == datastatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003654 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003655 break;
3656 if (i == DATASLLEN) {
3657 DEBUGP(DCC, "Message unhandled at this state.\n");
3658 return 0;
3659 }
3660
3661 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003662
3663 return rc;
3664}
3665
3666/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3667int gsm0408_rcvmsg(struct msgb *msg)
3668{
3669 struct gsm48_hdr *gh = msgb_l3(msg);
3670 u_int8_t pdisc = gh->proto_discr & 0x0f;
3671 int rc = 0;
3672
3673 switch (pdisc) {
3674 case GSM48_PDISC_CC:
3675 rc = gsm0408_rcv_cc(msg);
3676 break;
3677 case GSM48_PDISC_MM:
3678 rc = gsm0408_rcv_mm(msg);
3679 break;
3680 case GSM48_PDISC_RR:
3681 rc = gsm0408_rcv_rr(msg);
3682 break;
3683 case GSM48_PDISC_SMS:
3684 rc = gsm0411_rcv_sms(msg);
3685 break;
3686 case GSM48_PDISC_MM_GPRS:
3687 case GSM48_PDISC_SM_GPRS:
3688 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3689 pdisc);
3690 break;
3691 default:
3692 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3693 pdisc);
3694 break;
3695 }
3696
3697 return rc;
3698}
3699
Harald Welte59b04682009-06-10 05:40:52 +08003700/* Section 9.1.8 / Table 9.9 */
3701struct chreq {
3702 u_int8_t val;
3703 u_int8_t mask;
3704 enum chreq_type type;
3705};
3706
3707/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3708static const struct chreq chreq_type_neci1[] = {
3709 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3710 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3711 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3712 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3713 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3714 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3715 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3716 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3717 { 0x10, 0xf0, CHREQ_T_SDCCH },
3718 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3719 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3720 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3721};
3722
3723/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3724static const struct chreq chreq_type_neci0[] = {
3725 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3726 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3727 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3728 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3729 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3730 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3731 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3732 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3733};
3734
3735static const enum gsm_chan_t ctype_by_chreq[] = {
3736 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3737 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3738 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3739 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3740 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3741 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3742 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3743 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3744 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3745 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3746 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3747 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3748};
3749
3750static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3751 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3752 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3753 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3754 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3755 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3756 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3757 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3758 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3759 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3760 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3761 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3762 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3763};
3764
3765enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3766{
3767 int i;
3768 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3769
3770 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3771 const struct chreq *chr = &chreq_type_neci0[i];
3772 if ((ra & chr->mask) == chr->val)
3773 return ctype_by_chreq[chr->type];
3774 }
3775 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3776 return GSM_LCHAN_SDCCH;
3777}
3778
3779enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3780{
3781 int i;
3782 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3783
3784 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3785 const struct chreq *chr = &chreq_type_neci0[i];
3786 if ((ra & chr->mask) == chr->val)
3787 return reason_by_chreq[chr->type];
3788 }
3789 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3790 return GSM_CHREQ_REASON_OTHER;
3791}
Harald Welte03740842009-06-10 23:11:52 +08003792
3793/* dequeue messages to layer 4 */
3794int bsc_upqueue(struct gsm_network *net)
3795{
3796 struct gsm_mncc *mncc;
3797 struct msgb *msg;
3798 int work = 0;
3799
3800 if (net)
3801 while ((msg = msgb_dequeue(&net->upqueue))) {
3802 mncc = (struct gsm_mncc *)msg->data;
3803 if (net->mncc_recv)
3804 net->mncc_recv(net, mncc->msg_type, mncc);
3805 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003806 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003807 }
3808
3809 return work;
3810}
Harald Weltec2189a62009-07-23 18:56:43 +02003811
Harald Welte3c062072009-07-28 18:25:29 +02003812/*
3813 * This will be ran by the linker when loading the DSO. We use it to
3814 * do system initialization, e.g. registration of signal handlers.
3815 */
3816static __attribute__((constructor)) void on_dso_load_0408(void)
3817{
3818 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3819 "loc_updating_oper");
3820 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3821 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3822}