blob: 0523538a8f597b03a7cc91a7a5f7a646dd908f90 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <time.h>
31#include <netinet/in.h>
32
33#include <openbsc/db.h>
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
42#include <openbsc/chan_alloc.h>
43#include <openbsc/paging.h>
44#include <openbsc/signal.h>
45#include <openbsc/trau_frame.h>
46#include <openbsc/trau_mux.h>
Harald Welte3c062072009-07-28 18:25:29 +020047#include <openbsc/rtp_proxy.h>
Harald Weltea8379772009-06-20 22:36:41 +020048#include <openbsc/talloc.h>
Harald Weltec2189a62009-07-23 18:56:43 +020049#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080050
51#define GSM48_ALLOC_SIZE 1024
52#define GSM48_ALLOC_HEADROOM 128
53
Harald Welteb8a18b52009-06-10 12:08:54 +080054#define GSM_MAX_FACILITY 128
55#define GSM_MAX_SSVERSION 128
56#define GSM_MAX_USERUSER 128
57
Harald Weltea8379772009-06-20 22:36:41 +020058static void *tall_locop_ctx;
Harald Weltea8379772009-06-20 22:36:41 +020059
Harald Welte3c062072009-07-28 18:25:29 +020060/* should ip.access BTS use direct RTP streams between each other (1),
61 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
62int ipacc_rtp_direct = 1;
63
Harald Welte59b04682009-06-10 05:40:52 +080064static const struct tlv_definition rsl_att_tlvdef = {
65 .def = {
66 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
67 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
69 [GSM48_IE_UTC] = { TLV_TYPE_TV },
70 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
71 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
72
73 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
74 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
75 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
76 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
77 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
78 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
79 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welteb8a18b52009-06-10 12:08:54 +080080 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte59b04682009-06-10 05:40:52 +080081 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
82 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welteb8a18b52009-06-10 12:08:54 +080083 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
84 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte59b04682009-06-10 05:40:52 +080085 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
86 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
89 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
91 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
92 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
94 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
95 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
96 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
98 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welteb8a18b52009-06-10 12:08:54 +080099 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
100 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte59b04682009-06-10 05:40:52 +0800101 /* FIXME: more elements */
102 },
103};
104
105static const char *rr_cause_names[] = {
106 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
107 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
108 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
109 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
110 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
111 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
112 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
113 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
114 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
115 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
116 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
117 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
118 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
119 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
120 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
121 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
122 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
123};
124
Harald Welte03740842009-06-10 23:11:52 +0800125static const char *cc_state_names[] = {
126 "NULL",
127 "INITIATED",
128 "illegal state 2",
129 "MO_CALL_PROC",
130 "CALL_DELIVERED",
131 "illegal state 5",
132 "CALL_PRESENT",
133 "CALL_RECEIVED",
134 "CONNECT_REQUEST",
135 "MO_TERM_CALL_CONF",
136 "ACTIVE",
137 "DISCONNECT_REQ",
138 "DISCONNECT_IND",
139 "illegal state 13",
140 "illegal state 14",
141 "illegal state 15",
142 "illegal state 16",
143 "illegal state 17",
144 "illegal state 18",
145 "RELEASE_REQ",
146 "illegal state 20",
147 "illegal state 21",
148 "illegal state 22",
149 "illegal state 23",
150 "illegal state 24",
151 "illegal state 25",
152 "MO_ORIG_MODIFY",
153 "MO_TERM_MODIFY",
154 "CONNECT_IND",
155 "illegal state 29",
156 "illegal state 30",
157 "illegal state 31",
158};
159
160static const char *cc_msg_names[] = {
161 "unknown 0x00",
162 "ALERTING",
163 "CALL_PROC",
164 "PROGRESS",
165 "ESTAB",
166 "SETUP",
167 "ESTAB_CONF",
168 "CONNECT",
169 "CALL_CONF",
170 "START_CC",
171 "unknown 0x0a",
172 "RECALL",
173 "unknown 0x0c",
174 "unknown 0x0d",
175 "EMERG_SETUP",
176 "CONNECT_ACK",
177 "USER_INFO",
178 "unknown 0x11",
179 "unknown 0x12",
180 "MODIFY_REJECT",
181 "unknown 0x14",
182 "unknown 0x15",
183 "unknown 0x16",
184 "MODIFY",
185 "HOLD",
186 "HOLD_ACK",
187 "HOLD_REJ",
188 "unknown 0x1b",
189 "RETR",
190 "RETR_ACK",
191 "RETR_REJ",
192 "MODIFY_COMPL",
193 "unknown 0x20",
194 "unknown 0x21",
195 "unknown 0x22",
196 "unknown 0x23",
197 "unknown 0x24",
198 "DISCONNECT",
199 "unknown 0x26",
200 "unknown 0x27",
201 "unknown 0x28",
202 "unknown 0x29",
203 "RELEASE_COMPL",
204 "unknown 0x2b",
205 "unknown 0x2c",
206 "RELEASE",
207 "unknown 0x2e",
208 "unknown 0x2f",
209 "unknown 0x30",
210 "STOP_DTMF",
211 "STOP_DTMF_ACK",
212 "unknown 0x33",
213 "STATUS_ENQ",
214 "START_DTMF",
215 "START_DTMF_ACK",
216 "START_DTMF_REJ",
217 "unknown 0x38",
218 "CONG_CTRL",
219 "FACILITY",
220 "unknown 0x3b",
221 "STATUS",
222 "unknown 0x3c",
223 "NOTIFY",
224 "unknown 0x3f",
225};
226
Harald Welte59b04682009-06-10 05:40:52 +0800227static char strbuf[64];
228
229static const char *rr_cause_name(u_int8_t cause)
230{
231 if (cause < ARRAY_SIZE(rr_cause_names) &&
232 rr_cause_names[cause])
233 return rr_cause_names[cause];
234
235 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
236 return strbuf;
237}
238
239static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
240 int len)
241{
242 memset(rep, 0, sizeof(*rep));
243
244 if (data[0] & 0x80)
245 rep->flags |= MEAS_REP_F_BA1;
246 if (data[0] & 0x40)
247 rep->flags |= MEAS_REP_F_DTX;
Harald Welteba6589d2009-07-05 04:05:44 +0200248 if ((data[1] & 0x40) == 0x00)
Harald Welte59b04682009-06-10 05:40:52 +0800249 rep->flags |= MEAS_REP_F_VALID;
250
251 rep->rxlev_full = data[0] & 0x3f;
252 rep->rxlev_sub = data[1] & 0x3f;
253 rep->rxqual_full = (data[3] >> 4) & 0x7;
254 rep->rxqual_sub = (data[3] >> 1) & 0x7;
255 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
256 if (rep->num_cell < 1)
257 return;
258
259 /* an encoding nightmare in perfection */
260
261 rep->cell[0].rxlev = data[4] & 0x3f;
262 rep->cell[0].bcch_freq = data[5] >> 2;
263 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
264 if (rep->num_cell < 2)
265 return;
266
267 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
268 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
269 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
270 if (rep->num_cell < 3)
271 return;
272
273 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
274 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
275 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
276 if (rep->num_cell < 4)
277 return;
278
279 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
280 rep->cell[3].bcch_freq = data[11] & 0x1f;
281 rep->cell[3].bsic = data[12] >> 2;
282 if (rep->num_cell < 5)
283 return;
284
285 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
286 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
287 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
288 if (rep->num_cell < 6)
289 return;
290
291 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
292 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
293 rep->cell[5].bsic = data[16] & 0x3f;
294}
295
296int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
297static int gsm48_tx_simple(struct gsm_lchan *lchan,
298 u_int8_t pdisc, u_int8_t msg_type);
299static void schedule_reject(struct gsm_lchan *lchan);
300
301struct gsm_lai {
302 u_int16_t mcc;
303 u_int16_t mnc;
304 u_int16_t lac;
305};
306
307static int authorize_everonye = 0;
308void gsm0408_allow_everyone(int everyone)
309{
310 printf("Allowing everyone?\n");
311 authorize_everonye = everyone;
312}
313
314static int reject_cause = 0;
315void gsm0408_set_reject_cause(int cause)
316{
317 reject_cause = cause;
318}
319
Harald Welte03740842009-06-10 23:11:52 +0800320static u_int32_t new_callref = 0x80000001;
321
Harald Welte59b04682009-06-10 05:40:52 +0800322static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
323 struct gsm_subscriber *subscriber)
324{
325 if (!subscriber)
326 return 0;
327
328 /*
329 * Do not send accept yet as more information should arrive. Some
330 * phones will not send us the information and we will have to check
331 * what we want to do with that.
332 */
333 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
334 return 0;
335
336 if (authorize_everonye)
337 return 1;
338
339 return subscriber->authorized;
340}
341
342static void release_loc_updating_req(struct gsm_lchan *lchan)
343{
344 if (!lchan->loc_operation)
345 return;
346
347 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Weltea8379772009-06-20 22:36:41 +0200348 talloc_free(lchan->loc_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800349 lchan->loc_operation = 0;
350 put_lchan(lchan);
351}
352
353static void allocate_loc_updating_req(struct gsm_lchan *lchan)
354{
355 use_lchan(lchan);
356 release_loc_updating_req(lchan);
357
Harald Welte857e00d2009-06-26 20:25:23 +0200358 lchan->loc_operation = talloc_zero(tall_locop_ctx,
359 struct gsm_loc_updating_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800360}
361
362static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
363{
364 u_int32_t tmsi;
365
366 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welte5070e942009-08-09 19:07:00 +0200367 int rc;
368
Harald Welte59b04682009-06-10 05:40:52 +0800369 db_subscriber_alloc_tmsi(lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800370 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
371 release_loc_updating_req(lchan);
Harald Welte5070e942009-08-09 19:07:00 +0200372 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
373 /* call subscr_update after putting the loc_upd_acc
374 * in the transmit queue, since S_SUBSCR_ATTACHED might
375 * trigger further action like SMS delivery */
376 subscr_update(lchan->subscr, msg->trx->bts,
377 GSM_SUBSCRIBER_UPDATE_ATTACHED);
378 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800379 }
380
381 return 0;
382}
383
384static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
385 void *handler_data, void *signal_data)
386{
Harald Welte03740842009-06-10 23:11:52 +0800387 struct gsm_trans *trans, *temp;
388
Harald Welte59b04682009-06-10 05:40:52 +0800389 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
390 return 0;
391
392 /*
393 * Cancel any outstanding location updating request
394 * operation taking place on the lchan.
395 */
Harald Welte12560da2009-07-04 09:35:21 +0200396 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Welte1ff81b52009-06-26 20:17:06 +0200397 if (!lchan)
398 return 0;
399
Harald Welte59b04682009-06-10 05:40:52 +0800400 release_loc_updating_req(lchan);
401
Harald Welte03740842009-06-10 23:11:52 +0800402 /* Free all transactions that are associated with the released lchan */
Harald Weltec2189a62009-07-23 18:56:43 +0200403 /* FIXME: this is not neccessarily the right thing to do, we should
404 * only set trans->lchan to NULL and wait for another lchan to be
405 * established to the same MM entity (phone/subscriber) */
Harald Welte03740842009-06-10 23:11:52 +0800406 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
407 if (trans->lchan == lchan)
Harald Weltec2189a62009-07-23 18:56:43 +0200408 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +0800409 }
410
Harald Welte59b04682009-06-10 05:40:52 +0800411 return 0;
412}
413
Harald Welte59b04682009-06-10 05:40:52 +0800414static void to_bcd(u_int8_t *bcd, u_int16_t val)
415{
416 bcd[2] = val % 10;
417 val = val / 10;
418 bcd[1] = val % 10;
419 val = val / 10;
420 bcd[0] = val % 10;
421 val = val / 10;
422}
423
424void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
425 u_int16_t mnc, u_int16_t lac)
426{
427 u_int8_t bcd[3];
428
429 to_bcd(bcd, mcc);
430 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
431 lai48->digits[1] = bcd[2];
432
433 to_bcd(bcd, mnc);
434 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
435#if 0
436 lai48->digits[1] |= bcd[2] << 4;
437 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
438#else
439 lai48->digits[1] |= 0xf << 4;
440 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
441#endif
442
443 lai48->lac = htons(lac);
444}
445
446#define TMSI_LEN 5
447#define MID_TMSI_LEN (TMSI_LEN + 2)
448
449int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
450{
451 u_int32_t *tptr = (u_int32_t *) &buf[3];
452
453 buf[0] = GSM48_IE_MOBILE_ID;
454 buf[1] = TMSI_LEN;
455 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
456 *tptr = htonl(tmsi);
457
458 return 7;
459}
460
461static const char bcd_num_digits[] = {
462 '0', '1', '2', '3', '4', '5', '6', '7',
463 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
464};
465
Harald Welteb8a18b52009-06-10 12:08:54 +0800466/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
467int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
468 int h_len)
Harald Welte59b04682009-06-10 05:40:52 +0800469{
470 u_int8_t in_len = bcd_lv[0];
471 int i;
472
Harald Welteb8a18b52009-06-10 12:08:54 +0800473 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte59b04682009-06-10 05:40:52 +0800474 /* lower nibble */
475 output_len--;
476 if (output_len <= 1)
477 break;
478 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
479
480 /* higher nibble */
481 output_len--;
482 if (output_len <= 1)
483 break;
484 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
485 }
486 if (output_len >= 1)
487 *output++ = '\0';
488
Harald Welteb8a18b52009-06-10 12:08:54 +0800489 return 0;
Harald Welte59b04682009-06-10 05:40:52 +0800490}
491
492/* convert a single ASCII character to call-control BCD */
493static int asc_to_bcd(const char asc)
494{
495 int i;
496
497 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
498 if (bcd_num_digits[i] == asc)
499 return i;
500 }
501 return -EINVAL;
502}
503
Harald Welteb8a18b52009-06-10 12:08:54 +0800504/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte59b04682009-06-10 05:40:52 +0800505int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welteb8a18b52009-06-10 12:08:54 +0800506 int h_len, const char *input)
Harald Welte59b04682009-06-10 05:40:52 +0800507{
508 int in_len = strlen(input);
509 int i;
Harald Welteb8a18b52009-06-10 12:08:54 +0800510 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800511
512 /* two digits per byte, plus type byte */
Harald Welteb8a18b52009-06-10 12:08:54 +0800513 bcd_lv[0] = in_len/2 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800514 if (in_len % 2)
515 bcd_lv[0]++;
516
Harald Welteb8a18b52009-06-10 12:08:54 +0800517 if (bcd_lv[0] > max_len)
518 return -EIO;
Harald Welte59b04682009-06-10 05:40:52 +0800519
520 for (i = 0; i < in_len; i++) {
521 int rc = asc_to_bcd(input[i]);
522 if (rc < 0)
523 return rc;
524 if (i % 2 == 0)
525 *bcd_cur = rc;
526 else
527 *bcd_cur++ |= (rc << 4);
528 }
529 /* append padding nibble in case of odd length */
530 if (i % 2)
531 *bcd_cur++ |= 0xf0;
532
533 /* return how many bytes we used */
534 return (bcd_cur - bcd_lv);
535}
536
Harald Welteb8a18b52009-06-10 12:08:54 +0800537/* decode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800538static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welteb8a18b52009-06-10 12:08:54 +0800539 const u_int8_t *lv)
540{
541 u_int8_t in_len = lv[0];
542 int i, s;
543
544 if (in_len < 1)
545 return -EINVAL;
546
Harald Welte03740842009-06-10 23:11:52 +0800547 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welteb8a18b52009-06-10 12:08:54 +0800548
549 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800550 bcap->transfer = lv[1] & 0x07;
551 bcap->mode = (lv[1] & 0x08) >> 3;
552 bcap->coding = (lv[1] & 0x10) >> 4;
553 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800554
555 i = 1;
556 s = 0;
557 while(!(lv[i] & 0x80)) {
558 i++; /* octet 3a etc */
559 if (in_len < i)
560 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800561 bcap->speech_ver[s++] = lv[i] & 0x0f;
562 bcap->speech_ver[s] = -1; /* end of list */
Harald Welteb8a18b52009-06-10 12:08:54 +0800563 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800564 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800565 if (s == 7) /* maximum speech versions + end of list */
566 return 0;
567 }
568
569 return 0;
570}
571
572/* encode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800573static int encode_bearer_cap(struct msgb *msg, int lv_only,
574 const struct gsm_mncc_bearer_cap *bcap)
Harald Welteb8a18b52009-06-10 12:08:54 +0800575{
576 u_int8_t lv[32 + 1];
577 int i, s;
578
Harald Welte03740842009-06-10 23:11:52 +0800579 lv[1] = bcap->transfer;
580 lv[1] |= bcap->mode << 3;
581 lv[1] |= bcap->coding << 4;
582 lv[1] |= bcap->radio << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800583
584 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800585 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800586 i++; /* octet 3a etc */
Harald Welte03740842009-06-10 23:11:52 +0800587 lv[i] = bcap->speech_ver[s];
Harald Welteb8a18b52009-06-10 12:08:54 +0800588 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800589 lv[i] |= bcap->speech_ctm << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800590 }
591 lv[i] |= 0x80; /* last IE of octet 3 etc */
592
593 lv[0] = i;
594 if (lv_only)
595 msgb_lv_put(msg, lv[0], lv+1);
596 else
597 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
598
599 return 0;
600}
601
602/* decode 'call control cap' */
Harald Welte03740842009-06-10 23:11:52 +0800603static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800604{
605 u_int8_t in_len = lv[0];
606
607 if (in_len < 1)
608 return -EINVAL;
609
610 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800611 ccap->dtmf = lv[1] & 0x01;
612 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welteb8a18b52009-06-10 12:08:54 +0800613
614 return 0;
615}
616
617/* decode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800618static int decode_called(struct gsm_mncc_number *called,
619 const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800620{
621 u_int8_t in_len = lv[0];
622
623 if (in_len < 1)
624 return -EINVAL;
625
626 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800627 called->plan = lv[1] & 0x0f;
628 called->type = (lv[1] & 0x70) >> 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800629
630 /* octet 4..N */
Harald Welte03740842009-06-10 23:11:52 +0800631 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800632
633 return 0;
634}
635
636/* encode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800637static int encode_called(struct msgb *msg,
638 const struct gsm_mncc_number *called)
Harald Welteb8a18b52009-06-10 12:08:54 +0800639{
640 u_int8_t lv[18];
641 int ret;
642
643 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800644 lv[1] = called->plan;
645 lv[1] |= called->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800646
647 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800648 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800649 if (ret < 0)
650 return ret;
651
652 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
653
654 return 0;
655}
656
657/* encode callerid of various IEs */
Harald Welte03740842009-06-10 23:11:52 +0800658static int encode_callerid(struct msgb *msg, int ie,
659 const struct gsm_mncc_number *callerid)
Harald Welteb8a18b52009-06-10 12:08:54 +0800660{
661 u_int8_t lv[13];
662 int h_len = 1;
663 int ret;
664
665 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800666 lv[1] = callerid->plan;
667 lv[1] |= callerid->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800668
Harald Welte03740842009-06-10 23:11:52 +0800669 if (callerid->present || callerid->screen) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800670 /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800671 lv[2] = callerid->screen;
672 lv[2] |= callerid->present << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800673 lv[2] |= 0x80;
674 h_len++;
675 } else
676 lv[1] |= 0x80;
677
678 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800679 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800680 if (ret < 0)
681 return ret;
682
683 msgb_tlv_put(msg, ie, lv[0], lv+1);
684
685 return 0;
686}
687
688/* decode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800689static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welteb8a18b52009-06-10 12:08:54 +0800690 const u_int8_t *lv)
691{
692 u_int8_t in_len = lv[0];
693 int i;
694
695 if (in_len < 2)
696 return -EINVAL;
697
Harald Welte03740842009-06-10 23:11:52 +0800698 cause->diag_len = 0;
Harald Welteb8a18b52009-06-10 12:08:54 +0800699
700 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800701 cause->location = lv[1] & 0x0f;
702 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800703
704 i = 1;
705 if (!(lv[i] & 0x80)) {
706 i++; /* octet 3a */
707 if (in_len < i+1)
708 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800709 cause->rec = 1;
710 cause->rec_val = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800711
712 }
713 i++;
714
715 /* octet 4 */
Harald Welte03740842009-06-10 23:11:52 +0800716 cause->value = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800717 i++;
718
719 if (in_len < i) /* no diag */
720 return 0;
721
722 if (in_len - (i-1) > 32) /* maximum 32 octets */
723 return 0;
724
725 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800726 memcpy(cause->diag, lv + i, in_len - (i-1));
727 cause->diag_len = in_len - (i-1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800728
729 return 0;
730}
731
732/* encode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800733static int encode_cause(struct msgb *msg, int lv_only,
734 const struct gsm_mncc_cause *cause)
Harald Welteb8a18b52009-06-10 12:08:54 +0800735{
736 u_int8_t lv[32+4];
737 int i;
738
Harald Welte03740842009-06-10 23:11:52 +0800739 if (cause->diag_len > 32)
Harald Welteb8a18b52009-06-10 12:08:54 +0800740 return -EINVAL;
741
742 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800743 lv[1] = cause->location;
744 lv[1] |= cause->coding << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800745
746 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800747 if (cause->rec) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800748 i++; /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800749 lv[i] = cause->rec_val;
Harald Welteb8a18b52009-06-10 12:08:54 +0800750 }
751 lv[i] |= 0x80; /* end of octet 3 */
752
753 /* octet 4 */
754 i++;
Harald Welte03740842009-06-10 23:11:52 +0800755 lv[i] = 0x80 | cause->value;
Harald Welteb8a18b52009-06-10 12:08:54 +0800756
757 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800758 if (cause->diag_len) {
759 memcpy(lv + i, cause->diag, cause->diag_len);
760 i += cause->diag_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800761 }
762
763 lv[0] = i;
764 if (lv_only)
765 msgb_lv_put(msg, lv[0], lv+1);
766 else
767 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
768
769 return 0;
770}
771
772/* encode 'calling number' */
Harald Welte03740842009-06-10 23:11:52 +0800773static int encode_calling(struct msgb *msg,
774 const struct gsm_mncc_number *calling)
Harald Welteb8a18b52009-06-10 12:08:54 +0800775{
Harald Welte03740842009-06-10 23:11:52 +0800776 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welteb8a18b52009-06-10 12:08:54 +0800777}
778
779/* encode 'connected number' */
Harald Welte03740842009-06-10 23:11:52 +0800780static int encode_connected(struct msgb *msg,
781 const struct gsm_mncc_number *connected)
Harald Welteb8a18b52009-06-10 12:08:54 +0800782{
Harald Welte03740842009-06-10 23:11:52 +0800783 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welteb8a18b52009-06-10 12:08:54 +0800784}
785
786/* encode 'redirecting number' */
Harald Welte03740842009-06-10 23:11:52 +0800787static int encode_redirecting(struct msgb *msg,
788 const struct gsm_mncc_number *redirecting)
Harald Welteb8a18b52009-06-10 12:08:54 +0800789{
Harald Welte03740842009-06-10 23:11:52 +0800790 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welteb8a18b52009-06-10 12:08:54 +0800791}
792
793/* decode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800794static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welteb8a18b52009-06-10 12:08:54 +0800795 const u_int8_t *lv)
796{
797 u_int8_t in_len = lv[0];
798
799 if (in_len < 1)
800 return -EINVAL;
801
Harald Welte03740842009-06-10 23:11:52 +0800802 if (in_len > sizeof(facility->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800803 return -EINVAL;
804
Harald Welte03740842009-06-10 23:11:52 +0800805 memcpy(facility->info, lv+1, in_len);
806 facility->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800807
808 return 0;
809}
810
811/* encode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800812static int encode_facility(struct msgb *msg, int lv_only,
813 const struct gsm_mncc_facility *facility)
Harald Welteb8a18b52009-06-10 12:08:54 +0800814{
815 u_int8_t lv[GSM_MAX_FACILITY + 1];
816
Harald Welte03740842009-06-10 23:11:52 +0800817 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welteb8a18b52009-06-10 12:08:54 +0800818 return -EINVAL;
819
Harald Welte03740842009-06-10 23:11:52 +0800820 memcpy(lv+1, facility->info, facility->len);
821 lv[0] = facility->len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800822 if (lv_only)
823 msgb_lv_put(msg, lv[0], lv+1);
824 else
825 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
826
827 return 0;
828}
829
830/* decode 'notify' */
831static int decode_notify(int *notify, const u_int8_t *v)
832{
833 *notify = v[0] & 0x7f;
834
835 return 0;
836}
837
838/* encode 'notify' */
839static int encode_notify(struct msgb *msg, int notify)
840{
841 msgb_v_put(msg, notify | 0x80);
842
843 return 0;
844}
845
846/* encode 'signal' */
847static int encode_signal(struct msgb *msg, int signal)
848{
849 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
850
851 return 0;
852}
853
854/* decode 'keypad' */
855static int decode_keypad(int *keypad, const u_int8_t *lv)
856{
857 u_int8_t in_len = lv[0];
858
859 if (in_len < 1)
860 return -EINVAL;
861
862 *keypad = lv[1] & 0x7f;
863
864 return 0;
865}
866
867/* encode 'keypad' */
868static int encode_keypad(struct msgb *msg, int keypad)
869{
870 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
871
872 return 0;
873}
874
875/* decode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800876static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welteb8a18b52009-06-10 12:08:54 +0800877 const u_int8_t *lv)
878{
879 u_int8_t in_len = lv[0];
880
881 if (in_len < 2)
882 return -EINVAL;
883
Harald Welte03740842009-06-10 23:11:52 +0800884 progress->coding = (lv[1] & 0x60) >> 5;
885 progress->location = lv[1] & 0x0f;
886 progress->descr = lv[2] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800887
888 return 0;
889}
890
891/* encode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800892static int encode_progress(struct msgb *msg, int lv_only,
893 const struct gsm_mncc_progress *p)
Harald Welteb8a18b52009-06-10 12:08:54 +0800894{
895 u_int8_t lv[3];
896
897 lv[0] = 2;
Harald Welte03740842009-06-10 23:11:52 +0800898 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
899 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welteb8a18b52009-06-10 12:08:54 +0800900 if (lv_only)
901 msgb_lv_put(msg, lv[0], lv+1);
902 else
903 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
904
905 return 0;
906}
907
908/* decode 'user-user' */
Harald Welte03740842009-06-10 23:11:52 +0800909static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welteb8a18b52009-06-10 12:08:54 +0800910 const u_int8_t *lv)
911{
912 u_int8_t in_len = lv[0];
Harald Welte03740842009-06-10 23:11:52 +0800913 char *info = uu->info;
914 int info_len = sizeof(uu->info);
Harald Welteb8a18b52009-06-10 12:08:54 +0800915 int i;
916
917 if (in_len < 1)
918 return -EINVAL;
919
Harald Welte03740842009-06-10 23:11:52 +0800920 uu->proto = lv[1];
Harald Welteb8a18b52009-06-10 12:08:54 +0800921
922 for (i = 2; i <= in_len; i++) {
923 info_len--;
924 if (info_len <= 1)
925 break;
926 *info++ = lv[i];
927 }
928 if (info_len >= 1)
929 *info++ = '\0';
930
931 return 0;
932}
933
934/* encode 'useruser' */
Harald Welte03740842009-06-10 23:11:52 +0800935static int encode_useruser(struct msgb *msg, int lv_only,
936 const struct gsm_mncc_useruser *uu)
Harald Welteb8a18b52009-06-10 12:08:54 +0800937{
938 u_int8_t lv[GSM_MAX_USERUSER + 2];
939
Harald Welte03740842009-06-10 23:11:52 +0800940 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welteb8a18b52009-06-10 12:08:54 +0800941 return -EINVAL;
942
Harald Welte03740842009-06-10 23:11:52 +0800943 lv[0] = 1 + strlen(uu->info);
944 lv[1] = uu->proto;
945 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welteb8a18b52009-06-10 12:08:54 +0800946 if (lv_only)
947 msgb_lv_put(msg, lv[0], lv+1);
948 else
949 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
950
951 return 0;
952}
953
954/* decode 'ss version' */
Harald Welte03740842009-06-10 23:11:52 +0800955static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welteb8a18b52009-06-10 12:08:54 +0800956 const u_int8_t *lv)
957{
958 u_int8_t in_len = lv[0];
959
Harald Welte03740842009-06-10 23:11:52 +0800960 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800961 return -EINVAL;
962
Harald Welte03740842009-06-10 23:11:52 +0800963 memcpy(ssv->info, lv + 1, in_len);
964 ssv->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800965
966 return 0;
967}
968
969/* encode 'more data' */
970static int encode_more(struct msgb *msg)
971{
972 u_int8_t *ie;
973
974 ie = msgb_put(msg, 1);
975 ie[0] = GSM48_IE_MORE_DATA;
976
977 return 0;
978}
979
Harald Welte59b04682009-06-10 05:40:52 +0800980struct msgb *gsm48_msgb_alloc(void)
981{
Harald Welte9cfc9352009-06-26 19:39:35 +0200982 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
983 "GSM 04.08");
Harald Welte59b04682009-06-10 05:40:52 +0800984}
985
Harald Welte36fe2e82009-07-23 21:13:03 +0200986int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800987{
Harald Welte36fe2e82009-07-23 21:13:03 +0200988 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
989
990 /* if we get passed a transaction reference, do some common
991 * work that the caller no longer has to do */
992 if (trans) {
Harald Welte4861c822009-07-23 21:21:14 +0200993 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte36fe2e82009-07-23 21:13:03 +0200994 msg->lchan = trans->lchan;
995 }
996
Harald Welte59b04682009-06-10 05:40:52 +0800997 if (msg->lchan) {
998 msg->trx = msg->lchan->ts->trx;
999
Harald Welte03740842009-06-10 23:11:52 +08001000 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1001 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1002 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1003 msg->trx->nr, msg->lchan->ts->nr,
1004 gh->proto_discr & 0xf0,
1005 cc_msg_names[gh->msg_type & 0x3f]);
1006 else
1007 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1008 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1009 msg->trx->nr, msg->lchan->ts->nr,
1010 gh->proto_discr, gh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001011 }
1012
1013 msg->l3h = msg->data;
1014
1015 return rsl_data_request(msg, 0);
1016}
1017
Harald Welte59b04682009-06-10 05:40:52 +08001018/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
1019int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
1020{
1021 struct msgb *msg = gsm48_msgb_alloc();
1022 struct gsm48_hdr *gh;
1023
1024 msg->lchan = lchan;
1025
1026 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1027 gh->proto_discr = GSM48_PDISC_MM;
1028 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
1029 gh->data[0] = cause;
1030
1031 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1032
Harald Welte36fe2e82009-07-23 21:13:03 +02001033 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001034}
1035
1036/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
1037int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
1038{
1039 struct gsm_bts *bts = lchan->ts->trx->bts;
1040 struct msgb *msg = gsm48_msgb_alloc();
1041 struct gsm48_hdr *gh;
1042 struct gsm48_loc_area_id *lai;
1043 u_int8_t *mid;
1044 int ret;
1045
1046 msg->lchan = lchan;
1047
1048 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1049 gh->proto_discr = GSM48_PDISC_MM;
1050 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1051
1052 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
1053 gsm0408_generate_lai(lai, bts->network->country_code,
1054 bts->network->network_code, bts->location_area_code);
1055
1056 mid = msgb_put(msg, MID_TMSI_LEN);
1057 generate_mid_from_tmsi(mid, tmsi);
1058
1059 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1060
Harald Welte36fe2e82009-07-23 21:13:03 +02001061 ret = gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001062
Harald Welte5070e942009-08-09 19:07:00 +02001063 /* send MM INFO with network name */
Harald Welte59b04682009-06-10 05:40:52 +08001064 ret = gsm48_tx_mm_info(lchan);
1065
1066 return ret;
1067}
1068
1069static char bcd2char(u_int8_t bcd)
1070{
1071 if (bcd < 0xa)
1072 return '0' + bcd;
1073 else
1074 return 'A' + (bcd - 0xa);
1075}
1076
1077/* Convert Mobile Identity (10.5.1.4) to string */
1078static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1079{
1080 int i;
1081 u_int8_t mi_type;
1082 char *str_cur = string;
1083 u_int32_t tmsi;
1084
1085 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1086
1087 switch (mi_type) {
1088 case GSM_MI_TYPE_NONE:
1089 break;
1090 case GSM_MI_TYPE_TMSI:
1091 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1092 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1093 memcpy(&tmsi, &mi[1], 4);
1094 tmsi = ntohl(tmsi);
1095 return snprintf(string, str_len, "%u", tmsi);
1096 }
1097 break;
1098 case GSM_MI_TYPE_IMSI:
1099 case GSM_MI_TYPE_IMEI:
1100 case GSM_MI_TYPE_IMEISV:
1101 *str_cur++ = bcd2char(mi[0] >> 4);
1102
1103 for (i = 1; i < mi_len; i++) {
1104 if (str_cur + 2 >= string + str_len)
1105 return str_cur - string;
1106 *str_cur++ = bcd2char(mi[i] & 0xf);
1107 /* skip last nibble in last input byte when GSM_EVEN */
1108 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1109 *str_cur++ = bcd2char(mi[i] >> 4);
1110 }
1111 break;
1112 default:
1113 break;
1114 }
1115 *str_cur++ = '\0';
1116
1117 return str_cur - string;
1118}
1119
1120/* Transmit Chapter 9.2.10 Identity Request */
1121static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1122{
1123 struct msgb *msg = gsm48_msgb_alloc();
1124 struct gsm48_hdr *gh;
1125
1126 msg->lchan = lchan;
1127
1128 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1129 gh->proto_discr = GSM48_PDISC_MM;
1130 gh->msg_type = GSM48_MT_MM_ID_REQ;
1131 gh->data[0] = id_type;
1132
Harald Welte36fe2e82009-07-23 21:13:03 +02001133 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001134}
1135
1136#define MI_SIZE 32
1137
1138/* Parse Chapter 9.2.11 Identity Response */
1139static int mm_rx_id_resp(struct msgb *msg)
1140{
1141 struct gsm48_hdr *gh = msgb_l3(msg);
1142 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001143 struct gsm_bts *bts = lchan->ts->trx->bts;
1144 struct gsm_network *net = bts->network;
Harald Welte59b04682009-06-10 05:40:52 +08001145 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1146 char mi_string[MI_SIZE];
1147
1148 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
1149 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
1150 mi_type, mi_string);
1151
Harald Welte59b04682009-06-10 05:40:52 +08001152 switch (mi_type) {
1153 case GSM_MI_TYPE_IMSI:
Jan Luebbe9bdbd622009-08-12 10:19:34 +02001154 /* look up subscriber based on IMSI, create if not found */
1155 if (!lchan->subscr) {
1156 lchan->subscr = subscr_get_by_imsi(net, mi_string);
1157 }
Jan Luebbee2974032009-08-12 10:12:52 +02001158 if (!lchan->subscr) {
Harald Welte75350412009-07-23 18:46:00 +02001159 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbee2974032009-08-12 10:12:52 +02001160 if (lchan->subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1161 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &lchan->subscr);
1162 }
1163 }
Harald Welte59b04682009-06-10 05:40:52 +08001164 if (lchan->loc_operation)
1165 lchan->loc_operation->waiting_for_imsi = 0;
1166 break;
1167 case GSM_MI_TYPE_IMEI:
1168 case GSM_MI_TYPE_IMEISV:
1169 /* update subscribe <-> IMEI mapping */
1170 if (lchan->subscr)
1171 db_subscriber_assoc_imei(lchan->subscr, mi_string);
1172 if (lchan->loc_operation)
1173 lchan->loc_operation->waiting_for_imei = 0;
1174 break;
1175 }
1176
1177 /* Check if we can let the mobile station enter */
1178 return gsm0408_authorize(lchan, msg);
1179}
1180
1181
1182static void loc_upd_rej_cb(void *data)
1183{
1184 struct gsm_lchan *lchan = data;
1185
1186 release_loc_updating_req(lchan);
1187 gsm0408_loc_upd_rej(lchan, reject_cause);
1188 lchan_auto_release(lchan);
1189}
1190
1191static void schedule_reject(struct gsm_lchan *lchan)
1192{
1193 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1194 lchan->loc_operation->updating_timer.data = lchan;
1195 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
1196}
1197
1198static const char *lupd_name(u_int8_t type)
1199{
1200 switch (type) {
1201 case GSM48_LUPD_NORMAL:
1202 return "NORMAL";
1203 case GSM48_LUPD_PERIODIC:
1204 return "PEROIDOC";
1205 case GSM48_LUPD_IMSI_ATT:
1206 return "IMSI ATTACH";
1207 default:
1208 return "UNKNOWN";
1209 }
1210}
1211
1212#define MI_SIZE 32
1213/* Chapter 9.2.15: Receive Location Updating Request */
1214static int mm_rx_loc_upd_req(struct msgb *msg)
1215{
1216 struct gsm48_hdr *gh = msgb_l3(msg);
1217 struct gsm48_loc_upd_req *lu;
Harald Welte03740842009-06-10 23:11:52 +08001218 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001219 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001220 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001221 u_int8_t mi_type;
1222 char mi_string[MI_SIZE];
1223 int rc;
1224
1225 lu = (struct gsm48_loc_upd_req *) gh->data;
1226
1227 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
1228
1229 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1230
Harald Welte79639662009-06-27 02:58:43 +02001231 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte59b04682009-06-10 05:40:52 +08001232 lupd_name(lu->type));
1233
1234 /*
1235 * Pseudo Spoof detection: Just drop a second/concurrent
1236 * location updating request.
1237 */
1238 if (lchan->loc_operation) {
Harald Welte79639662009-06-27 02:58:43 +02001239 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Harald Welte59b04682009-06-10 05:40:52 +08001240 lchan->loc_operation);
1241 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1242 return 0;
1243 }
1244
1245 allocate_loc_updating_req(lchan);
1246
1247 switch (mi_type) {
1248 case GSM_MI_TYPE_IMSI:
Harald Welte79639662009-06-27 02:58:43 +02001249 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001250 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001251 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1252 lchan->loc_operation->waiting_for_imei = 1;
1253
Jan Luebbe9bdbd622009-08-12 10:19:34 +02001254 /* look up subscriber based on IMSI, create if not found */
1255 subscr = subscr_get_by_imsi(bts->network, mi_string);
1256 if (!subscr) {
1257 subscr = db_create_subscriber(bts->network, mi_string);
1258 }
Jan Luebbee2974032009-08-12 10:12:52 +02001259 if (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1260 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &subscr);
1261 }
Harald Welte59b04682009-06-10 05:40:52 +08001262 break;
1263 case GSM_MI_TYPE_TMSI:
Harald Welte79639662009-06-27 02:58:43 +02001264 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001265 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001266 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1267 lchan->loc_operation->waiting_for_imei = 1;
1268
1269 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte75350412009-07-23 18:46:00 +02001270 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001271 if (!subscr) {
1272 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte59b04682009-06-10 05:40:52 +08001273 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
1274 lchan->loc_operation->waiting_for_imsi = 1;
1275 }
1276 break;
1277 case GSM_MI_TYPE_IMEI:
1278 case GSM_MI_TYPE_IMEISV:
1279 /* no sim card... FIXME: what to do ? */
Harald Welte79639662009-06-27 02:58:43 +02001280 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001281 break;
1282 default:
Harald Welte79639662009-06-27 02:58:43 +02001283 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001284 break;
1285 }
1286
Harald Welteccd69362009-07-04 10:18:00 +02001287 /* schedule the reject timer */
1288 schedule_reject(lchan);
1289
Harald Welte03740842009-06-10 23:11:52 +08001290 if (!subscr) {
Harald Welte79639662009-06-27 02:58:43 +02001291 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte03740842009-06-10 23:11:52 +08001292 /* FIXME: request id? close channel? */
1293 return -EINVAL;
1294 }
1295
Harald Welte59b04682009-06-10 05:40:52 +08001296 lchan->subscr = subscr;
1297
Harald Welteccd69362009-07-04 10:18:00 +02001298 /* check if we can let the subscriber into our network immediately
1299 * or if we need to wait for identity responses. */
Harald Welte59b04682009-06-10 05:40:52 +08001300 return gsm0408_authorize(lchan, msg);
1301}
1302
Harald Welteca745e22009-07-29 12:10:35 +02001303/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte59b04682009-06-10 05:40:52 +08001304int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1305{
1306 struct msgb *msg = gsm48_msgb_alloc();
1307 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1308 struct gsm48_chan_mode_modify *cmm =
1309 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
1310 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
1311
1312 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
1313
1314 lchan->tch_mode = mode;
1315 msg->lchan = lchan;
1316 gh->proto_discr = GSM48_PDISC_RR;
1317 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1318
1319 /* fill the channel information element, this code
1320 * should probably be shared with rsl_rx_chan_rqd() */
1321 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
1322 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
1323 cmm->chan_desc.h0.h = 0;
1324 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1325 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1326 cmm->mode = mode;
1327
Harald Welte36fe2e82009-07-23 21:13:03 +02001328 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001329}
1330
Harald Welte03740842009-06-10 23:11:52 +08001331#if 0
1332static u_int8_t to_bcd8(u_int8_t val)
1333{
1334 return ((val / 10) << 4) | (val % 10);
1335}
1336#endif
1337
Harald Welte59b04682009-06-10 05:40:52 +08001338/* Section 9.2.15a */
1339int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1340{
1341 struct msgb *msg = gsm48_msgb_alloc();
1342 struct gsm48_hdr *gh;
1343 struct gsm_network *net = lchan->ts->trx->bts->network;
1344 u_int8_t *ptr8;
1345 u_int16_t *ptr16;
1346 int name_len;
1347 int i;
Harald Welte03740842009-06-10 23:11:52 +08001348#if 0
1349 time_t cur_t;
1350 struct tm* cur_time;
1351 int tz15min;
1352#endif
Harald Welte59b04682009-06-10 05:40:52 +08001353
1354 msg->lchan = lchan;
1355
1356 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1357 gh->proto_discr = GSM48_PDISC_MM;
1358 gh->msg_type = GSM48_MT_MM_INFO;
1359
1360 if (net->name_long) {
1361 name_len = strlen(net->name_long);
1362 /* 10.5.3.5a */
1363 ptr8 = msgb_put(msg, 3);
1364 ptr8[0] = GSM48_IE_NAME_LONG;
1365 ptr8[1] = name_len*2 +1;
1366 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1367
1368 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1369 for (i = 0; i < name_len; i++)
1370 ptr16[i] = htons(net->name_long[i]);
1371
1372 /* FIXME: Use Cell Broadcast, not UCS-2, since
1373 * UCS-2 is only supported by later revisions of the spec */
1374 }
1375
1376 if (net->name_short) {
1377 name_len = strlen(net->name_short);
1378 /* 10.5.3.5a */
1379 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Weltef6284712009-07-19 17:51:36 +02001380 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Welte59b04682009-06-10 05:40:52 +08001381 ptr8[1] = name_len*2 + 1;
1382 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1383
1384 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1385 for (i = 0; i < name_len; i++)
1386 ptr16[i] = htons(net->name_short[i]);
1387 }
1388
1389#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001390 /* Section 10.5.3.9 */
1391 cur_t = time(NULL);
Harald Welte03740842009-06-10 23:11:52 +08001392 cur_time = gmtime(&cur_t);
Harald Welte59b04682009-06-10 05:40:52 +08001393 ptr8 = msgb_put(msg, 8);
1394 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1395 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1396 ptr8[2] = to_bcd8(cur_time->tm_mon);
1397 ptr8[3] = to_bcd8(cur_time->tm_mday);
1398 ptr8[4] = to_bcd8(cur_time->tm_hour);
1399 ptr8[5] = to_bcd8(cur_time->tm_min);
1400 ptr8[6] = to_bcd8(cur_time->tm_sec);
1401 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1402 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte03740842009-06-10 23:11:52 +08001403 ptr8[7] = to_bcd8(tz15min);
Harald Welte59b04682009-06-10 05:40:52 +08001404 if (tz15min < 0)
Harald Welte03740842009-06-10 23:11:52 +08001405 ptr8[7] |= 0x80;
Harald Welte59b04682009-06-10 05:40:52 +08001406#endif
1407
Harald Welte36fe2e82009-07-23 21:13:03 +02001408 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001409}
1410
1411static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1412{
1413 DEBUGP(DMM, "-> CM SERVICE ACK\n");
1414 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
1415}
1416
1417/* 9.2.6 CM service reject */
1418static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1419 enum gsm48_reject_value value)
1420{
1421 struct msgb *msg = gsm48_msgb_alloc();
1422 struct gsm48_hdr *gh;
1423
1424 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1425
1426 msg->lchan = lchan;
1427 use_lchan(lchan);
1428
1429 gh->proto_discr = GSM48_PDISC_MM;
1430 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1431 gh->data[0] = value;
1432 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1433
Harald Welte36fe2e82009-07-23 21:13:03 +02001434 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001435}
1436
Harald Welte583ceaf2009-08-10 10:12:45 +02001437static int send_siemens_mrpci(struct gsm_lchan *lchan,
1438 u_int8_t *classmark2_lv)
1439{
1440 struct rsl_mrpci mrpci;
1441
1442 if (classmark2_lv[0] < 2)
1443 return -EINVAL;
1444
1445 mrpci.power_class = classmark2_lv[1] & 0x7;
1446 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1447 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1448 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1449
1450 return rsl_siemens_mrpci(lchan, &mrpci);
1451}
Harald Welte59b04682009-06-10 05:40:52 +08001452
1453/*
1454 * Handle CM Service Requests
1455 * a) Verify that the packet is long enough to contain the information
1456 * we require otherwsie reject with INCORRECT_MESSAGE
1457 * b) Try to parse the TMSI. If we do not have one reject
1458 * c) Check that we know the subscriber with the TMSI otherwise reject
1459 * with a HLR cause
1460 * d) Set the subscriber on the gsm_lchan and accept
1461 */
1462static int gsm48_rx_mm_serv_req(struct msgb *msg)
1463{
1464 u_int8_t mi_type;
1465 char mi_string[MI_SIZE];
1466
Harald Welte75350412009-07-23 18:46:00 +02001467 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001468 struct gsm_subscriber *subscr;
1469 struct gsm48_hdr *gh = msgb_l3(msg);
1470 struct gsm48_service_request *req =
1471 (struct gsm48_service_request *)gh->data;
1472 /* unfortunately in Phase1 the classmar2 length is variable */
1473 u_int8_t classmark2_len = gh->data[1];
1474 u_int8_t *classmark2 = gh->data+2;
1475 u_int8_t mi_len = *(classmark2 + classmark2_len);
1476 u_int8_t *mi = (classmark2 + classmark2_len + 1);
1477
1478 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
1479 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
1480 DEBUGPC(DMM, "wrong sized message\n");
1481 return gsm48_tx_mm_serv_rej(msg->lchan,
1482 GSM48_REJECT_INCORRECT_MESSAGE);
1483 }
1484
1485 if (msg->data_len < req->mi_len + 6) {
1486 DEBUGPC(DMM, "does not fit in packet\n");
1487 return gsm48_tx_mm_serv_rej(msg->lchan,
1488 GSM48_REJECT_INCORRECT_MESSAGE);
1489 }
1490
1491 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1492 if (mi_type != GSM_MI_TYPE_TMSI) {
1493 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
1494 return gsm48_tx_mm_serv_rej(msg->lchan,
1495 GSM48_REJECT_INCORRECT_MESSAGE);
1496 }
1497
1498 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1499 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
1500 req->cm_service_type, mi_type, mi_string);
1501
Harald Welte583ceaf2009-08-10 10:12:45 +02001502 if (is_siemens_bts(bts))
1503 send_siemens_mrpci(msg->lchan, classmark2-1);
1504
Harald Welte75350412009-07-23 18:46:00 +02001505 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001506
1507 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
1508 if (!subscr)
1509 return gsm48_tx_mm_serv_rej(msg->lchan,
1510 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1511
1512 if (!msg->lchan->subscr)
1513 msg->lchan->subscr = subscr;
1514 else if (msg->lchan->subscr != subscr) {
1515 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1516 subscr_put(subscr);
1517 }
1518
Harald Weltef6845a72009-07-05 14:08:13 +02001519 subscr->equipment.classmark2_len = classmark2_len;
1520 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1521 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001522
1523 return gsm48_tx_mm_serv_ack(msg->lchan);
1524}
1525
1526static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1527{
Harald Welte75350412009-07-23 18:46:00 +02001528 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001529 struct gsm48_hdr *gh = msgb_l3(msg);
1530 struct gsm48_imsi_detach_ind *idi =
1531 (struct gsm48_imsi_detach_ind *) gh->data;
1532 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1533 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001534 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001535
1536 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1537 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1538 mi_type, mi_string);
1539
1540 switch (mi_type) {
1541 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001542 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001543 break;
1544 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001545 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001546 break;
1547 case GSM_MI_TYPE_IMEI:
1548 case GSM_MI_TYPE_IMEISV:
1549 /* no sim card... FIXME: what to do ? */
1550 DEBUGPC(DMM, "unimplemented mobile identity type\n");
1551 break;
1552 default:
1553 DEBUGPC(DMM, "unknown mobile identity type\n");
1554 break;
1555 }
1556
1557 if (subscr) {
1558 subscr_update(subscr, msg->trx->bts,
1559 GSM_SUBSCRIBER_UPDATE_DETACHED);
1560 DEBUGP(DMM, "Subscriber: %s\n",
1561 subscr->name ? subscr->name : subscr->imsi);
1562 subscr_put(subscr);
1563 } else
1564 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1565
Harald Welte59b04682009-06-10 05:40:52 +08001566 return 0;
1567}
1568
1569static int gsm48_rx_mm_status(struct msgb *msg)
1570{
1571 struct gsm48_hdr *gh = msgb_l3(msg);
1572
1573 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1574
1575 return 0;
1576}
1577
1578/* Receive a GSM 04.08 Mobility Management (MM) message */
1579static int gsm0408_rcv_mm(struct msgb *msg)
1580{
1581 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte03740842009-06-10 23:11:52 +08001582 int rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08001583
1584 switch (gh->msg_type & 0xbf) {
1585 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Welte79639662009-06-27 02:58:43 +02001586 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte59b04682009-06-10 05:40:52 +08001587 rc = mm_rx_loc_upd_req(msg);
1588 break;
1589 case GSM48_MT_MM_ID_RESP:
1590 rc = mm_rx_id_resp(msg);
1591 break;
1592 case GSM48_MT_MM_CM_SERV_REQ:
1593 rc = gsm48_rx_mm_serv_req(msg);
1594 break;
1595 case GSM48_MT_MM_STATUS:
1596 rc = gsm48_rx_mm_status(msg);
1597 break;
1598 case GSM48_MT_MM_TMSI_REALL_COMPL:
1599 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1600 msg->lchan->subscr ?
1601 msg->lchan->subscr->imsi :
1602 "unknown subscriber");
1603 break;
1604 case GSM48_MT_MM_IMSI_DETACH_IND:
1605 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1606 break;
1607 case GSM48_MT_MM_CM_REEST_REQ:
1608 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1609 break;
1610 case GSM48_MT_MM_AUTH_RESP:
1611 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
1612 break;
1613 default:
1614 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1615 gh->msg_type);
1616 break;
1617 }
1618
1619 return rc;
1620}
1621
1622/* Receive a PAGING RESPONSE message from the MS */
1623static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1624{
Harald Welte75350412009-07-23 18:46:00 +02001625 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001626 struct gsm48_hdr *gh = msgb_l3(msg);
1627 u_int8_t *classmark2_lv = gh->data + 1;
1628 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1629 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
1630 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001631 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001632 struct paging_signal_data sig_data;
1633 int rc = 0;
1634
1635 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
1636 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1637 mi_type, mi_string);
Harald Welte583ceaf2009-08-10 10:12:45 +02001638
1639 if (is_siemens_bts(bts))
1640 send_siemens_mrpci(msg->lchan, classmark2_lv);
1641
Harald Welte59b04682009-06-10 05:40:52 +08001642 switch (mi_type) {
1643 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001644 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001645 break;
1646 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001647 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001648 break;
1649 }
1650
1651 if (!subscr) {
1652 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1653 /* FIXME: request id? close channel? */
1654 return -EINVAL;
1655 }
1656 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte68b7df22009-08-08 16:03:15 +02001657 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Harald Welte59b04682009-06-10 05:40:52 +08001658
Harald Weltef6845a72009-07-05 14:08:13 +02001659 subscr->equipment.classmark2_len = *classmark2_lv;
1660 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1661 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001662
1663 if (!msg->lchan->subscr) {
1664 msg->lchan->subscr = subscr;
1665 } else if (msg->lchan->subscr != subscr) {
1666 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1667 subscr_put(subscr);
1668 return -EINVAL;
1669 } else {
1670 DEBUGP(DRR, "<- Channel already owned by us\n");
1671 subscr_put(subscr);
1672 subscr = msg->lchan->subscr;
1673 }
1674
1675 sig_data.subscr = subscr;
1676 sig_data.bts = msg->lchan->ts->trx->bts;
1677 sig_data.lchan = msg->lchan;
1678
1679 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Welte876312f2009-06-10 11:21:55 +08001680
1681 /* Stop paging on the bts we received the paging response */
Harald Welte59b04682009-06-10 05:40:52 +08001682 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
1683
1684 /* FIXME: somehow signal the completion of the PAGING to
1685 * the entity that requested the paging */
1686
1687 return rc;
1688}
1689
1690static int gsm48_rx_rr_classmark(struct msgb *msg)
1691{
1692 struct gsm48_hdr *gh = msgb_l3(msg);
1693 struct gsm_subscriber *subscr = msg->lchan->subscr;
1694 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1695 u_int8_t cm2_len, cm3_len = 0;
1696 u_int8_t *cm2, *cm3 = NULL;
1697
1698 DEBUGP(DRR, "CLASSMARK CHANGE ");
1699
1700 /* classmark 2 */
1701 cm2_len = gh->data[0];
1702 cm2 = &gh->data[1];
1703 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1704
1705 if (payload_len > cm2_len + 1) {
1706 /* we must have a classmark3 */
1707 if (gh->data[cm2_len+1] != 0x20) {
1708 DEBUGPC(DRR, "ERR CM3 TAG\n");
1709 return -EINVAL;
1710 }
1711 if (cm2_len > 3) {
1712 DEBUGPC(DRR, "CM2 too long!\n");
1713 return -EINVAL;
1714 }
1715
1716 cm3_len = gh->data[cm2_len+2];
1717 cm3 = &gh->data[cm2_len+3];
1718 if (cm3_len > 14) {
1719 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1720 return -EINVAL;
1721 }
1722 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1723 }
1724 if (subscr) {
Harald Weltef6845a72009-07-05 14:08:13 +02001725 subscr->equipment.classmark2_len = cm2_len;
1726 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Welte59b04682009-06-10 05:40:52 +08001727 if (cm3) {
Harald Weltef6845a72009-07-05 14:08:13 +02001728 subscr->equipment.classmark3_len = cm3_len;
1729 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Welte59b04682009-06-10 05:40:52 +08001730 }
Harald Weltef6845a72009-07-05 14:08:13 +02001731 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001732 }
1733
Harald Welte59b04682009-06-10 05:40:52 +08001734 return 0;
1735}
1736
1737static int gsm48_rx_rr_status(struct msgb *msg)
1738{
1739 struct gsm48_hdr *gh = msgb_l3(msg);
1740
1741 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1742 rr_cause_name(gh->data[0]));
1743
1744 return 0;
1745}
1746
1747static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1748{
1749 struct gsm48_hdr *gh = msgb_l3(msg);
1750 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1751 static struct gsm_meas_rep meas_rep;
1752
Harald Welte02993682009-06-27 02:53:10 +02001753 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Welte59b04682009-06-10 05:40:52 +08001754 parse_meas_rep(&meas_rep, gh->data, payload_len);
1755 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte02993682009-06-27 02:53:10 +02001756 DEBUGPC(DMEAS, "DTX ");
Harald Welte59b04682009-06-10 05:40:52 +08001757 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte02993682009-06-27 02:53:10 +02001758 DEBUGPC(DMEAS, "BA1 ");
Harald Welte59b04682009-06-10 05:40:52 +08001759 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte02993682009-06-27 02:53:10 +02001760 DEBUGPC(DMEAS, "NOT VALID ");
Harald Welte59b04682009-06-10 05:40:52 +08001761 else
Harald Welte02993682009-06-27 02:53:10 +02001762 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Welte59b04682009-06-10 05:40:52 +08001763 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1764 meas_rep.rxqual_sub);
1765
Harald Welte02993682009-06-27 02:53:10 +02001766 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Welte59b04682009-06-10 05:40:52 +08001767
1768 /* FIXME: put the results somwhere */
1769
1770 return 0;
1771}
1772
1773/* Receive a GSM 04.08 Radio Resource (RR) message */
1774static int gsm0408_rcv_rr(struct msgb *msg)
1775{
1776 struct gsm48_hdr *gh = msgb_l3(msg);
1777 int rc = 0;
1778
1779 switch (gh->msg_type) {
1780 case GSM48_MT_RR_CLSM_CHG:
1781 rc = gsm48_rx_rr_classmark(msg);
1782 break;
1783 case GSM48_MT_RR_GPRS_SUSP_REQ:
1784 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1785 break;
1786 case GSM48_MT_RR_PAG_RESP:
1787 rc = gsm48_rr_rx_pag_resp(msg);
1788 break;
1789 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1790 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welteca745e22009-07-29 12:10:35 +02001791 /* We've successfully modified the MS side of the channel,
1792 * now go on to modify the BTS side of the channel */
Harald Welte39274f42009-07-29 15:41:29 +02001793 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte59b04682009-06-10 05:40:52 +08001794 rc = rsl_chan_mode_modify_req(msg->lchan);
1795 break;
1796 case GSM48_MT_RR_STATUS:
1797 rc = gsm48_rx_rr_status(msg);
1798 break;
1799 case GSM48_MT_RR_MEAS_REP:
1800 rc = gsm48_rx_rr_meas_rep(msg);
1801 break;
1802 default:
1803 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1804 gh->msg_type);
1805 break;
1806 }
1807
1808 return rc;
1809}
1810
Harald Welte85a163c2009-08-10 11:43:22 +02001811/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Harald Welte59b04682009-06-10 05:40:52 +08001812int gsm48_send_rr_release(struct gsm_lchan *lchan)
1813{
1814 struct msgb *msg = gsm48_msgb_alloc();
1815 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1816 u_int8_t *cause;
1817
1818 msg->lchan = lchan;
1819 gh->proto_discr = GSM48_PDISC_RR;
1820 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1821
1822 cause = msgb_put(msg, 1);
1823 cause[0] = GSM48_RR_CAUSE_NORMAL;
1824
1825 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1826 lchan->nr, lchan->type);
1827
Harald Welteafe3c232009-07-19 18:36:49 +02001828 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001829 gsm48_sendmsg(msg, NULL);
Harald Welte68b7df22009-08-08 16:03:15 +02001830 /* FIXME: Start Timer T3109 */
Harald Welteafe3c232009-07-19 18:36:49 +02001831
1832 /* Deactivate the SACCH on the BTS side */
1833 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001834}
1835
1836/* Call Control */
1837
1838/* The entire call control code is written in accordance with Figure 7.10c
1839 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1840 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1841 * it for voice */
1842
Harald Welte03740842009-06-10 23:11:52 +08001843static void new_cc_state(struct gsm_trans *trans, int state)
1844{
1845 if (state > 31 || state < 0)
1846 return;
1847
1848 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltec2189a62009-07-23 18:56:43 +02001849 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001850
Harald Weltec2189a62009-07-23 18:56:43 +02001851 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001852}
1853
1854static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001855{
1856 struct msgb *msg = gsm48_msgb_alloc();
1857 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1858 u_int8_t *cause, *call_state;
1859
Harald Welte59b04682009-06-10 05:40:52 +08001860 gh->msg_type = GSM48_MT_CC_STATUS;
1861
1862 cause = msgb_put(msg, 3);
1863 cause[0] = 2;
1864 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1865 cause[2] = 0x80 | 30; /* response to status inquiry */
1866
1867 call_state = msgb_put(msg, 1);
1868 call_state[0] = 0xc0 | 0x00;
1869
Harald Welte36fe2e82009-07-23 21:13:03 +02001870 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001871}
1872
1873static int gsm48_tx_simple(struct gsm_lchan *lchan,
1874 u_int8_t pdisc, u_int8_t msg_type)
1875{
1876 struct msgb *msg = gsm48_msgb_alloc();
1877 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1878
1879 msg->lchan = lchan;
1880
1881 gh->proto_discr = pdisc;
1882 gh->msg_type = msg_type;
1883
Harald Welte36fe2e82009-07-23 21:13:03 +02001884 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001885}
1886
Harald Welte03740842009-06-10 23:11:52 +08001887static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1888{
Harald Weltec2189a62009-07-23 18:56:43 +02001889 if (bsc_timer_pending(&trans->cc.timer)) {
1890 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1891 bsc_del_timer(&trans->cc.timer);
1892 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001893 }
1894}
1895
1896static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1897 int msg_type, struct gsm_mncc *mncc)
1898{
1899 struct msgb *msg;
1900
1901 if (trans)
1902 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02001903 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08001904 "Sending '%s' to MNCC.\n",
1905 trans->lchan->ts->trx->bts->nr,
1906 trans->lchan->ts->trx->nr,
1907 trans->lchan->ts->nr, trans->transaction_id,
1908 (trans->subscr)?(trans->subscr->extension):"-",
1909 get_mncc_name(msg_type));
1910 else
1911 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1912 "Sending '%s' to MNCC.\n",
1913 (trans->subscr)?(trans->subscr->extension):"-",
1914 get_mncc_name(msg_type));
1915 else
1916 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1917 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1918
1919 mncc->msg_type = msg_type;
1920
Harald Welte9cfc9352009-06-26 19:39:35 +02001921 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08001922 if (!msg)
1923 return -ENOMEM;
1924 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1925 msgb_enqueue(&net->upqueue, msg);
1926
1927 return 0;
1928}
1929
1930int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1931 u_int32_t callref, int location, int value)
1932{
1933 struct gsm_mncc rel;
1934
Harald Weltecb0595f2009-06-12 01:54:08 +08001935 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08001936 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001937 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08001938 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1939}
1940
Harald Weltec2189a62009-07-23 18:56:43 +02001941/* Call Control Specific transaction release.
1942 * gets called by trans_free, DO NOT CALL YOURSELF! */
1943void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08001944{
Harald Welte03740842009-06-10 23:11:52 +08001945 gsm48_stop_cc_timer(trans);
1946
1947 /* send release to L4, if callref still exists */
1948 if (trans->callref) {
1949 /* Ressource unavailable */
Harald Welte0abe5a62009-07-23 19:06:52 +02001950 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08001951 GSM48_CAUSE_LOC_PRN_S_LU,
1952 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08001953 }
Harald Weltec2189a62009-07-23 18:56:43 +02001954 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08001955 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltec2189a62009-07-23 18:56:43 +02001956 if (trans->lchan)
1957 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08001958}
1959
1960static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1961
Harald Welte59b04682009-06-10 05:40:52 +08001962/* call-back from paging the B-end of the connection */
1963static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
1964 struct msgb *msg, void *_lchan, void *param)
1965{
1966 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08001967 struct gsm_subscriber *subscr = param;
1968 struct gsm_trans *transt, *tmp;
1969 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02001970
Harald Welte59b04682009-06-10 05:40:52 +08001971 if (hooknum != GSM_HOOK_RR_PAGING)
1972 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08001973
1974 if (!subscr)
1975 return -EINVAL;
1976 net = subscr->net;
1977 if (!net) {
1978 DEBUGP(DCC, "Error Network not set!\n");
1979 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001980 }
1981
Harald Welte03740842009-06-10 23:11:52 +08001982 /* check all tranactions (without lchan) for subscriber */
1983 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1984 if (transt->subscr != subscr || transt->lchan)
1985 continue;
1986 switch (event) {
1987 case GSM_PAGING_SUCCEEDED:
1988 if (!lchan) // paranoid
1989 break;
1990 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1991 subscr->extension);
1992 /* Assign lchan */
1993 if (!transt->lchan) {
1994 transt->lchan = lchan;
1995 use_lchan(lchan);
1996 }
1997 /* send SETUP request to called party */
Harald Weltec2189a62009-07-23 18:56:43 +02001998 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08001999 break;
2000 case GSM_PAGING_EXPIRED:
2001 DEBUGP(DCC, "Paging subscr %s expired!\n",
2002 subscr->extension);
2003 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002004 mncc_release_ind(transt->subscr->net, transt,
2005 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002006 GSM48_CAUSE_LOC_PRN_S_LU,
2007 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08002008 transt->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002009 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08002010 break;
2011 }
2012 }
Harald Welte59b04682009-06-10 05:40:52 +08002013 return 0;
2014}
2015
Harald Welte3c062072009-07-28 18:25:29 +02002016/* some other part of the code sends us a signal */
2017static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2018 void *handler_data, void *signal_data)
2019{
2020 struct gsm_lchan *lchan = signal_data;
2021 struct gsm_bts_trx_ts *ts;
2022 int rc;
2023
2024 if (subsys != SS_ABISIP)
2025 return 0;
2026
2027 /* in case we use direct BTS-to-BTS RTP */
2028 if (ipacc_rtp_direct)
2029 return 0;
2030
2031 ts = lchan->ts;
2032
2033 switch (signal) {
2034 case S_ABISIP_BIND_ACK:
2035 /* the BTS has successfully bound a TCH to a local ip/port,
2036 * which means we can connect our UDP socket to it */
2037 if (ts->abis_ip.rtp_socket) {
2038 rtp_socket_free(ts->abis_ip.rtp_socket);
2039 ts->abis_ip.rtp_socket = NULL;
2040 }
2041
2042 ts->abis_ip.rtp_socket = rtp_socket_create();
2043 if (!ts->abis_ip.rtp_socket)
2044 goto out_err;
2045
2046 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2047 ts->abis_ip.bound_ip,
2048 ts->abis_ip.bound_port);
2049 if (rc < 0)
2050 goto out_err;
2051 break;
2052 case S_ABISIP_DISC_IND:
2053 /* the BTS tells us a RTP stream has been disconnected */
2054 if (ts->abis_ip.rtp_socket) {
2055 rtp_socket_free(ts->abis_ip.rtp_socket);
2056 ts->abis_ip.rtp_socket = NULL;
2057 }
2058 break;
2059 }
2060
2061 return 0;
2062out_err:
2063 /* FIXME: do something */
2064 return 0;
2065}
2066
2067/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2068static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2069{
2070 struct gsm_bts_trx_ts *ts = lchan->ts;
2071 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2072 int rc;
2073
2074 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2075 ntohs(rs->rtp.sin_local.sin_port),
2076 ts->abis_ip.conn_id,
2077 /* FIXME: use RTP payload of bound socket, not BTS*/
2078 ts->abis_ip.rtp_payload2);
2079
2080 return rc;
2081}
2082
Harald Welte59b04682009-06-10 05:40:52 +08002083/* map two ipaccess RTP streams onto each other */
2084static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2085{
2086 struct gsm_bts *bts = lchan->ts->trx->bts;
2087 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2088 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002089 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002090
2091 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2092 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2093 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2094
2095 if (bts->type != remote_bts->type) {
2096 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2097 return -EINVAL;
2098 }
2099
2100 switch (bts->type) {
2101 case GSM_BTS_TYPE_NANOBTS_900:
2102 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002103 if (!ipacc_rtp_direct) {
2104 /* connect the TCH's to our RTP proxy */
2105 rc = ipacc_connect_proxy_bind(lchan);
2106 if (rc < 0)
2107 return rc;
2108 rc = ipacc_connect_proxy_bind(remote_lchan);
2109
2110 /* connect them with each other */
2111 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2112 remote_lchan->ts->abis_ip.rtp_socket);
2113 } else {
2114 /* directly connect TCH RTP streams to each other */
2115 ts = remote_lchan->ts;
2116 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2117 ts->abis_ip.bound_port,
2118 lchan->ts->abis_ip.conn_id,
2119 ts->abis_ip.rtp_payload2);
2120 if (rc < 0)
2121 return rc;
2122 ts = lchan->ts;
2123 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2124 ts->abis_ip.bound_port,
2125 remote_lchan->ts->abis_ip.conn_id,
2126 ts->abis_ip.rtp_payload2);
2127 }
Harald Welte59b04682009-06-10 05:40:52 +08002128 break;
2129 case GSM_BTS_TYPE_BS11:
2130 trau_mux_map_lchan(lchan, remote_lchan);
2131 break;
2132 default:
2133 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002134 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002135 break;
2136 }
2137
2138 return 0;
2139}
2140
Harald Welte03740842009-06-10 23:11:52 +08002141/* bridge channels of two transactions */
2142static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002143{
Harald Weltec2189a62009-07-23 18:56:43 +02002144 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2145 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002146
Harald Welte03740842009-06-10 23:11:52 +08002147 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002148 return -EIO;
2149
Harald Welte03740842009-06-10 23:11:52 +08002150 if (!trans1->lchan || !trans2->lchan)
2151 return -EIO;
2152
2153 /* through-connect channel */
2154 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002155}
2156
Harald Welte03740842009-06-10 23:11:52 +08002157/* enable receive of channels to upqueue */
2158static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2159{
2160 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002161
Harald Welte03740842009-06-10 23:11:52 +08002162 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002163 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002164 if (!trans)
2165 return -EIO;
2166 if (!trans->lchan)
2167 return 0;
2168
2169 // todo IPACCESS
2170 if (enable)
2171 return trau_recv_lchan(trans->lchan, data->callref);
2172 return trau_mux_unmap(NULL, data->callref);
2173}
2174
2175/* send a frame to channel */
2176static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2177{
2178 struct gsm_trans *trans;
2179
2180 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002181 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002182 if (!trans)
2183 return -EIO;
2184 if (!trans->lchan)
2185 return 0;
2186 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2187 trans->lchan->type != GSM_LCHAN_TCH_H)
2188 return 0;
2189
2190 // todo IPACCESS
2191 return trau_send_lchan(trans->lchan,
2192 (struct decoded_trau_frame *)frame->data);
2193}
2194
2195
2196static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2197{
2198 DEBUGP(DCC, "-> STATUS ENQ\n");
2199 return gsm48_cc_tx_status(trans, msg);
2200}
2201
2202static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2203static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2204
2205static void gsm48_cc_timeout(void *arg)
2206{
2207 struct gsm_trans *trans = arg;
2208 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002209 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2210 int mo_location = GSM48_CAUSE_LOC_USER;
2211 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2212 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002213 struct gsm_mncc mo_rel, l4_rel;
2214
2215 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2216 mo_rel.callref = trans->callref;
2217 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2218 l4_rel.callref = trans->callref;
2219
Harald Weltec2189a62009-07-23 18:56:43 +02002220 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002221 case 0x303:
2222 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002223 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002224 break;
2225 case 0x310:
2226 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002227 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002228 break;
2229 case 0x313:
2230 disconnect = 1;
2231 /* unknown, did not find it in the specs */
2232 break;
2233 case 0x301:
2234 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002235 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002236 break;
2237 case 0x308:
Harald Weltec2189a62009-07-23 18:56:43 +02002238 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002239 /* restart T308 a second time */
Harald Weltec2189a62009-07-23 18:56:43 +02002240 gsm48_cc_tx_release(trans, &trans->cc.msg);
2241 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002242 break; /* stay in release state */
2243 }
Harald Weltec2189a62009-07-23 18:56:43 +02002244 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002245 return;
2246// release = 1;
2247// l4_cause = 14;
2248// break;
2249 case 0x306:
2250 release = 1;
Harald Weltec2189a62009-07-23 18:56:43 +02002251 mo_cause = trans->cc.msg.cause.value;
2252 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002253 break;
2254 case 0x323:
2255 disconnect = 1;
2256 break;
2257 default:
2258 release = 1;
2259 }
2260
2261 if (release && trans->callref) {
2262 /* process release towards layer 4 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002263 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002264 l4_location, l4_cause);
2265 trans->callref = 0;
2266 }
2267
2268 if (disconnect && trans->callref) {
2269 /* process disconnect towards layer 4 */
2270 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte0abe5a62009-07-23 19:06:52 +02002271 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002272 }
2273
2274 /* process disconnect towards mobile station */
2275 if (disconnect || release) {
2276 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltec2189a62009-07-23 18:56:43 +02002277 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2278 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2279 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002280 mo_rel.cause.diag_len = 3;
2281
2282 if (disconnect)
2283 gsm48_cc_tx_disconnect(trans, &mo_rel);
2284 if (release)
2285 gsm48_cc_tx_release(trans, &mo_rel);
2286 }
2287
2288}
2289
2290static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2291 int sec, int micro)
2292{
2293 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltec2189a62009-07-23 18:56:43 +02002294 trans->cc.timer.cb = gsm48_cc_timeout;
2295 trans->cc.timer.data = trans;
2296 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2297 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002298}
2299
2300static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2301{
2302 struct gsm48_hdr *gh = msgb_l3(msg);
2303 u_int8_t msg_type = gh->msg_type & 0xbf;
2304 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2305 struct tlv_parsed tp;
2306 struct gsm_mncc setup;
2307
2308 memset(&setup, 0, sizeof(struct gsm_mncc));
2309 setup.callref = trans->callref;
2310 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2311 /* emergency setup is identified by msg_type */
2312 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2313 setup.emergency = 1;
2314
2315 /* use subscriber as calling party number */
2316 if (trans->subscr) {
2317 setup.fields |= MNCC_F_CALLING;
2318 strncpy(setup.calling.number, trans->subscr->extension,
2319 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002320 strncpy(setup.imsi, trans->subscr->imsi,
2321 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002322 }
2323 /* bearer capability */
2324 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2325 setup.fields |= MNCC_F_BEARER_CAP;
2326 decode_bearer_cap(&setup.bearer_cap,
2327 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2328 }
2329 /* facility */
2330 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2331 setup.fields |= MNCC_F_FACILITY;
2332 decode_facility(&setup.facility,
2333 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2334 }
2335 /* called party bcd number */
2336 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2337 setup.fields |= MNCC_F_CALLED;
2338 decode_called(&setup.called,
2339 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2340 }
2341 /* user-user */
2342 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2343 setup.fields |= MNCC_F_USERUSER;
2344 decode_useruser(&setup.useruser,
2345 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2346 }
2347 /* ss-version */
2348 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2349 setup.fields |= MNCC_F_SSVERSION;
2350 decode_ssversion(&setup.ssversion,
2351 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2352 }
2353 /* CLIR suppression */
2354 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2355 setup.clir.sup = 1;
2356 /* CLIR invocation */
2357 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2358 setup.clir.inv = 1;
2359 /* cc cap */
2360 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2361 setup.fields |= MNCC_F_CCCAP;
2362 decode_cccap(&setup.cccap,
2363 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2364 }
2365
Harald Welte03740842009-06-10 23:11:52 +08002366 new_cc_state(trans, GSM_CSTATE_INITIATED);
2367
2368 /* indicate setup to MNCC */
Harald Welte0abe5a62009-07-23 19:06:52 +02002369 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002370
Harald Welteca745e22009-07-29 12:10:35 +02002371 /* MNCC code will modify the channel asynchronously, we should
2372 * ipaccess-bind only after the modification has been made to the
2373 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002374 return 0;
2375}
2376
2377static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002378{
2379 struct msgb *msg = gsm48_msgb_alloc();
2380 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002381 struct gsm_mncc *setup = arg;
Harald Welte165fc332009-07-23 21:36:44 +02002382 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002383
2384 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2385
Harald Welte03740842009-06-10 23:11:52 +08002386 /* transaction id must not be assigned */
2387 if (trans->transaction_id != 0xff) { /* unasssigned */
2388 DEBUGP(DCC, "TX Setup with assigned transaction. "
2389 "This is not allowed!\n");
2390 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002391 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002392 GSM48_CAUSE_LOC_PRN_S_LU,
2393 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002394 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002395 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002396 return rc;
2397 }
2398
2399 /* Get free transaction_id */
Harald Welte165fc332009-07-23 21:36:44 +02002400 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2401 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002402 /* no free transaction ID */
Harald Welte0abe5a62009-07-23 19:06:52 +02002403 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002404 GSM48_CAUSE_LOC_PRN_S_LU,
2405 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002406 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002407 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002408 return rc;
2409 }
Harald Welte165fc332009-07-23 21:36:44 +02002410 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002411
Harald Welte59b04682009-06-10 05:40:52 +08002412 gh->msg_type = GSM48_MT_CC_SETUP;
2413
Harald Welte03740842009-06-10 23:11:52 +08002414 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002415
Harald Welte03740842009-06-10 23:11:52 +08002416 /* bearer capability */
2417 if (setup->fields & MNCC_F_BEARER_CAP)
2418 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2419 /* facility */
2420 if (setup->fields & MNCC_F_FACILITY)
2421 encode_facility(msg, 0, &setup->facility);
2422 /* progress */
2423 if (setup->fields & MNCC_F_PROGRESS)
2424 encode_progress(msg, 0, &setup->progress);
2425 /* calling party BCD number */
2426 if (setup->fields & MNCC_F_CALLING)
2427 encode_calling(msg, &setup->calling);
2428 /* called party BCD number */
2429 if (setup->fields & MNCC_F_CALLED)
2430 encode_called(msg, &setup->called);
2431 /* user-user */
2432 if (setup->fields & MNCC_F_USERUSER)
2433 encode_useruser(msg, 0, &setup->useruser);
2434 /* redirecting party BCD number */
2435 if (setup->fields & MNCC_F_REDIRECTING)
2436 encode_redirecting(msg, &setup->redirecting);
2437 /* signal */
2438 if (setup->fields & MNCC_F_SIGNAL)
2439 encode_signal(msg, setup->signal);
2440
2441 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002442
Harald Welte36fe2e82009-07-23 21:13:03 +02002443 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002444}
2445
Harald Welte03740842009-06-10 23:11:52 +08002446static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2447{
2448 struct gsm48_hdr *gh = msgb_l3(msg);
2449 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2450 struct tlv_parsed tp;
2451 struct gsm_mncc call_conf;
2452
2453 gsm48_stop_cc_timer(trans);
2454 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2455
2456 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2457 call_conf.callref = trans->callref;
2458 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2459#if 0
2460 /* repeat */
2461 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2462 call_conf.repeat = 1;
2463 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2464 call_conf.repeat = 2;
2465#endif
2466 /* bearer capability */
2467 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2468 call_conf.fields |= MNCC_F_BEARER_CAP;
2469 decode_bearer_cap(&call_conf.bearer_cap,
2470 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2471 }
2472 /* cause */
2473 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2474 call_conf.fields |= MNCC_F_CAUSE;
2475 decode_cause(&call_conf.cause,
2476 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2477 }
2478 /* cc cap */
2479 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2480 call_conf.fields |= MNCC_F_CCCAP;
2481 decode_cccap(&call_conf.cccap,
2482 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2483 }
2484
2485 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2486
Harald Welte0abe5a62009-07-23 19:06:52 +02002487 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2488 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002489}
2490
2491static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2492{
2493 struct gsm_mncc *proceeding = arg;
2494 struct msgb *msg = gsm48_msgb_alloc();
2495 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2496
Harald Welte03740842009-06-10 23:11:52 +08002497 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2498
2499 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2500
2501 /* bearer capability */
2502 if (proceeding->fields & MNCC_F_BEARER_CAP)
2503 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2504 /* facility */
2505 if (proceeding->fields & MNCC_F_FACILITY)
2506 encode_facility(msg, 0, &proceeding->facility);
2507 /* progress */
2508 if (proceeding->fields & MNCC_F_PROGRESS)
2509 encode_progress(msg, 0, &proceeding->progress);
2510
Harald Welte36fe2e82009-07-23 21:13:03 +02002511 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002512}
2513
2514static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2515{
2516 struct gsm48_hdr *gh = msgb_l3(msg);
2517 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2518 struct tlv_parsed tp;
2519 struct gsm_mncc alerting;
2520
2521 gsm48_stop_cc_timer(trans);
2522 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2523
2524 memset(&alerting, 0, sizeof(struct gsm_mncc));
2525 alerting.callref = trans->callref;
2526 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2527 /* facility */
2528 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2529 alerting.fields |= MNCC_F_FACILITY;
2530 decode_facility(&alerting.facility,
2531 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2532 }
2533
2534 /* progress */
2535 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2536 alerting.fields |= MNCC_F_PROGRESS;
2537 decode_progress(&alerting.progress,
2538 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2539 }
2540 /* ss-version */
2541 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2542 alerting.fields |= MNCC_F_SSVERSION;
2543 decode_ssversion(&alerting.ssversion,
2544 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2545 }
2546
2547 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2548
Harald Welte0abe5a62009-07-23 19:06:52 +02002549 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2550 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002551}
2552
2553static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2554{
2555 struct gsm_mncc *alerting = arg;
2556 struct msgb *msg = gsm48_msgb_alloc();
2557 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2558
Harald Welte03740842009-06-10 23:11:52 +08002559 gh->msg_type = GSM48_MT_CC_ALERTING;
2560
2561 /* facility */
2562 if (alerting->fields & MNCC_F_FACILITY)
2563 encode_facility(msg, 0, &alerting->facility);
2564 /* progress */
2565 if (alerting->fields & MNCC_F_PROGRESS)
2566 encode_progress(msg, 0, &alerting->progress);
2567 /* user-user */
2568 if (alerting->fields & MNCC_F_USERUSER)
2569 encode_useruser(msg, 0, &alerting->useruser);
2570
2571 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2572
Harald Welte36fe2e82009-07-23 21:13:03 +02002573 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002574}
2575
2576static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2577{
2578 struct gsm_mncc *progress = arg;
2579 struct msgb *msg = gsm48_msgb_alloc();
2580 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2581
Harald Welte03740842009-06-10 23:11:52 +08002582 gh->msg_type = GSM48_MT_CC_PROGRESS;
2583
2584 /* progress */
2585 encode_progress(msg, 1, &progress->progress);
2586 /* user-user */
2587 if (progress->fields & MNCC_F_USERUSER)
2588 encode_useruser(msg, 0, &progress->useruser);
2589
Harald Welte36fe2e82009-07-23 21:13:03 +02002590 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002591}
2592
2593static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2594{
2595 struct gsm_mncc *connect = arg;
2596 struct msgb *msg = gsm48_msgb_alloc();
2597 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2598
Harald Welte03740842009-06-10 23:11:52 +08002599 gh->msg_type = GSM48_MT_CC_CONNECT;
2600
2601 gsm48_stop_cc_timer(trans);
2602 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2603
2604 /* facility */
2605 if (connect->fields & MNCC_F_FACILITY)
2606 encode_facility(msg, 0, &connect->facility);
2607 /* progress */
2608 if (connect->fields & MNCC_F_PROGRESS)
2609 encode_progress(msg, 0, &connect->progress);
2610 /* connected number */
2611 if (connect->fields & MNCC_F_CONNECTED)
2612 encode_connected(msg, &connect->connected);
2613 /* user-user */
2614 if (connect->fields & MNCC_F_USERUSER)
2615 encode_useruser(msg, 0, &connect->useruser);
2616
2617 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2618
Harald Welte36fe2e82009-07-23 21:13:03 +02002619 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002620}
2621
2622static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2623{
2624 struct gsm48_hdr *gh = msgb_l3(msg);
2625 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2626 struct tlv_parsed tp;
2627 struct gsm_mncc connect;
2628
2629 gsm48_stop_cc_timer(trans);
2630
2631 memset(&connect, 0, sizeof(struct gsm_mncc));
2632 connect.callref = trans->callref;
2633 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2634 /* use subscriber as connected party number */
2635 if (trans->subscr) {
2636 connect.fields |= MNCC_F_CONNECTED;
2637 strncpy(connect.connected.number, trans->subscr->extension,
2638 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002639 strncpy(connect.imsi, trans->subscr->imsi,
2640 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002641 }
2642 /* facility */
2643 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2644 connect.fields |= MNCC_F_FACILITY;
2645 decode_facility(&connect.facility,
2646 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2647 }
2648 /* user-user */
2649 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2650 connect.fields |= MNCC_F_USERUSER;
2651 decode_useruser(&connect.useruser,
2652 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2653 }
2654 /* ss-version */
2655 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2656 connect.fields |= MNCC_F_SSVERSION;
2657 decode_ssversion(&connect.ssversion,
2658 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2659 }
2660
2661 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2662
Harald Welte0abe5a62009-07-23 19:06:52 +02002663 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002664}
2665
2666
2667static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2668{
2669 struct gsm_mncc connect_ack;
2670
2671 gsm48_stop_cc_timer(trans);
2672
2673 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2674
2675 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2676 connect_ack.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002677 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002678 &connect_ack);
2679}
2680
2681static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2682{
2683 struct msgb *msg = gsm48_msgb_alloc();
2684 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2685
Harald Welte03740842009-06-10 23:11:52 +08002686 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2687
2688 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2689
Harald Welte36fe2e82009-07-23 21:13:03 +02002690 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002691}
2692
2693static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2694{
2695 struct gsm48_hdr *gh = msgb_l3(msg);
2696 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2697 struct tlv_parsed tp;
2698 struct gsm_mncc disc;
2699
2700 gsm48_stop_cc_timer(trans);
2701
2702 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2703
2704 memset(&disc, 0, sizeof(struct gsm_mncc));
2705 disc.callref = trans->callref;
2706 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2707 /* cause */
2708 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2709 disc.fields |= MNCC_F_CAUSE;
2710 decode_cause(&disc.cause,
2711 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2712 }
2713 /* facility */
2714 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2715 disc.fields |= MNCC_F_FACILITY;
2716 decode_facility(&disc.facility,
2717 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2718 }
2719 /* user-user */
2720 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2721 disc.fields |= MNCC_F_USERUSER;
2722 decode_useruser(&disc.useruser,
2723 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2724 }
2725 /* ss-version */
2726 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2727 disc.fields |= MNCC_F_SSVERSION;
2728 decode_ssversion(&disc.ssversion,
2729 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2730 }
2731
Harald Welte0abe5a62009-07-23 19:06:52 +02002732 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002733
2734}
2735
Harald Weltebbc636a2009-06-11 14:23:20 +08002736static struct gsm_mncc_cause default_cause = {
2737 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2738 .coding = 0,
2739 .rec = 0,
2740 .rec_val = 0,
2741 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2742 .diag_len = 0,
2743 .diag = { 0 },
2744};
Harald Welte03740842009-06-10 23:11:52 +08002745
2746static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2747{
2748 struct gsm_mncc *disc = arg;
2749 struct msgb *msg = gsm48_msgb_alloc();
2750 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2751
Harald Welte03740842009-06-10 23:11:52 +08002752 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2753
2754 gsm48_stop_cc_timer(trans);
2755 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2756
2757 /* cause */
2758 if (disc->fields & MNCC_F_CAUSE)
2759 encode_cause(msg, 1, &disc->cause);
2760 else
2761 encode_cause(msg, 1, &default_cause);
2762
2763 /* facility */
2764 if (disc->fields & MNCC_F_FACILITY)
2765 encode_facility(msg, 0, &disc->facility);
2766 /* progress */
2767 if (disc->fields & MNCC_F_PROGRESS)
2768 encode_progress(msg, 0, &disc->progress);
2769 /* user-user */
2770 if (disc->fields & MNCC_F_USERUSER)
2771 encode_useruser(msg, 0, &disc->useruser);
2772
2773 /* store disconnect cause for T306 expiry */
Harald Weltec2189a62009-07-23 18:56:43 +02002774 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002775
2776 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2777
Harald Welte36fe2e82009-07-23 21:13:03 +02002778 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002779}
2780
2781static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2782{
2783 struct gsm48_hdr *gh = msgb_l3(msg);
2784 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2785 struct tlv_parsed tp;
2786 struct gsm_mncc rel;
2787 int rc;
2788
2789 gsm48_stop_cc_timer(trans);
2790
2791 memset(&rel, 0, sizeof(struct gsm_mncc));
2792 rel.callref = trans->callref;
2793 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2794 /* cause */
2795 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2796 rel.fields |= MNCC_F_CAUSE;
2797 decode_cause(&rel.cause,
2798 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2799 }
2800 /* facility */
2801 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2802 rel.fields |= MNCC_F_FACILITY;
2803 decode_facility(&rel.facility,
2804 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2805 }
2806 /* user-user */
2807 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2808 rel.fields |= MNCC_F_USERUSER;
2809 decode_useruser(&rel.useruser,
2810 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2811 }
2812 /* ss-version */
2813 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2814 rel.fields |= MNCC_F_SSVERSION;
2815 decode_ssversion(&rel.ssversion,
2816 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2817 }
2818
Harald Weltec2189a62009-07-23 18:56:43 +02002819 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002820 /* release collision 5.4.5 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002821 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002822 } else {
Harald Welte0abe5a62009-07-23 19:06:52 +02002823 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002824 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte0abe5a62009-07-23 19:06:52 +02002825 GSM48_MT_CC_RELEASE_COMPL);
2826 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002827 }
2828
2829 new_cc_state(trans, GSM_CSTATE_NULL);
2830
2831 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002832 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002833
2834 return rc;
2835}
2836
2837static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2838{
2839 struct gsm_mncc *rel = arg;
2840 struct msgb *msg = gsm48_msgb_alloc();
2841 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2842
Harald Welte03740842009-06-10 23:11:52 +08002843 gh->msg_type = GSM48_MT_CC_RELEASE;
2844
2845 trans->callref = 0;
2846
2847 gsm48_stop_cc_timer(trans);
2848 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2849
2850 /* cause */
2851 if (rel->fields & MNCC_F_CAUSE)
2852 encode_cause(msg, 0, &rel->cause);
2853 /* facility */
2854 if (rel->fields & MNCC_F_FACILITY)
2855 encode_facility(msg, 0, &rel->facility);
2856 /* user-user */
2857 if (rel->fields & MNCC_F_USERUSER)
2858 encode_useruser(msg, 0, &rel->useruser);
2859
Harald Weltec2189a62009-07-23 18:56:43 +02002860 trans->cc.T308_second = 0;
2861 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002862
Harald Weltec2189a62009-07-23 18:56:43 +02002863 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002864 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2865
Harald Welte36fe2e82009-07-23 21:13:03 +02002866 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002867}
2868
2869static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2870{
2871 struct gsm48_hdr *gh = msgb_l3(msg);
2872 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2873 struct tlv_parsed tp;
2874 struct gsm_mncc rel;
2875 int rc = 0;
2876
2877 gsm48_stop_cc_timer(trans);
2878
2879 memset(&rel, 0, sizeof(struct gsm_mncc));
2880 rel.callref = trans->callref;
2881 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2882 /* cause */
2883 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2884 rel.fields |= MNCC_F_CAUSE;
2885 decode_cause(&rel.cause,
2886 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2887 }
2888 /* facility */
2889 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2890 rel.fields |= MNCC_F_FACILITY;
2891 decode_facility(&rel.facility,
2892 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2893 }
2894 /* user-user */
2895 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2896 rel.fields |= MNCC_F_USERUSER;
2897 decode_useruser(&rel.useruser,
2898 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2899 }
2900 /* ss-version */
2901 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2902 rel.fields |= MNCC_F_SSVERSION;
2903 decode_ssversion(&rel.ssversion,
2904 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2905 }
2906
2907 if (trans->callref) {
Harald Weltec2189a62009-07-23 18:56:43 +02002908 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08002909 case GSM_CSTATE_CALL_PRESENT:
Harald Welte0abe5a62009-07-23 19:06:52 +02002910 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002911 MNCC_REJ_IND, &rel);
2912 break;
2913 case GSM_CSTATE_RELEASE_REQ:
Harald Welte0abe5a62009-07-23 19:06:52 +02002914 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002915 MNCC_REL_CNF, &rel);
2916 break;
2917 default:
Harald Welte0abe5a62009-07-23 19:06:52 +02002918 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08002919 MNCC_REL_IND, &rel);
2920 }
2921 }
2922
2923 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002924 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002925
2926 return rc;
2927}
2928
2929static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2930{
2931 struct gsm_mncc *rel = arg;
2932 struct msgb *msg = gsm48_msgb_alloc();
2933 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2934
Harald Welte03740842009-06-10 23:11:52 +08002935 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2936
2937 trans->callref = 0;
2938
2939 gsm48_stop_cc_timer(trans);
2940
2941 /* cause */
2942 if (rel->fields & MNCC_F_CAUSE)
2943 encode_cause(msg, 0, &rel->cause);
2944 /* facility */
2945 if (rel->fields & MNCC_F_FACILITY)
2946 encode_facility(msg, 0, &rel->facility);
2947 /* user-user */
2948 if (rel->fields & MNCC_F_USERUSER)
2949 encode_useruser(msg, 0, &rel->useruser);
2950
Harald Weltec2189a62009-07-23 18:56:43 +02002951 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002952
Harald Welte36fe2e82009-07-23 21:13:03 +02002953 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002954}
2955
2956static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2957{
2958 struct gsm48_hdr *gh = msgb_l3(msg);
2959 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2960 struct tlv_parsed tp;
2961 struct gsm_mncc fac;
2962
2963 memset(&fac, 0, sizeof(struct gsm_mncc));
2964 fac.callref = trans->callref;
2965 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2966 /* facility */
2967 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2968 fac.fields |= MNCC_F_FACILITY;
2969 decode_facility(&fac.facility,
2970 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2971 }
2972 /* ss-version */
2973 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2974 fac.fields |= MNCC_F_SSVERSION;
2975 decode_ssversion(&fac.ssversion,
2976 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2977 }
2978
Harald Welte0abe5a62009-07-23 19:06:52 +02002979 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08002980}
2981
2982static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2983{
2984 struct gsm_mncc *fac = arg;
2985 struct msgb *msg = gsm48_msgb_alloc();
2986 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2987
Harald Welte03740842009-06-10 23:11:52 +08002988 gh->msg_type = GSM48_MT_CC_FACILITY;
2989
2990 /* facility */
2991 encode_facility(msg, 1, &fac->facility);
2992
Harald Welte36fe2e82009-07-23 21:13:03 +02002993 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002994}
2995
2996static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2997{
2998 struct gsm_mncc hold;
2999
3000 memset(&hold, 0, sizeof(struct gsm_mncc));
3001 hold.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003002 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08003003}
3004
3005static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3006{
3007 struct msgb *msg = gsm48_msgb_alloc();
3008 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3009
Harald Welte03740842009-06-10 23:11:52 +08003010 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3011
Harald Welte36fe2e82009-07-23 21:13:03 +02003012 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003013}
3014
3015static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3016{
3017 struct gsm_mncc *hold_rej = arg;
3018 struct msgb *msg = gsm48_msgb_alloc();
3019 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3020
Harald Welte03740842009-06-10 23:11:52 +08003021 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3022
3023 /* cause */
3024 if (hold_rej->fields & MNCC_F_CAUSE)
3025 encode_cause(msg, 1, &hold_rej->cause);
3026 else
3027 encode_cause(msg, 1, &default_cause);
3028
Harald Welte36fe2e82009-07-23 21:13:03 +02003029 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003030}
3031
3032static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3033{
3034 struct gsm_mncc retrieve;
3035
3036 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3037 retrieve.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003038 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3039 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08003040}
3041
3042static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3043{
3044 struct msgb *msg = gsm48_msgb_alloc();
3045 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3046
Harald Welte03740842009-06-10 23:11:52 +08003047 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3048
Harald Welte36fe2e82009-07-23 21:13:03 +02003049 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003050}
3051
3052static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3053{
3054 struct gsm_mncc *retrieve_rej = arg;
3055 struct msgb *msg = gsm48_msgb_alloc();
3056 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3057
Harald Welte03740842009-06-10 23:11:52 +08003058 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3059
3060 /* cause */
3061 if (retrieve_rej->fields & MNCC_F_CAUSE)
3062 encode_cause(msg, 1, &retrieve_rej->cause);
3063 else
3064 encode_cause(msg, 1, &default_cause);
3065
Harald Welte36fe2e82009-07-23 21:13:03 +02003066 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003067}
3068
3069static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3070{
3071 struct gsm48_hdr *gh = msgb_l3(msg);
3072 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3073 struct tlv_parsed tp;
3074 struct gsm_mncc dtmf;
3075
3076 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3077 dtmf.callref = trans->callref;
3078 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3079 /* keypad facility */
3080 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3081 dtmf.fields |= MNCC_F_KEYPAD;
3082 decode_keypad(&dtmf.keypad,
3083 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3084 }
3085
Harald Welte0abe5a62009-07-23 19:06:52 +02003086 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003087}
3088
3089static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3090{
3091 struct gsm_mncc *dtmf = arg;
3092 struct msgb *msg = gsm48_msgb_alloc();
3093 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3094
Harald Welte03740842009-06-10 23:11:52 +08003095 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3096
3097 /* keypad */
3098 if (dtmf->fields & MNCC_F_KEYPAD)
3099 encode_keypad(msg, dtmf->keypad);
3100
Harald Welte36fe2e82009-07-23 21:13:03 +02003101 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003102}
3103
3104static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3105{
3106 struct gsm_mncc *dtmf = arg;
3107 struct msgb *msg = gsm48_msgb_alloc();
3108 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3109
Harald Welte03740842009-06-10 23:11:52 +08003110 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3111
3112 /* cause */
3113 if (dtmf->fields & MNCC_F_CAUSE)
3114 encode_cause(msg, 1, &dtmf->cause);
3115 else
3116 encode_cause(msg, 1, &default_cause);
3117
Harald Welte36fe2e82009-07-23 21:13:03 +02003118 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003119}
3120
3121static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3122{
3123 struct msgb *msg = gsm48_msgb_alloc();
3124 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3125
Harald Welte03740842009-06-10 23:11:52 +08003126 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3127
Harald Welte36fe2e82009-07-23 21:13:03 +02003128 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003129}
3130
3131static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3132{
3133 struct gsm_mncc dtmf;
3134
3135 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3136 dtmf.callref = trans->callref;
3137
Harald Welte0abe5a62009-07-23 19:06:52 +02003138 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003139}
3140
3141static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3142{
3143 struct gsm48_hdr *gh = msgb_l3(msg);
3144 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3145 struct tlv_parsed tp;
3146 struct gsm_mncc modify;
3147
3148 memset(&modify, 0, sizeof(struct gsm_mncc));
3149 modify.callref = trans->callref;
3150 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3151 /* bearer capability */
3152 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3153 modify.fields |= MNCC_F_BEARER_CAP;
3154 decode_bearer_cap(&modify.bearer_cap,
3155 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3156 }
3157
3158 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3159
Harald Welte0abe5a62009-07-23 19:06:52 +02003160 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003161}
3162
3163static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3164{
3165 struct gsm_mncc *modify = arg;
3166 struct msgb *msg = gsm48_msgb_alloc();
3167 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3168
Harald Welte03740842009-06-10 23:11:52 +08003169 gh->msg_type = GSM48_MT_CC_MODIFY;
3170
3171 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3172
3173 /* bearer capability */
3174 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3175
3176 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3177
Harald Welte36fe2e82009-07-23 21:13:03 +02003178 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003179}
3180
3181static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3182{
3183 struct gsm48_hdr *gh = msgb_l3(msg);
3184 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3185 struct tlv_parsed tp;
3186 struct gsm_mncc modify;
3187
3188 gsm48_stop_cc_timer(trans);
3189
3190 memset(&modify, 0, sizeof(struct gsm_mncc));
3191 modify.callref = trans->callref;
3192 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3193 /* bearer capability */
3194 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3195 modify.fields |= MNCC_F_BEARER_CAP;
3196 decode_bearer_cap(&modify.bearer_cap,
3197 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3198 }
3199
3200 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3201
Harald Welte0abe5a62009-07-23 19:06:52 +02003202 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003203}
3204
3205static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3206{
3207 struct gsm_mncc *modify = arg;
3208 struct msgb *msg = gsm48_msgb_alloc();
3209 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3210
Harald Welte03740842009-06-10 23:11:52 +08003211 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3212
3213 /* bearer capability */
3214 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3215
3216 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3217
Harald Welte36fe2e82009-07-23 21:13:03 +02003218 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003219}
3220
3221static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3222{
3223 struct gsm48_hdr *gh = msgb_l3(msg);
3224 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3225 struct tlv_parsed tp;
3226 struct gsm_mncc modify;
3227
3228 gsm48_stop_cc_timer(trans);
3229
3230 memset(&modify, 0, sizeof(struct gsm_mncc));
3231 modify.callref = trans->callref;
3232 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3233 /* bearer capability */
3234 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3235 modify.fields |= GSM48_IE_BEARER_CAP;
3236 decode_bearer_cap(&modify.bearer_cap,
3237 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3238 }
3239 /* cause */
3240 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3241 modify.fields |= MNCC_F_CAUSE;
3242 decode_cause(&modify.cause,
3243 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3244 }
3245
3246 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3247
Harald Welte0abe5a62009-07-23 19:06:52 +02003248 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003249}
3250
3251static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3252{
3253 struct gsm_mncc *modify = arg;
3254 struct msgb *msg = gsm48_msgb_alloc();
3255 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3256
Harald Welte03740842009-06-10 23:11:52 +08003257 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3258
3259 /* bearer capability */
3260 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3261 /* cause */
3262 encode_cause(msg, 1, &modify->cause);
3263
3264 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3265
Harald Welte36fe2e82009-07-23 21:13:03 +02003266 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003267}
3268
3269static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3270{
3271 struct gsm_mncc *notify = arg;
3272 struct msgb *msg = gsm48_msgb_alloc();
3273 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3274
Harald Welte03740842009-06-10 23:11:52 +08003275 gh->msg_type = GSM48_MT_CC_NOTIFY;
3276
3277 /* notify */
3278 encode_notify(msg, notify->notify);
3279
Harald Welte36fe2e82009-07-23 21:13:03 +02003280 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003281}
3282
3283static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3284{
3285 struct gsm48_hdr *gh = msgb_l3(msg);
3286 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3287// struct tlv_parsed tp;
3288 struct gsm_mncc notify;
3289
3290 memset(&notify, 0, sizeof(struct gsm_mncc));
3291 notify.callref = trans->callref;
3292// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3293 if (payload_len >= 1)
3294 decode_notify(&notify.notify, gh->data);
3295
Harald Welte0abe5a62009-07-23 19:06:52 +02003296 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003297}
3298
3299static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3300{
3301 struct gsm_mncc *user = arg;
3302 struct msgb *msg = gsm48_msgb_alloc();
3303 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3304
Harald Welte03740842009-06-10 23:11:52 +08003305 gh->msg_type = GSM48_MT_CC_USER_INFO;
3306
3307 /* user-user */
3308 if (user->fields & MNCC_F_USERUSER)
3309 encode_useruser(msg, 1, &user->useruser);
3310 /* more data */
3311 if (user->more)
3312 encode_more(msg);
3313
Harald Welte36fe2e82009-07-23 21:13:03 +02003314 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003315}
3316
3317static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3318{
3319 struct gsm48_hdr *gh = msgb_l3(msg);
3320 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3321 struct tlv_parsed tp;
3322 struct gsm_mncc user;
3323
3324 memset(&user, 0, sizeof(struct gsm_mncc));
3325 user.callref = trans->callref;
3326 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3327 /* user-user */
3328 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3329 user.fields |= MNCC_F_USERUSER;
3330 decode_useruser(&user.useruser,
3331 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3332 }
3333 /* more data */
3334 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3335 user.more = 1;
3336
Harald Welte0abe5a62009-07-23 19:06:52 +02003337 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003338}
3339
3340static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3341{
3342 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003343 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003344
Harald Welteca745e22009-07-29 12:10:35 +02003345 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3346 if (rc < 0)
3347 return rc;
3348
3349 /* FIXME: we not only need to do this after mode modify, but
3350 * also after channel activation */
3351 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3352 mode->lchan_mode != GSM48_CMODE_SIGN)
3353 rc = rsl_ipacc_bind(trans->lchan);
3354
3355 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003356}
3357
3358static struct downstate {
3359 u_int32_t states;
3360 int type;
3361 int (*rout) (struct gsm_trans *trans, void *arg);
3362} downstatelist[] = {
3363 /* mobile originating call establishment */
3364 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3365 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3366 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3367 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3368 {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 */
3369 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3370 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3371 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3372 /* mobile terminating call establishment */
3373 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3374 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3375 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3376 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3377 /* signalling during call */
3378 {SBIT(GSM_CSTATE_ACTIVE),
3379 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3380 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3381 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3382 {ALL_STATES,
3383 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3384 {ALL_STATES,
3385 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3386 {ALL_STATES,
3387 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3388 {SBIT(GSM_CSTATE_ACTIVE),
3389 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3390 {SBIT(GSM_CSTATE_ACTIVE),
3391 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3392 {SBIT(GSM_CSTATE_ACTIVE),
3393 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3394 {SBIT(GSM_CSTATE_ACTIVE),
3395 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3396 {SBIT(GSM_CSTATE_ACTIVE),
3397 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3398 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3399 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3400 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3401 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3402 {SBIT(GSM_CSTATE_ACTIVE),
3403 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3404 /* clearing */
3405 {SBIT(GSM_CSTATE_INITIATED),
3406 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3407 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3408 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3409 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3410 MNCC_REL_REQ, gsm48_cc_tx_release},
3411 /* special */
3412 {ALL_STATES,
3413 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3414};
3415
3416#define DOWNSLLEN \
3417 (sizeof(downstatelist) / sizeof(struct downstate))
3418
3419
3420int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3421{
Harald Welteaa60edb2009-08-09 18:52:33 +02003422 int i, rc = 0;
Harald Welte03740842009-06-10 23:11:52 +08003423 struct gsm_trans *trans = NULL, *transt;
3424 struct gsm_subscriber *subscr;
Harald Welteaa60edb2009-08-09 18:52:33 +02003425 struct gsm_lchan *lchan = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003426 struct gsm_bts *bts = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003427 struct gsm_mncc *data = arg, rel;
3428
3429 /* handle special messages */
3430 switch(msg_type) {
3431 case MNCC_BRIDGE:
3432 return tch_bridge(net, arg);
3433 case MNCC_FRAME_DROP:
3434 return tch_recv(net, arg, 0);
3435 case MNCC_FRAME_RECV:
3436 return tch_recv(net, arg, 1);
3437 case GSM_TRAU_FRAME:
3438 return tch_frame(net, arg);
3439 }
3440
3441 memset(&rel, 0, sizeof(struct gsm_mncc));
3442 rel.callref = data->callref;
3443
3444 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02003445 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003446
3447 /* Callref unknown */
3448 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003449 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003450 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3451 "Received '%s' from MNCC with "
3452 "unknown callref %d\n", data->called.number,
3453 get_mncc_name(msg_type), data->callref);
3454 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003455 return mncc_release_ind(net, NULL, data->callref,
3456 GSM48_CAUSE_LOC_PRN_S_LU,
3457 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003458 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003459 if (!data->called.number[0] && !data->imsi[0]) {
3460 DEBUGP(DCC, "(bts - trx - ts - ti) "
3461 "Received '%s' from MNCC with "
3462 "no number or IMSI\n", get_mncc_name(msg_type));
3463 /* Invalid number */
3464 return mncc_release_ind(net, NULL, data->callref,
3465 GSM48_CAUSE_LOC_PRN_S_LU,
3466 GSM48_CC_CAUSE_INV_NR_FORMAT);
3467 }
Harald Welte03740842009-06-10 23:11:52 +08003468 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003469 if (data->called.number[0])
Harald Welte75350412009-07-23 18:46:00 +02003470 subscr = subscr_get_by_extension(net,
3471 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003472 else
Harald Welte75350412009-07-23 18:46:00 +02003473 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003474 /* If subscriber is not found */
3475 if (!subscr) {
3476 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3477 "Received '%s' from MNCC with "
3478 "unknown subscriber %s\n", data->called.number,
3479 get_mncc_name(msg_type), data->called.number);
3480 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003481 return mncc_release_ind(net, NULL, data->callref,
3482 GSM48_CAUSE_LOC_PRN_S_LU,
3483 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003484 }
3485 /* If subscriber is not "attached" */
3486 if (!subscr->lac) {
3487 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3488 "Received '%s' from MNCC with "
3489 "detached subscriber %s\n", data->called.number,
3490 get_mncc_name(msg_type), data->called.number);
3491 subscr_put(subscr);
3492 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003493 return mncc_release_ind(net, NULL, data->callref,
3494 GSM48_CAUSE_LOC_PRN_S_LU,
3495 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003496 }
3497 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003498 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3499 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003500 DEBUGP(DCC, "No memory for trans.\n");
3501 subscr_put(subscr);
3502 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003503 mncc_release_ind(net, NULL, data->callref,
3504 GSM48_CAUSE_LOC_PRN_S_LU,
3505 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003506 return -ENOMEM;
3507 }
Harald Welte03740842009-06-10 23:11:52 +08003508 /* Find lchan */
Harald Welteaa60edb2009-08-09 18:52:33 +02003509 lchan = lchan_for_subscr(subscr);
Harald Welte03740842009-06-10 23:11:52 +08003510 /* If subscriber has no lchan */
3511 if (!lchan) {
3512 /* find transaction with this subscriber already paging */
3513 llist_for_each_entry(transt, &net->trans_list, entry) {
3514 /* Transaction of our lchan? */
3515 if (transt == trans ||
3516 transt->subscr != subscr)
3517 continue;
3518 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3519 "Received '%s' from MNCC with "
3520 "unallocated channel, paging already "
3521 "started.\n", bts->nr,
3522 data->called.number,
3523 get_mncc_name(msg_type));
3524 return 0;
3525 }
3526 /* store setup informations until paging was successfull */
Harald Weltec2189a62009-07-23 18:56:43 +02003527 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte2a3a81b2009-08-01 19:31:47 +02003528 /* Trigger paging */
3529 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3530 setup_trig_pag_evt, subscr);
Harald Welte03740842009-06-10 23:11:52 +08003531 return 0;
3532 }
3533 /* Assign lchan */
3534 trans->lchan = lchan;
3535 use_lchan(lchan);
3536 }
3537 lchan = trans->lchan;
3538
3539 /* if paging did not respond yet */
3540 if (!lchan) {
3541 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3542 "Received '%s' from MNCC in paging state\n",
3543 (trans->subscr)?(trans->subscr->extension):"-",
3544 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003545 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3546 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003547 if (msg_type == MNCC_REL_REQ)
3548 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3549 else
3550 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3551 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003552 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003553 return rc;
3554 }
3555
3556 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3557 "Received '%s' from MNCC in state %d (%s)\n",
3558 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3559 trans->transaction_id,
3560 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003561 get_mncc_name(msg_type), trans->cc.state,
3562 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003563
3564 /* Find function for current state and message */
3565 for (i = 0; i < DOWNSLLEN; i++)
3566 if ((msg_type == downstatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003567 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003568 break;
3569 if (i == DOWNSLLEN) {
3570 DEBUGP(DCC, "Message unhandled at this state.\n");
3571 return 0;
3572 }
3573
3574 rc = downstatelist[i].rout(trans, arg);
3575
3576 return rc;
3577}
3578
3579
3580static struct datastate {
3581 u_int32_t states;
3582 int type;
3583 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3584} datastatelist[] = {
3585 /* mobile originating call establishment */
3586 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3587 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3588 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3589 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3590 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3591 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3592 /* mobile terminating call establishment */
3593 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3594 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3595 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3596 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3597 {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 */
3598 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3599 /* signalling during call */
3600 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3601 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3602 {SBIT(GSM_CSTATE_ACTIVE),
3603 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3604 {ALL_STATES,
3605 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3606 {ALL_STATES,
3607 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3608 {ALL_STATES,
3609 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3610 {SBIT(GSM_CSTATE_ACTIVE),
3611 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3612 {SBIT(GSM_CSTATE_ACTIVE),
3613 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3614 {SBIT(GSM_CSTATE_ACTIVE),
3615 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3616 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3617 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3618 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3619 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3620 {SBIT(GSM_CSTATE_ACTIVE),
3621 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3622 /* clearing */
3623 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3624 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3625 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3626 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3627 {ALL_STATES, /* 5.4.3.4 */
3628 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3629};
3630
3631#define DATASLLEN \
3632 (sizeof(datastatelist) / sizeof(struct datastate))
3633
Harald Welte59b04682009-06-10 05:40:52 +08003634static int gsm0408_rcv_cc(struct msgb *msg)
3635{
3636 struct gsm48_hdr *gh = msgb_l3(msg);
3637 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003638 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003639 struct gsm_lchan *lchan = msg->lchan;
Harald Weltec2189a62009-07-23 18:56:43 +02003640 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003641 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003642
Harald Welte03740842009-06-10 23:11:52 +08003643 if (msg_type & 0x80) {
3644 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3645 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003646 }
Harald Welte03740842009-06-10 23:11:52 +08003647
3648 /* Find transaction */
Harald Welte0d824162009-07-23 21:58:40 +02003649 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltec2189a62009-07-23 18:56:43 +02003650
Harald Welte4861c822009-07-23 21:21:14 +02003651 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003652 "Received '%s' from MS in state %d (%s)\n",
3653 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3654 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003655 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3656 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003657
3658 /* Create transaction */
3659 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003660 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003661 "creating new trans.\n", transaction_id);
3662 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003663 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3664 transaction_id, new_callref++);
3665 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003666 DEBUGP(DCC, "No memory for trans.\n");
3667 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003668 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003669 GSM48_MT_CC_RELEASE_COMPL);
3670 return -ENOMEM;
3671 }
Harald Welte03740842009-06-10 23:11:52 +08003672 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003673 trans->lchan = lchan;
3674 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003675 }
3676
3677 /* find function for current state and message */
3678 for (i = 0; i < DATASLLEN; i++)
3679 if ((msg_type == datastatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003680 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003681 break;
3682 if (i == DATASLLEN) {
3683 DEBUGP(DCC, "Message unhandled at this state.\n");
3684 return 0;
3685 }
3686
3687 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003688
3689 return rc;
3690}
3691
3692/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3693int gsm0408_rcvmsg(struct msgb *msg)
3694{
3695 struct gsm48_hdr *gh = msgb_l3(msg);
3696 u_int8_t pdisc = gh->proto_discr & 0x0f;
3697 int rc = 0;
3698
3699 switch (pdisc) {
3700 case GSM48_PDISC_CC:
3701 rc = gsm0408_rcv_cc(msg);
3702 break;
3703 case GSM48_PDISC_MM:
3704 rc = gsm0408_rcv_mm(msg);
3705 break;
3706 case GSM48_PDISC_RR:
3707 rc = gsm0408_rcv_rr(msg);
3708 break;
3709 case GSM48_PDISC_SMS:
3710 rc = gsm0411_rcv_sms(msg);
3711 break;
3712 case GSM48_PDISC_MM_GPRS:
3713 case GSM48_PDISC_SM_GPRS:
3714 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3715 pdisc);
3716 break;
3717 default:
3718 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3719 pdisc);
3720 break;
3721 }
3722
3723 return rc;
3724}
3725
Harald Welte59b04682009-06-10 05:40:52 +08003726/* Section 9.1.8 / Table 9.9 */
3727struct chreq {
3728 u_int8_t val;
3729 u_int8_t mask;
3730 enum chreq_type type;
3731};
3732
3733/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3734static const struct chreq chreq_type_neci1[] = {
3735 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3736 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3737 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3738 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3739 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3740 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3741 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3742 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3743 { 0x10, 0xf0, CHREQ_T_SDCCH },
3744 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3745 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3746 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3747};
3748
3749/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3750static const struct chreq chreq_type_neci0[] = {
3751 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3752 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3753 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3754 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3755 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3756 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3757 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3758 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3759};
3760
3761static const enum gsm_chan_t ctype_by_chreq[] = {
3762 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3763 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3764 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3765 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3766 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3767 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3768 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3769 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3770 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3771 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3772 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3773 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3774};
3775
3776static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3777 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3778 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3779 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3780 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3781 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3782 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3783 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3784 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3785 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3786 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3787 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3788 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3789};
3790
3791enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3792{
3793 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003794 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003795
Harald Welte1ab707e2009-08-10 02:14:46 +02003796 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3797 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003798 if ((ra & chr->mask) == chr->val)
3799 return ctype_by_chreq[chr->type];
3800 }
3801 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3802 return GSM_LCHAN_SDCCH;
3803}
3804
3805enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3806{
3807 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003808 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003809
Harald Welte1ab707e2009-08-10 02:14:46 +02003810 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3811 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003812 if ((ra & chr->mask) == chr->val)
3813 return reason_by_chreq[chr->type];
3814 }
3815 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3816 return GSM_CHREQ_REASON_OTHER;
3817}
Harald Welte03740842009-06-10 23:11:52 +08003818
3819/* dequeue messages to layer 4 */
3820int bsc_upqueue(struct gsm_network *net)
3821{
3822 struct gsm_mncc *mncc;
3823 struct msgb *msg;
3824 int work = 0;
3825
3826 if (net)
3827 while ((msg = msgb_dequeue(&net->upqueue))) {
3828 mncc = (struct gsm_mncc *)msg->data;
3829 if (net->mncc_recv)
3830 net->mncc_recv(net, mncc->msg_type, mncc);
3831 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003832 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003833 }
3834
3835 return work;
3836}
Harald Weltec2189a62009-07-23 18:56:43 +02003837
Harald Welte3c062072009-07-28 18:25:29 +02003838/*
3839 * This will be ran by the linker when loading the DSO. We use it to
3840 * do system initialization, e.g. registration of signal handlers.
3841 */
3842static __attribute__((constructor)) void on_dso_load_0408(void)
3843{
3844 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3845 "loc_updating_oper");
3846 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3847 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3848}