blob: 46b447900d7f9d620e85d29c823da772e1e0a877 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <time.h>
31#include <netinet/in.h>
32
33#include <openbsc/db.h>
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
Daniel Willmannc8188202009-08-13 03:42:07 +020038#include <openbsc/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080039#include <openbsc/gsm_subscriber.h>
40#include <openbsc/gsm_04_11.h>
41#include <openbsc/gsm_04_08.h>
42#include <openbsc/abis_rsl.h>
43#include <openbsc/chan_alloc.h>
44#include <openbsc/paging.h>
45#include <openbsc/signal.h>
46#include <openbsc/trau_frame.h>
47#include <openbsc/trau_mux.h>
Harald Welte3c062072009-07-28 18:25:29 +020048#include <openbsc/rtp_proxy.h>
Harald Weltea8379772009-06-20 22:36:41 +020049#include <openbsc/talloc.h>
Harald Weltec2189a62009-07-23 18:56:43 +020050#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080051
52#define GSM48_ALLOC_SIZE 1024
53#define GSM48_ALLOC_HEADROOM 128
54
Harald Welteb8a18b52009-06-10 12:08:54 +080055#define GSM_MAX_FACILITY 128
56#define GSM_MAX_SSVERSION 128
57#define GSM_MAX_USERUSER 128
58
Harald Welte (local)8751ee92009-08-15 02:30:58 +020059void *tall_locop_ctx;
Harald Weltea8379772009-06-20 22:36:41 +020060
Harald Welte3c062072009-07-28 18:25:29 +020061/* should ip.access BTS use direct RTP streams between each other (1),
62 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
63int ipacc_rtp_direct = 1;
64
Harald Welte59b04682009-06-10 05:40:52 +080065static const struct tlv_definition rsl_att_tlvdef = {
66 .def = {
67 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
69 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
70 [GSM48_IE_UTC] = { TLV_TYPE_TV },
71 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
72 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
73
74 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
75 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
76 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
77 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
78 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
79 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
80 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welteb8a18b52009-06-10 12:08:54 +080081 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte59b04682009-06-10 05:40:52 +080082 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
83 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welteb8a18b52009-06-10 12:08:54 +080084 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte59b04682009-06-10 05:40:52 +080086 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
89 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
91 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
92 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
94 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
95 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
96 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
98 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
99 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welteb8a18b52009-06-10 12:08:54 +0800100 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
101 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte59b04682009-06-10 05:40:52 +0800102 /* FIXME: more elements */
103 },
104};
105
106static const char *rr_cause_names[] = {
107 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
108 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
109 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
110 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
111 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
112 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
113 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
114 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
115 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
116 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
117 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
118 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
119 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
120 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
121 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
122 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
123 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
124};
125
Harald Welte03740842009-06-10 23:11:52 +0800126static const char *cc_state_names[] = {
127 "NULL",
128 "INITIATED",
129 "illegal state 2",
130 "MO_CALL_PROC",
131 "CALL_DELIVERED",
132 "illegal state 5",
133 "CALL_PRESENT",
134 "CALL_RECEIVED",
135 "CONNECT_REQUEST",
136 "MO_TERM_CALL_CONF",
137 "ACTIVE",
138 "DISCONNECT_REQ",
139 "DISCONNECT_IND",
140 "illegal state 13",
141 "illegal state 14",
142 "illegal state 15",
143 "illegal state 16",
144 "illegal state 17",
145 "illegal state 18",
146 "RELEASE_REQ",
147 "illegal state 20",
148 "illegal state 21",
149 "illegal state 22",
150 "illegal state 23",
151 "illegal state 24",
152 "illegal state 25",
153 "MO_ORIG_MODIFY",
154 "MO_TERM_MODIFY",
155 "CONNECT_IND",
156 "illegal state 29",
157 "illegal state 30",
158 "illegal state 31",
159};
160
161static const char *cc_msg_names[] = {
162 "unknown 0x00",
163 "ALERTING",
164 "CALL_PROC",
165 "PROGRESS",
166 "ESTAB",
167 "SETUP",
168 "ESTAB_CONF",
169 "CONNECT",
170 "CALL_CONF",
171 "START_CC",
172 "unknown 0x0a",
173 "RECALL",
174 "unknown 0x0c",
175 "unknown 0x0d",
176 "EMERG_SETUP",
177 "CONNECT_ACK",
178 "USER_INFO",
179 "unknown 0x11",
180 "unknown 0x12",
181 "MODIFY_REJECT",
182 "unknown 0x14",
183 "unknown 0x15",
184 "unknown 0x16",
185 "MODIFY",
186 "HOLD",
187 "HOLD_ACK",
188 "HOLD_REJ",
189 "unknown 0x1b",
190 "RETR",
191 "RETR_ACK",
192 "RETR_REJ",
193 "MODIFY_COMPL",
194 "unknown 0x20",
195 "unknown 0x21",
196 "unknown 0x22",
197 "unknown 0x23",
198 "unknown 0x24",
199 "DISCONNECT",
200 "unknown 0x26",
201 "unknown 0x27",
202 "unknown 0x28",
203 "unknown 0x29",
204 "RELEASE_COMPL",
205 "unknown 0x2b",
206 "unknown 0x2c",
207 "RELEASE",
208 "unknown 0x2e",
209 "unknown 0x2f",
210 "unknown 0x30",
211 "STOP_DTMF",
212 "STOP_DTMF_ACK",
213 "unknown 0x33",
214 "STATUS_ENQ",
215 "START_DTMF",
216 "START_DTMF_ACK",
217 "START_DTMF_REJ",
218 "unknown 0x38",
219 "CONG_CTRL",
220 "FACILITY",
221 "unknown 0x3b",
222 "STATUS",
223 "unknown 0x3c",
224 "NOTIFY",
225 "unknown 0x3f",
226};
227
Harald Welte59b04682009-06-10 05:40:52 +0800228static char strbuf[64];
229
230static const char *rr_cause_name(u_int8_t cause)
231{
232 if (cause < ARRAY_SIZE(rr_cause_names) &&
233 rr_cause_names[cause])
234 return rr_cause_names[cause];
235
236 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
237 return strbuf;
238}
239
240static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
241 int len)
242{
243 memset(rep, 0, sizeof(*rep));
244
245 if (data[0] & 0x80)
246 rep->flags |= MEAS_REP_F_BA1;
247 if (data[0] & 0x40)
248 rep->flags |= MEAS_REP_F_DTX;
Harald Welteba6589d2009-07-05 04:05:44 +0200249 if ((data[1] & 0x40) == 0x00)
Harald Welte59b04682009-06-10 05:40:52 +0800250 rep->flags |= MEAS_REP_F_VALID;
251
252 rep->rxlev_full = data[0] & 0x3f;
253 rep->rxlev_sub = data[1] & 0x3f;
254 rep->rxqual_full = (data[3] >> 4) & 0x7;
255 rep->rxqual_sub = (data[3] >> 1) & 0x7;
256 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
257 if (rep->num_cell < 1)
258 return;
259
260 /* an encoding nightmare in perfection */
261
262 rep->cell[0].rxlev = data[4] & 0x3f;
263 rep->cell[0].bcch_freq = data[5] >> 2;
264 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
265 if (rep->num_cell < 2)
266 return;
267
268 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
269 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
270 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
271 if (rep->num_cell < 3)
272 return;
273
274 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
275 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
276 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
277 if (rep->num_cell < 4)
278 return;
279
280 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
281 rep->cell[3].bcch_freq = data[11] & 0x1f;
282 rep->cell[3].bsic = data[12] >> 2;
283 if (rep->num_cell < 5)
284 return;
285
286 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
287 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
288 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
289 if (rep->num_cell < 6)
290 return;
291
292 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
293 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
294 rep->cell[5].bsic = data[16] & 0x3f;
295}
296
297int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
298static int gsm48_tx_simple(struct gsm_lchan *lchan,
299 u_int8_t pdisc, u_int8_t msg_type);
300static void schedule_reject(struct gsm_lchan *lchan);
301
302struct gsm_lai {
303 u_int16_t mcc;
304 u_int16_t mnc;
305 u_int16_t lac;
306};
307
Harald Welte59b04682009-06-10 05:40:52 +0800308static int reject_cause = 0;
309void gsm0408_set_reject_cause(int cause)
310{
311 reject_cause = cause;
312}
313
Harald Welte03740842009-06-10 23:11:52 +0800314static u_int32_t new_callref = 0x80000001;
315
Harald Welte59b04682009-06-10 05:40:52 +0800316static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
317 struct gsm_subscriber *subscriber)
318{
319 if (!subscriber)
320 return 0;
321
322 /*
323 * Do not send accept yet as more information should arrive. Some
324 * phones will not send us the information and we will have to check
325 * what we want to do with that.
326 */
327 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
328 return 0;
329
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200330 switch (subscriber->net->auth_policy) {
331 case GSM_AUTH_POLICY_CLOSED:
332 return subscriber->authorized;
Harald Welte (local)16480eb2009-08-13 13:49:51 +0200333 case GSM_AUTH_POLICY_TOKEN:
Harald Welte (local)272f5c72009-08-13 20:44:23 +0200334 if (subscriber->authorized)
335 return subscriber->authorized;
Harald Welte (local)16480eb2009-08-13 13:49:51 +0200336 return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT);
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200337 case GSM_AUTH_POLICY_ACCEPT_ALL:
Harald Welte59b04682009-06-10 05:40:52 +0800338 return 1;
Jan Luebbe3d6294e2009-08-12 12:48:00 +0200339 default:
340 return 0;
341 }
Harald Welte59b04682009-06-10 05:40:52 +0800342}
343
344static void release_loc_updating_req(struct gsm_lchan *lchan)
345{
346 if (!lchan->loc_operation)
347 return;
348
349 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Weltea8379772009-06-20 22:36:41 +0200350 talloc_free(lchan->loc_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800351 lchan->loc_operation = 0;
352 put_lchan(lchan);
353}
354
355static void allocate_loc_updating_req(struct gsm_lchan *lchan)
356{
357 use_lchan(lchan);
358 release_loc_updating_req(lchan);
359
Harald Welte857e00d2009-06-26 20:25:23 +0200360 lchan->loc_operation = talloc_zero(tall_locop_ctx,
361 struct gsm_loc_updating_operation);
Harald Welte59b04682009-06-10 05:40:52 +0800362}
363
364static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
365{
366 u_int32_t tmsi;
367
368 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welte5070e942009-08-09 19:07:00 +0200369 int rc;
370
Harald Welte59b04682009-06-10 05:40:52 +0800371 db_subscriber_alloc_tmsi(lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800372 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
373 release_loc_updating_req(lchan);
Harald Welte5070e942009-08-09 19:07:00 +0200374 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
375 /* call subscr_update after putting the loc_upd_acc
376 * in the transmit queue, since S_SUBSCR_ATTACHED might
377 * trigger further action like SMS delivery */
378 subscr_update(lchan->subscr, msg->trx->bts,
379 GSM_SUBSCRIBER_UPDATE_ATTACHED);
380 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800381 }
382
383 return 0;
384}
385
386static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
387 void *handler_data, void *signal_data)
388{
Harald Welte03740842009-06-10 23:11:52 +0800389 struct gsm_trans *trans, *temp;
390
Harald Welte59b04682009-06-10 05:40:52 +0800391 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
392 return 0;
393
394 /*
395 * Cancel any outstanding location updating request
396 * operation taking place on the lchan.
397 */
Harald Welte12560da2009-07-04 09:35:21 +0200398 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Welte1ff81b52009-06-26 20:17:06 +0200399 if (!lchan)
400 return 0;
401
Harald Welte59b04682009-06-10 05:40:52 +0800402 release_loc_updating_req(lchan);
403
Harald Welte03740842009-06-10 23:11:52 +0800404 /* Free all transactions that are associated with the released lchan */
Harald Weltec2189a62009-07-23 18:56:43 +0200405 /* FIXME: this is not neccessarily the right thing to do, we should
406 * only set trans->lchan to NULL and wait for another lchan to be
407 * established to the same MM entity (phone/subscriber) */
Harald Welte03740842009-06-10 23:11:52 +0800408 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
409 if (trans->lchan == lchan)
Harald Weltec2189a62009-07-23 18:56:43 +0200410 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +0800411 }
412
Harald Welte59b04682009-06-10 05:40:52 +0800413 return 0;
414}
415
Harald Welte59b04682009-06-10 05:40:52 +0800416static void to_bcd(u_int8_t *bcd, u_int16_t val)
417{
418 bcd[2] = val % 10;
419 val = val / 10;
420 bcd[1] = val % 10;
421 val = val / 10;
422 bcd[0] = val % 10;
423 val = val / 10;
424}
425
426void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
427 u_int16_t mnc, u_int16_t lac)
428{
429 u_int8_t bcd[3];
430
431 to_bcd(bcd, mcc);
432 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
433 lai48->digits[1] = bcd[2];
434
435 to_bcd(bcd, mnc);
436 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
437#if 0
438 lai48->digits[1] |= bcd[2] << 4;
439 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
440#else
441 lai48->digits[1] |= 0xf << 4;
442 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
443#endif
444
445 lai48->lac = htons(lac);
446}
447
448#define TMSI_LEN 5
449#define MID_TMSI_LEN (TMSI_LEN + 2)
450
451int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
452{
453 u_int32_t *tptr = (u_int32_t *) &buf[3];
454
455 buf[0] = GSM48_IE_MOBILE_ID;
456 buf[1] = TMSI_LEN;
457 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
458 *tptr = htonl(tmsi);
459
460 return 7;
461}
462
463static const char bcd_num_digits[] = {
464 '0', '1', '2', '3', '4', '5', '6', '7',
465 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
466};
467
Harald Welteb8a18b52009-06-10 12:08:54 +0800468/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
469int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
470 int h_len)
Harald Welte59b04682009-06-10 05:40:52 +0800471{
472 u_int8_t in_len = bcd_lv[0];
473 int i;
474
Harald Welteb8a18b52009-06-10 12:08:54 +0800475 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte59b04682009-06-10 05:40:52 +0800476 /* lower nibble */
477 output_len--;
478 if (output_len <= 1)
479 break;
480 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
481
482 /* higher nibble */
483 output_len--;
484 if (output_len <= 1)
485 break;
486 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
487 }
488 if (output_len >= 1)
489 *output++ = '\0';
490
Harald Welteb8a18b52009-06-10 12:08:54 +0800491 return 0;
Harald Welte59b04682009-06-10 05:40:52 +0800492}
493
494/* convert a single ASCII character to call-control BCD */
495static int asc_to_bcd(const char asc)
496{
497 int i;
498
499 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
500 if (bcd_num_digits[i] == asc)
501 return i;
502 }
503 return -EINVAL;
504}
505
Harald Welteb8a18b52009-06-10 12:08:54 +0800506/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte59b04682009-06-10 05:40:52 +0800507int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welteb8a18b52009-06-10 12:08:54 +0800508 int h_len, const char *input)
Harald Welte59b04682009-06-10 05:40:52 +0800509{
510 int in_len = strlen(input);
511 int i;
Harald Welteb8a18b52009-06-10 12:08:54 +0800512 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800513
514 /* two digits per byte, plus type byte */
Harald Welteb8a18b52009-06-10 12:08:54 +0800515 bcd_lv[0] = in_len/2 + h_len;
Harald Welte59b04682009-06-10 05:40:52 +0800516 if (in_len % 2)
517 bcd_lv[0]++;
518
Harald Welteb8a18b52009-06-10 12:08:54 +0800519 if (bcd_lv[0] > max_len)
520 return -EIO;
Harald Welte59b04682009-06-10 05:40:52 +0800521
522 for (i = 0; i < in_len; i++) {
523 int rc = asc_to_bcd(input[i]);
524 if (rc < 0)
525 return rc;
526 if (i % 2 == 0)
527 *bcd_cur = rc;
528 else
529 *bcd_cur++ |= (rc << 4);
530 }
531 /* append padding nibble in case of odd length */
532 if (i % 2)
533 *bcd_cur++ |= 0xf0;
534
535 /* return how many bytes we used */
536 return (bcd_cur - bcd_lv);
537}
538
Harald Welteb8a18b52009-06-10 12:08:54 +0800539/* decode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800540static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welteb8a18b52009-06-10 12:08:54 +0800541 const u_int8_t *lv)
542{
543 u_int8_t in_len = lv[0];
544 int i, s;
545
546 if (in_len < 1)
547 return -EINVAL;
548
Harald Welte03740842009-06-10 23:11:52 +0800549 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welteb8a18b52009-06-10 12:08:54 +0800550
551 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800552 bcap->transfer = lv[1] & 0x07;
553 bcap->mode = (lv[1] & 0x08) >> 3;
554 bcap->coding = (lv[1] & 0x10) >> 4;
555 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800556
557 i = 1;
558 s = 0;
559 while(!(lv[i] & 0x80)) {
560 i++; /* octet 3a etc */
561 if (in_len < i)
562 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800563 bcap->speech_ver[s++] = lv[i] & 0x0f;
564 bcap->speech_ver[s] = -1; /* end of list */
Harald Welteb8a18b52009-06-10 12:08:54 +0800565 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800566 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800567 if (s == 7) /* maximum speech versions + end of list */
568 return 0;
569 }
570
571 return 0;
572}
573
574/* encode 'bearer capability' */
Harald Welte03740842009-06-10 23:11:52 +0800575static int encode_bearer_cap(struct msgb *msg, int lv_only,
576 const struct gsm_mncc_bearer_cap *bcap)
Harald Welteb8a18b52009-06-10 12:08:54 +0800577{
578 u_int8_t lv[32 + 1];
579 int i, s;
580
Harald Welte03740842009-06-10 23:11:52 +0800581 lv[1] = bcap->transfer;
582 lv[1] |= bcap->mode << 3;
583 lv[1] |= bcap->coding << 4;
584 lv[1] |= bcap->radio << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800585
586 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800587 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800588 i++; /* octet 3a etc */
Harald Welte03740842009-06-10 23:11:52 +0800589 lv[i] = bcap->speech_ver[s];
Harald Welteb8a18b52009-06-10 12:08:54 +0800590 if (i == 2) /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800591 lv[i] |= bcap->speech_ctm << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800592 }
593 lv[i] |= 0x80; /* last IE of octet 3 etc */
594
595 lv[0] = i;
596 if (lv_only)
597 msgb_lv_put(msg, lv[0], lv+1);
598 else
599 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
600
601 return 0;
602}
603
604/* decode 'call control cap' */
Harald Welte03740842009-06-10 23:11:52 +0800605static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800606{
607 u_int8_t in_len = lv[0];
608
609 if (in_len < 1)
610 return -EINVAL;
611
612 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800613 ccap->dtmf = lv[1] & 0x01;
614 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welteb8a18b52009-06-10 12:08:54 +0800615
616 return 0;
617}
618
619/* decode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800620static int decode_called(struct gsm_mncc_number *called,
621 const u_int8_t *lv)
Harald Welteb8a18b52009-06-10 12:08:54 +0800622{
623 u_int8_t in_len = lv[0];
624
625 if (in_len < 1)
626 return -EINVAL;
627
628 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800629 called->plan = lv[1] & 0x0f;
630 called->type = (lv[1] & 0x70) >> 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800631
632 /* octet 4..N */
Harald Welte03740842009-06-10 23:11:52 +0800633 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800634
635 return 0;
636}
637
638/* encode 'called party BCD number' */
Harald Welte03740842009-06-10 23:11:52 +0800639static int encode_called(struct msgb *msg,
640 const struct gsm_mncc_number *called)
Harald Welteb8a18b52009-06-10 12:08:54 +0800641{
642 u_int8_t lv[18];
643 int ret;
644
645 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800646 lv[1] = called->plan;
647 lv[1] |= called->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800648
649 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800650 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800651 if (ret < 0)
652 return ret;
653
654 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
655
656 return 0;
657}
658
659/* encode callerid of various IEs */
Harald Welte03740842009-06-10 23:11:52 +0800660static int encode_callerid(struct msgb *msg, int ie,
661 const struct gsm_mncc_number *callerid)
Harald Welteb8a18b52009-06-10 12:08:54 +0800662{
663 u_int8_t lv[13];
664 int h_len = 1;
665 int ret;
666
667 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800668 lv[1] = callerid->plan;
669 lv[1] |= callerid->type << 4;
Harald Welteb8a18b52009-06-10 12:08:54 +0800670
Harald Welte03740842009-06-10 23:11:52 +0800671 if (callerid->present || callerid->screen) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800672 /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800673 lv[2] = callerid->screen;
674 lv[2] |= callerid->present << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800675 lv[2] |= 0x80;
676 h_len++;
677 } else
678 lv[1] |= 0x80;
679
680 /* octet 4..N, octet 2 */
Harald Welte03740842009-06-10 23:11:52 +0800681 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welteb8a18b52009-06-10 12:08:54 +0800682 if (ret < 0)
683 return ret;
684
685 msgb_tlv_put(msg, ie, lv[0], lv+1);
686
687 return 0;
688}
689
690/* decode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800691static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welteb8a18b52009-06-10 12:08:54 +0800692 const u_int8_t *lv)
693{
694 u_int8_t in_len = lv[0];
695 int i;
696
697 if (in_len < 2)
698 return -EINVAL;
699
Harald Welte03740842009-06-10 23:11:52 +0800700 cause->diag_len = 0;
Harald Welteb8a18b52009-06-10 12:08:54 +0800701
702 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800703 cause->location = lv[1] & 0x0f;
704 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800705
706 i = 1;
707 if (!(lv[i] & 0x80)) {
708 i++; /* octet 3a */
709 if (in_len < i+1)
710 return 0;
Harald Welte03740842009-06-10 23:11:52 +0800711 cause->rec = 1;
712 cause->rec_val = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800713
714 }
715 i++;
716
717 /* octet 4 */
Harald Welte03740842009-06-10 23:11:52 +0800718 cause->value = lv[i] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800719 i++;
720
721 if (in_len < i) /* no diag */
722 return 0;
723
724 if (in_len - (i-1) > 32) /* maximum 32 octets */
725 return 0;
726
727 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800728 memcpy(cause->diag, lv + i, in_len - (i-1));
729 cause->diag_len = in_len - (i-1);
Harald Welteb8a18b52009-06-10 12:08:54 +0800730
731 return 0;
732}
733
734/* encode 'cause' */
Harald Welte03740842009-06-10 23:11:52 +0800735static int encode_cause(struct msgb *msg, int lv_only,
736 const struct gsm_mncc_cause *cause)
Harald Welteb8a18b52009-06-10 12:08:54 +0800737{
738 u_int8_t lv[32+4];
739 int i;
740
Harald Welte03740842009-06-10 23:11:52 +0800741 if (cause->diag_len > 32)
Harald Welteb8a18b52009-06-10 12:08:54 +0800742 return -EINVAL;
743
744 /* octet 3 */
Harald Welte03740842009-06-10 23:11:52 +0800745 lv[1] = cause->location;
746 lv[1] |= cause->coding << 5;
Harald Welteb8a18b52009-06-10 12:08:54 +0800747
748 i = 1;
Harald Welte03740842009-06-10 23:11:52 +0800749 if (cause->rec) {
Harald Welteb8a18b52009-06-10 12:08:54 +0800750 i++; /* octet 3a */
Harald Welte03740842009-06-10 23:11:52 +0800751 lv[i] = cause->rec_val;
Harald Welteb8a18b52009-06-10 12:08:54 +0800752 }
753 lv[i] |= 0x80; /* end of octet 3 */
754
755 /* octet 4 */
756 i++;
Harald Welte03740842009-06-10 23:11:52 +0800757 lv[i] = 0x80 | cause->value;
Harald Welteb8a18b52009-06-10 12:08:54 +0800758
759 /* octet 5-N */
Harald Welte03740842009-06-10 23:11:52 +0800760 if (cause->diag_len) {
761 memcpy(lv + i, cause->diag, cause->diag_len);
762 i += cause->diag_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800763 }
764
765 lv[0] = i;
766 if (lv_only)
767 msgb_lv_put(msg, lv[0], lv+1);
768 else
769 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
770
771 return 0;
772}
773
774/* encode 'calling number' */
Harald Welte03740842009-06-10 23:11:52 +0800775static int encode_calling(struct msgb *msg,
776 const struct gsm_mncc_number *calling)
Harald Welteb8a18b52009-06-10 12:08:54 +0800777{
Harald Welte03740842009-06-10 23:11:52 +0800778 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welteb8a18b52009-06-10 12:08:54 +0800779}
780
781/* encode 'connected number' */
Harald Welte03740842009-06-10 23:11:52 +0800782static int encode_connected(struct msgb *msg,
783 const struct gsm_mncc_number *connected)
Harald Welteb8a18b52009-06-10 12:08:54 +0800784{
Harald Welte03740842009-06-10 23:11:52 +0800785 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welteb8a18b52009-06-10 12:08:54 +0800786}
787
788/* encode 'redirecting number' */
Harald Welte03740842009-06-10 23:11:52 +0800789static int encode_redirecting(struct msgb *msg,
790 const struct gsm_mncc_number *redirecting)
Harald Welteb8a18b52009-06-10 12:08:54 +0800791{
Harald Welte03740842009-06-10 23:11:52 +0800792 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welteb8a18b52009-06-10 12:08:54 +0800793}
794
795/* decode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800796static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welteb8a18b52009-06-10 12:08:54 +0800797 const u_int8_t *lv)
798{
799 u_int8_t in_len = lv[0];
800
801 if (in_len < 1)
802 return -EINVAL;
803
Harald Welte03740842009-06-10 23:11:52 +0800804 if (in_len > sizeof(facility->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800805 return -EINVAL;
806
Harald Welte03740842009-06-10 23:11:52 +0800807 memcpy(facility->info, lv+1, in_len);
808 facility->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800809
810 return 0;
811}
812
813/* encode 'facility' */
Harald Welte03740842009-06-10 23:11:52 +0800814static int encode_facility(struct msgb *msg, int lv_only,
815 const struct gsm_mncc_facility *facility)
Harald Welteb8a18b52009-06-10 12:08:54 +0800816{
817 u_int8_t lv[GSM_MAX_FACILITY + 1];
818
Harald Welte03740842009-06-10 23:11:52 +0800819 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welteb8a18b52009-06-10 12:08:54 +0800820 return -EINVAL;
821
Harald Welte03740842009-06-10 23:11:52 +0800822 memcpy(lv+1, facility->info, facility->len);
823 lv[0] = facility->len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800824 if (lv_only)
825 msgb_lv_put(msg, lv[0], lv+1);
826 else
827 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
828
829 return 0;
830}
831
832/* decode 'notify' */
833static int decode_notify(int *notify, const u_int8_t *v)
834{
835 *notify = v[0] & 0x7f;
836
837 return 0;
838}
839
840/* encode 'notify' */
841static int encode_notify(struct msgb *msg, int notify)
842{
843 msgb_v_put(msg, notify | 0x80);
844
845 return 0;
846}
847
848/* encode 'signal' */
849static int encode_signal(struct msgb *msg, int signal)
850{
851 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
852
853 return 0;
854}
855
856/* decode 'keypad' */
857static int decode_keypad(int *keypad, const u_int8_t *lv)
858{
859 u_int8_t in_len = lv[0];
860
861 if (in_len < 1)
862 return -EINVAL;
863
864 *keypad = lv[1] & 0x7f;
865
866 return 0;
867}
868
869/* encode 'keypad' */
870static int encode_keypad(struct msgb *msg, int keypad)
871{
872 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
873
874 return 0;
875}
876
877/* decode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800878static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welteb8a18b52009-06-10 12:08:54 +0800879 const u_int8_t *lv)
880{
881 u_int8_t in_len = lv[0];
882
883 if (in_len < 2)
884 return -EINVAL;
885
Harald Welte03740842009-06-10 23:11:52 +0800886 progress->coding = (lv[1] & 0x60) >> 5;
887 progress->location = lv[1] & 0x0f;
888 progress->descr = lv[2] & 0x7f;
Harald Welteb8a18b52009-06-10 12:08:54 +0800889
890 return 0;
891}
892
893/* encode 'progress' */
Harald Welte03740842009-06-10 23:11:52 +0800894static int encode_progress(struct msgb *msg, int lv_only,
895 const struct gsm_mncc_progress *p)
Harald Welteb8a18b52009-06-10 12:08:54 +0800896{
897 u_int8_t lv[3];
898
899 lv[0] = 2;
Harald Welte03740842009-06-10 23:11:52 +0800900 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
901 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welteb8a18b52009-06-10 12:08:54 +0800902 if (lv_only)
903 msgb_lv_put(msg, lv[0], lv+1);
904 else
905 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
906
907 return 0;
908}
909
910/* decode 'user-user' */
Harald Welte03740842009-06-10 23:11:52 +0800911static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welteb8a18b52009-06-10 12:08:54 +0800912 const u_int8_t *lv)
913{
914 u_int8_t in_len = lv[0];
Harald Welte03740842009-06-10 23:11:52 +0800915 char *info = uu->info;
916 int info_len = sizeof(uu->info);
Harald Welteb8a18b52009-06-10 12:08:54 +0800917 int i;
918
919 if (in_len < 1)
920 return -EINVAL;
921
Harald Welte03740842009-06-10 23:11:52 +0800922 uu->proto = lv[1];
Harald Welteb8a18b52009-06-10 12:08:54 +0800923
924 for (i = 2; i <= in_len; i++) {
925 info_len--;
926 if (info_len <= 1)
927 break;
928 *info++ = lv[i];
929 }
930 if (info_len >= 1)
931 *info++ = '\0';
932
933 return 0;
934}
935
936/* encode 'useruser' */
Harald Welte03740842009-06-10 23:11:52 +0800937static int encode_useruser(struct msgb *msg, int lv_only,
938 const struct gsm_mncc_useruser *uu)
Harald Welteb8a18b52009-06-10 12:08:54 +0800939{
940 u_int8_t lv[GSM_MAX_USERUSER + 2];
941
Harald Welte03740842009-06-10 23:11:52 +0800942 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welteb8a18b52009-06-10 12:08:54 +0800943 return -EINVAL;
944
Harald Welte03740842009-06-10 23:11:52 +0800945 lv[0] = 1 + strlen(uu->info);
946 lv[1] = uu->proto;
947 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welteb8a18b52009-06-10 12:08:54 +0800948 if (lv_only)
949 msgb_lv_put(msg, lv[0], lv+1);
950 else
951 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
952
953 return 0;
954}
955
956/* decode 'ss version' */
Harald Welte03740842009-06-10 23:11:52 +0800957static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welteb8a18b52009-06-10 12:08:54 +0800958 const u_int8_t *lv)
959{
960 u_int8_t in_len = lv[0];
961
Harald Welte03740842009-06-10 23:11:52 +0800962 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welteb8a18b52009-06-10 12:08:54 +0800963 return -EINVAL;
964
Harald Welte03740842009-06-10 23:11:52 +0800965 memcpy(ssv->info, lv + 1, in_len);
966 ssv->len = in_len;
Harald Welteb8a18b52009-06-10 12:08:54 +0800967
968 return 0;
969}
970
971/* encode 'more data' */
972static int encode_more(struct msgb *msg)
973{
974 u_int8_t *ie;
975
976 ie = msgb_put(msg, 1);
977 ie[0] = GSM48_IE_MORE_DATA;
978
979 return 0;
980}
981
Harald Welte59b04682009-06-10 05:40:52 +0800982struct msgb *gsm48_msgb_alloc(void)
983{
Harald Welte9cfc9352009-06-26 19:39:35 +0200984 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
985 "GSM 04.08");
Harald Welte59b04682009-06-10 05:40:52 +0800986}
987
Harald Welte36fe2e82009-07-23 21:13:03 +0200988int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800989{
Harald Welte36fe2e82009-07-23 21:13:03 +0200990 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
991
992 /* if we get passed a transaction reference, do some common
993 * work that the caller no longer has to do */
994 if (trans) {
Harald Welte4861c822009-07-23 21:21:14 +0200995 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte36fe2e82009-07-23 21:13:03 +0200996 msg->lchan = trans->lchan;
997 }
998
Harald Welte59b04682009-06-10 05:40:52 +0800999 if (msg->lchan) {
1000 msg->trx = msg->lchan->ts->trx;
1001
Harald Welte03740842009-06-10 23:11:52 +08001002 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1003 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1004 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1005 msg->trx->nr, msg->lchan->ts->nr,
1006 gh->proto_discr & 0xf0,
1007 cc_msg_names[gh->msg_type & 0x3f]);
1008 else
1009 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1010 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1011 msg->trx->nr, msg->lchan->ts->nr,
1012 gh->proto_discr, gh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001013 }
1014
1015 msg->l3h = msg->data;
1016
1017 return rsl_data_request(msg, 0);
1018}
1019
Harald Welte59b04682009-06-10 05:40:52 +08001020/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
1021int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
1022{
1023 struct msgb *msg = gsm48_msgb_alloc();
1024 struct gsm48_hdr *gh;
1025
1026 msg->lchan = lchan;
1027
1028 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1029 gh->proto_discr = GSM48_PDISC_MM;
1030 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
1031 gh->data[0] = cause;
1032
1033 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1034
Harald Welte36fe2e82009-07-23 21:13:03 +02001035 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001036}
1037
1038/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
1039int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
1040{
1041 struct gsm_bts *bts = lchan->ts->trx->bts;
1042 struct msgb *msg = gsm48_msgb_alloc();
1043 struct gsm48_hdr *gh;
1044 struct gsm48_loc_area_id *lai;
1045 u_int8_t *mid;
1046 int ret;
1047
1048 msg->lchan = lchan;
1049
1050 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1051 gh->proto_discr = GSM48_PDISC_MM;
1052 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1053
1054 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
1055 gsm0408_generate_lai(lai, bts->network->country_code,
1056 bts->network->network_code, bts->location_area_code);
1057
1058 mid = msgb_put(msg, MID_TMSI_LEN);
1059 generate_mid_from_tmsi(mid, tmsi);
1060
1061 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1062
Harald Welte36fe2e82009-07-23 21:13:03 +02001063 ret = gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001064
Harald Welte5070e942009-08-09 19:07:00 +02001065 /* send MM INFO with network name */
Harald Welte59b04682009-06-10 05:40:52 +08001066 ret = gsm48_tx_mm_info(lchan);
1067
1068 return ret;
1069}
1070
1071static char bcd2char(u_int8_t bcd)
1072{
1073 if (bcd < 0xa)
1074 return '0' + bcd;
1075 else
1076 return 'A' + (bcd - 0xa);
1077}
1078
1079/* Convert Mobile Identity (10.5.1.4) to string */
1080static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1081{
1082 int i;
1083 u_int8_t mi_type;
1084 char *str_cur = string;
1085 u_int32_t tmsi;
1086
1087 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1088
1089 switch (mi_type) {
1090 case GSM_MI_TYPE_NONE:
1091 break;
1092 case GSM_MI_TYPE_TMSI:
1093 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1094 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1095 memcpy(&tmsi, &mi[1], 4);
1096 tmsi = ntohl(tmsi);
1097 return snprintf(string, str_len, "%u", tmsi);
1098 }
1099 break;
1100 case GSM_MI_TYPE_IMSI:
1101 case GSM_MI_TYPE_IMEI:
1102 case GSM_MI_TYPE_IMEISV:
1103 *str_cur++ = bcd2char(mi[0] >> 4);
1104
1105 for (i = 1; i < mi_len; i++) {
1106 if (str_cur + 2 >= string + str_len)
1107 return str_cur - string;
1108 *str_cur++ = bcd2char(mi[i] & 0xf);
1109 /* skip last nibble in last input byte when GSM_EVEN */
1110 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1111 *str_cur++ = bcd2char(mi[i] >> 4);
1112 }
1113 break;
1114 default:
1115 break;
1116 }
1117 *str_cur++ = '\0';
1118
1119 return str_cur - string;
1120}
1121
1122/* Transmit Chapter 9.2.10 Identity Request */
1123static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1124{
1125 struct msgb *msg = gsm48_msgb_alloc();
1126 struct gsm48_hdr *gh;
1127
1128 msg->lchan = lchan;
1129
1130 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1131 gh->proto_discr = GSM48_PDISC_MM;
1132 gh->msg_type = GSM48_MT_MM_ID_REQ;
1133 gh->data[0] = id_type;
1134
Harald Welte36fe2e82009-07-23 21:13:03 +02001135 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001136}
1137
1138#define MI_SIZE 32
1139
1140/* Parse Chapter 9.2.11 Identity Response */
1141static int mm_rx_id_resp(struct msgb *msg)
1142{
1143 struct gsm48_hdr *gh = msgb_l3(msg);
1144 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75350412009-07-23 18:46:00 +02001145 struct gsm_bts *bts = lchan->ts->trx->bts;
1146 struct gsm_network *net = bts->network;
Harald Welte59b04682009-06-10 05:40:52 +08001147 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1148 char mi_string[MI_SIZE];
1149
1150 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
1151 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
1152 mi_type, mi_string);
1153
Harald Welte59b04682009-06-10 05:40:52 +08001154 switch (mi_type) {
1155 case GSM_MI_TYPE_IMSI:
Jan Luebbe9bdbd622009-08-12 10:19:34 +02001156 /* look up subscriber based on IMSI, create if not found */
1157 if (!lchan->subscr) {
1158 lchan->subscr = subscr_get_by_imsi(net, mi_string);
Harald Welte (local)16480eb2009-08-13 13:49:51 +02001159 if (!lchan->subscr)
1160 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbee2974032009-08-12 10:12:52 +02001161 }
Harald Welte59b04682009-06-10 05:40:52 +08001162 if (lchan->loc_operation)
1163 lchan->loc_operation->waiting_for_imsi = 0;
1164 break;
1165 case GSM_MI_TYPE_IMEI:
1166 case GSM_MI_TYPE_IMEISV:
1167 /* update subscribe <-> IMEI mapping */
Harald Welte (local)ced09ed2009-08-17 09:39:55 +02001168 if (lchan->subscr) {
Harald Welte59b04682009-06-10 05:40:52 +08001169 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +02001170 db_sync_equipment(&lchan->subscr->equipment);
1171 }
Harald Welte59b04682009-06-10 05:40:52 +08001172 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 }
Harald Welte59b04682009-06-10 05:40:52 +08001259 break;
1260 case GSM_MI_TYPE_TMSI:
Harald Welte79639662009-06-27 02:58:43 +02001261 DEBUGPC(DMM, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001262 /* we always want the IMEI, too */
Harald Welte59b04682009-06-10 05:40:52 +08001263 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
1264 lchan->loc_operation->waiting_for_imei = 1;
1265
1266 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte75350412009-07-23 18:46:00 +02001267 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001268 if (!subscr) {
1269 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte59b04682009-06-10 05:40:52 +08001270 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
1271 lchan->loc_operation->waiting_for_imsi = 1;
1272 }
1273 break;
1274 case GSM_MI_TYPE_IMEI:
1275 case GSM_MI_TYPE_IMEISV:
1276 /* no sim card... FIXME: what to do ? */
Harald Welte79639662009-06-27 02:58:43 +02001277 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001278 break;
1279 default:
Harald Welte79639662009-06-27 02:58:43 +02001280 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte59b04682009-06-10 05:40:52 +08001281 break;
1282 }
1283
Harald Welteccd69362009-07-04 10:18:00 +02001284 /* schedule the reject timer */
1285 schedule_reject(lchan);
1286
Harald Welte03740842009-06-10 23:11:52 +08001287 if (!subscr) {
Harald Welte79639662009-06-27 02:58:43 +02001288 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte03740842009-06-10 23:11:52 +08001289 /* FIXME: request id? close channel? */
1290 return -EINVAL;
1291 }
1292
Harald Welte59b04682009-06-10 05:40:52 +08001293 lchan->subscr = subscr;
Harald Welte (local)ced09ed2009-08-17 09:39:55 +02001294 lchan->subscr->equipment.classmark1 = lu->classmark1;
Harald Welte59b04682009-06-10 05:40:52 +08001295
Harald Welteccd69362009-07-04 10:18:00 +02001296 /* check if we can let the subscriber into our network immediately
1297 * or if we need to wait for identity responses. */
Harald Welte59b04682009-06-10 05:40:52 +08001298 return gsm0408_authorize(lchan, msg);
1299}
1300
Harald Welteca745e22009-07-29 12:10:35 +02001301/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte59b04682009-06-10 05:40:52 +08001302int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1303{
1304 struct msgb *msg = gsm48_msgb_alloc();
1305 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1306 struct gsm48_chan_mode_modify *cmm =
1307 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
1308 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
1309
1310 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
1311
1312 lchan->tch_mode = mode;
1313 msg->lchan = lchan;
1314 gh->proto_discr = GSM48_PDISC_RR;
1315 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1316
1317 /* fill the channel information element, this code
1318 * should probably be shared with rsl_rx_chan_rqd() */
1319 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
1320 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
1321 cmm->chan_desc.h0.h = 0;
1322 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1323 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1324 cmm->mode = mode;
1325
Harald Welte36fe2e82009-07-23 21:13:03 +02001326 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001327}
1328
Harald Welte03740842009-06-10 23:11:52 +08001329#if 0
1330static u_int8_t to_bcd8(u_int8_t val)
1331{
1332 return ((val / 10) << 4) | (val % 10);
1333}
1334#endif
1335
Harald Welte59b04682009-06-10 05:40:52 +08001336/* Section 9.2.15a */
1337int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1338{
1339 struct msgb *msg = gsm48_msgb_alloc();
1340 struct gsm48_hdr *gh;
1341 struct gsm_network *net = lchan->ts->trx->bts->network;
1342 u_int8_t *ptr8;
1343 u_int16_t *ptr16;
Daniel Willmannc8188202009-08-13 03:42:07 +02001344 int name_len, name_pad;
Harald Welte59b04682009-06-10 05:40:52 +08001345 int i;
Harald Welte03740842009-06-10 23:11:52 +08001346#if 0
1347 time_t cur_t;
1348 struct tm* cur_time;
1349 int tz15min;
1350#endif
Harald Welte59b04682009-06-10 05:40:52 +08001351
1352 msg->lchan = lchan;
1353
1354 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1355 gh->proto_discr = GSM48_PDISC_MM;
1356 gh->msg_type = GSM48_MT_MM_INFO;
1357
1358 if (net->name_long) {
Daniel Willmannc8188202009-08-13 03:42:07 +02001359#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001360 name_len = strlen(net->name_long);
1361 /* 10.5.3.5a */
1362 ptr8 = msgb_put(msg, 3);
1363 ptr8[0] = GSM48_IE_NAME_LONG;
1364 ptr8[1] = name_len*2 +1;
1365 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1366
1367 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1368 for (i = 0; i < name_len; i++)
1369 ptr16[i] = htons(net->name_long[i]);
1370
1371 /* FIXME: Use Cell Broadcast, not UCS-2, since
1372 * UCS-2 is only supported by later revisions of the spec */
Daniel Willmannc8188202009-08-13 03:42:07 +02001373#endif
1374 name_len = (strlen(net->name_long)*7)/8;
1375 name_pad = (8 - strlen(net->name_long)*7)%8;
1376 if (name_pad > 0)
1377 name_len++;
1378 /* 10.5.3.5a */
1379 ptr8 = msgb_put(msg, 3);
1380 ptr8[0] = GSM48_IE_NAME_LONG;
1381 ptr8[1] = name_len +1;
1382 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1383
1384 ptr8 = msgb_put(msg, name_len);
1385 gsm_7bit_encode(ptr8, net->name_long);
1386
Harald Welte59b04682009-06-10 05:40:52 +08001387 }
1388
1389 if (net->name_short) {
Daniel Willmannc8188202009-08-13 03:42:07 +02001390#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001391 name_len = strlen(net->name_short);
1392 /* 10.5.3.5a */
1393 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Weltef6284712009-07-19 17:51:36 +02001394 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Welte59b04682009-06-10 05:40:52 +08001395 ptr8[1] = name_len*2 + 1;
1396 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1397
1398 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1399 for (i = 0; i < name_len; i++)
1400 ptr16[i] = htons(net->name_short[i]);
Daniel Willmannc8188202009-08-13 03:42:07 +02001401#endif
1402 name_len = (strlen(net->name_short)*7)/8;
1403 name_pad = (8 - strlen(net->name_short)*7)%8;
1404 if (name_pad > 0)
1405 name_len++;
1406 /* 10.5.3.5a */
1407 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1408 ptr8[0] = GSM48_IE_NAME_SHORT;
1409 ptr8[1] = name_len +1;
1410 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1411
1412 ptr8 = msgb_put(msg, name_len);
1413 gsm_7bit_encode(ptr8, net->name_short);
1414
Harald Welte59b04682009-06-10 05:40:52 +08001415 }
1416
1417#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001418 /* Section 10.5.3.9 */
1419 cur_t = time(NULL);
Harald Welte03740842009-06-10 23:11:52 +08001420 cur_time = gmtime(&cur_t);
Harald Welte59b04682009-06-10 05:40:52 +08001421 ptr8 = msgb_put(msg, 8);
1422 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1423 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1424 ptr8[2] = to_bcd8(cur_time->tm_mon);
1425 ptr8[3] = to_bcd8(cur_time->tm_mday);
1426 ptr8[4] = to_bcd8(cur_time->tm_hour);
1427 ptr8[5] = to_bcd8(cur_time->tm_min);
1428 ptr8[6] = to_bcd8(cur_time->tm_sec);
1429 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1430 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte03740842009-06-10 23:11:52 +08001431 ptr8[7] = to_bcd8(tz15min);
Harald Welte59b04682009-06-10 05:40:52 +08001432 if (tz15min < 0)
Harald Welte03740842009-06-10 23:11:52 +08001433 ptr8[7] |= 0x80;
Harald Welte59b04682009-06-10 05:40:52 +08001434#endif
1435
Daniel Willmannc8188202009-08-13 03:42:07 +02001436 DEBUGP(DMM, "-> MM INFO\n");
1437
Harald Welte36fe2e82009-07-23 21:13:03 +02001438 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001439}
1440
Harald Welte36970f62009-08-12 22:56:50 +02001441/* Section 9.2.2 */
1442int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
1443{
1444 struct msgb *msg = gsm48_msgb_alloc();
1445 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1446 u_int8_t *r;
1447
1448 DEBUGP(DMM, "-> AUTH REQ\n");
1449
1450 msg->lchan = lchan;
1451 gh->proto_discr = GSM48_PDISC_MM;
1452 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
1453
1454 /* 16 bytes RAND parameters */
1455 r = msgb_put(msg, 16);
1456 if (rand)
1457 memcpy(r, rand, 16);
1458
1459 return gsm48_sendmsg(msg, NULL);
1460}
1461
1462/* Section 9.2.1 */
1463int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
1464{
1465 DEBUGP(DMM, "-> AUTH REJECT\n");
1466 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
1467}
1468
Harald Welte59b04682009-06-10 05:40:52 +08001469static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1470{
1471 DEBUGP(DMM, "-> CM SERVICE ACK\n");
1472 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
1473}
1474
1475/* 9.2.6 CM service reject */
1476static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1477 enum gsm48_reject_value value)
1478{
1479 struct msgb *msg = gsm48_msgb_alloc();
1480 struct gsm48_hdr *gh;
1481
1482 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1483
1484 msg->lchan = lchan;
1485 use_lchan(lchan);
1486
1487 gh->proto_discr = GSM48_PDISC_MM;
1488 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1489 gh->data[0] = value;
1490 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1491
Harald Welte36fe2e82009-07-23 21:13:03 +02001492 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001493}
1494
Harald Welte583ceaf2009-08-10 10:12:45 +02001495static int send_siemens_mrpci(struct gsm_lchan *lchan,
1496 u_int8_t *classmark2_lv)
1497{
1498 struct rsl_mrpci mrpci;
1499
1500 if (classmark2_lv[0] < 2)
1501 return -EINVAL;
1502
1503 mrpci.power_class = classmark2_lv[1] & 0x7;
1504 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1505 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1506 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1507
1508 return rsl_siemens_mrpci(lchan, &mrpci);
1509}
Harald Welte59b04682009-06-10 05:40:52 +08001510
1511/*
1512 * Handle CM Service Requests
1513 * a) Verify that the packet is long enough to contain the information
1514 * we require otherwsie reject with INCORRECT_MESSAGE
1515 * b) Try to parse the TMSI. If we do not have one reject
1516 * c) Check that we know the subscriber with the TMSI otherwise reject
1517 * with a HLR cause
1518 * d) Set the subscriber on the gsm_lchan and accept
1519 */
1520static int gsm48_rx_mm_serv_req(struct msgb *msg)
1521{
1522 u_int8_t mi_type;
1523 char mi_string[MI_SIZE];
1524
Harald Welte75350412009-07-23 18:46:00 +02001525 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001526 struct gsm_subscriber *subscr;
1527 struct gsm48_hdr *gh = msgb_l3(msg);
1528 struct gsm48_service_request *req =
1529 (struct gsm48_service_request *)gh->data;
1530 /* unfortunately in Phase1 the classmar2 length is variable */
1531 u_int8_t classmark2_len = gh->data[1];
1532 u_int8_t *classmark2 = gh->data+2;
1533 u_int8_t mi_len = *(classmark2 + classmark2_len);
1534 u_int8_t *mi = (classmark2 + classmark2_len + 1);
1535
1536 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
1537 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
1538 DEBUGPC(DMM, "wrong sized message\n");
1539 return gsm48_tx_mm_serv_rej(msg->lchan,
1540 GSM48_REJECT_INCORRECT_MESSAGE);
1541 }
1542
1543 if (msg->data_len < req->mi_len + 6) {
1544 DEBUGPC(DMM, "does not fit in packet\n");
1545 return gsm48_tx_mm_serv_rej(msg->lchan,
1546 GSM48_REJECT_INCORRECT_MESSAGE);
1547 }
1548
1549 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1550 if (mi_type != GSM_MI_TYPE_TMSI) {
1551 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
1552 return gsm48_tx_mm_serv_rej(msg->lchan,
1553 GSM48_REJECT_INCORRECT_MESSAGE);
1554 }
1555
1556 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1557 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
1558 req->cm_service_type, mi_type, mi_string);
1559
Harald Welte583ceaf2009-08-10 10:12:45 +02001560 if (is_siemens_bts(bts))
1561 send_siemens_mrpci(msg->lchan, classmark2-1);
1562
Harald Welte75350412009-07-23 18:46:00 +02001563 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001564
1565 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
1566 if (!subscr)
1567 return gsm48_tx_mm_serv_rej(msg->lchan,
1568 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1569
1570 if (!msg->lchan->subscr)
1571 msg->lchan->subscr = subscr;
1572 else if (msg->lchan->subscr != subscr) {
1573 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1574 subscr_put(subscr);
1575 }
1576
Harald Weltef6845a72009-07-05 14:08:13 +02001577 subscr->equipment.classmark2_len = classmark2_len;
1578 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1579 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001580
1581 return gsm48_tx_mm_serv_ack(msg->lchan);
1582}
1583
1584static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1585{
Harald Welte75350412009-07-23 18:46:00 +02001586 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001587 struct gsm48_hdr *gh = msgb_l3(msg);
1588 struct gsm48_imsi_detach_ind *idi =
1589 (struct gsm48_imsi_detach_ind *) gh->data;
1590 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1591 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001592 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001593
1594 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1595 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1596 mi_type, mi_string);
1597
1598 switch (mi_type) {
1599 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001600 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001601 break;
1602 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001603 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001604 break;
1605 case GSM_MI_TYPE_IMEI:
1606 case GSM_MI_TYPE_IMEISV:
1607 /* no sim card... FIXME: what to do ? */
1608 DEBUGPC(DMM, "unimplemented mobile identity type\n");
1609 break;
1610 default:
1611 DEBUGPC(DMM, "unknown mobile identity type\n");
1612 break;
1613 }
1614
1615 if (subscr) {
1616 subscr_update(subscr, msg->trx->bts,
1617 GSM_SUBSCRIBER_UPDATE_DETACHED);
1618 DEBUGP(DMM, "Subscriber: %s\n",
1619 subscr->name ? subscr->name : subscr->imsi);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +02001620
1621 subscr->equipment.classmark1 = idi->classmark1;
1622 db_sync_equipment(&subscr->equipment);
1623
Harald Welte59b04682009-06-10 05:40:52 +08001624 subscr_put(subscr);
1625 } else
1626 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1627
Harald Welte59b04682009-06-10 05:40:52 +08001628 return 0;
1629}
1630
1631static int gsm48_rx_mm_status(struct msgb *msg)
1632{
1633 struct gsm48_hdr *gh = msgb_l3(msg);
1634
1635 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1636
1637 return 0;
1638}
1639
1640/* Receive a GSM 04.08 Mobility Management (MM) message */
1641static int gsm0408_rcv_mm(struct msgb *msg)
1642{
1643 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte03740842009-06-10 23:11:52 +08001644 int rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08001645
1646 switch (gh->msg_type & 0xbf) {
1647 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Welte79639662009-06-27 02:58:43 +02001648 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte59b04682009-06-10 05:40:52 +08001649 rc = mm_rx_loc_upd_req(msg);
1650 break;
1651 case GSM48_MT_MM_ID_RESP:
1652 rc = mm_rx_id_resp(msg);
1653 break;
1654 case GSM48_MT_MM_CM_SERV_REQ:
1655 rc = gsm48_rx_mm_serv_req(msg);
1656 break;
1657 case GSM48_MT_MM_STATUS:
1658 rc = gsm48_rx_mm_status(msg);
1659 break;
1660 case GSM48_MT_MM_TMSI_REALL_COMPL:
1661 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1662 msg->lchan->subscr ?
1663 msg->lchan->subscr->imsi :
1664 "unknown subscriber");
1665 break;
1666 case GSM48_MT_MM_IMSI_DETACH_IND:
1667 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1668 break;
1669 case GSM48_MT_MM_CM_REEST_REQ:
1670 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1671 break;
1672 case GSM48_MT_MM_AUTH_RESP:
1673 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
1674 break;
1675 default:
1676 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1677 gh->msg_type);
1678 break;
1679 }
1680
1681 return rc;
1682}
1683
1684/* Receive a PAGING RESPONSE message from the MS */
1685static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1686{
Harald Welte75350412009-07-23 18:46:00 +02001687 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001688 struct gsm48_hdr *gh = msgb_l3(msg);
1689 u_int8_t *classmark2_lv = gh->data + 1;
1690 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1691 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
1692 char mi_string[MI_SIZE];
Harald Welte03740842009-06-10 23:11:52 +08001693 struct gsm_subscriber *subscr = NULL;
Harald Welte59b04682009-06-10 05:40:52 +08001694 struct paging_signal_data sig_data;
1695 int rc = 0;
1696
1697 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
1698 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1699 mi_type, mi_string);
Harald Welte583ceaf2009-08-10 10:12:45 +02001700
1701 if (is_siemens_bts(bts))
1702 send_siemens_mrpci(msg->lchan, classmark2_lv);
1703
Harald Welte59b04682009-06-10 05:40:52 +08001704 switch (mi_type) {
1705 case GSM_MI_TYPE_TMSI:
Harald Welte75350412009-07-23 18:46:00 +02001706 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001707 break;
1708 case GSM_MI_TYPE_IMSI:
Harald Welte75350412009-07-23 18:46:00 +02001709 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte59b04682009-06-10 05:40:52 +08001710 break;
1711 }
1712
1713 if (!subscr) {
1714 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1715 /* FIXME: request id? close channel? */
1716 return -EINVAL;
1717 }
1718 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte68b7df22009-08-08 16:03:15 +02001719 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Harald Welte59b04682009-06-10 05:40:52 +08001720
Harald Weltef6845a72009-07-05 14:08:13 +02001721 subscr->equipment.classmark2_len = *classmark2_lv;
1722 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1723 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001724
1725 if (!msg->lchan->subscr) {
1726 msg->lchan->subscr = subscr;
1727 } else if (msg->lchan->subscr != subscr) {
1728 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1729 subscr_put(subscr);
1730 return -EINVAL;
1731 } else {
1732 DEBUGP(DRR, "<- Channel already owned by us\n");
1733 subscr_put(subscr);
1734 subscr = msg->lchan->subscr;
1735 }
1736
1737 sig_data.subscr = subscr;
1738 sig_data.bts = msg->lchan->ts->trx->bts;
1739 sig_data.lchan = msg->lchan;
1740
1741 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Welte876312f2009-06-10 11:21:55 +08001742
1743 /* Stop paging on the bts we received the paging response */
Harald Welte59b04682009-06-10 05:40:52 +08001744 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
1745
1746 /* FIXME: somehow signal the completion of the PAGING to
1747 * the entity that requested the paging */
1748
1749 return rc;
1750}
1751
1752static int gsm48_rx_rr_classmark(struct msgb *msg)
1753{
1754 struct gsm48_hdr *gh = msgb_l3(msg);
1755 struct gsm_subscriber *subscr = msg->lchan->subscr;
1756 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1757 u_int8_t cm2_len, cm3_len = 0;
1758 u_int8_t *cm2, *cm3 = NULL;
1759
1760 DEBUGP(DRR, "CLASSMARK CHANGE ");
1761
1762 /* classmark 2 */
1763 cm2_len = gh->data[0];
1764 cm2 = &gh->data[1];
1765 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1766
1767 if (payload_len > cm2_len + 1) {
1768 /* we must have a classmark3 */
1769 if (gh->data[cm2_len+1] != 0x20) {
1770 DEBUGPC(DRR, "ERR CM3 TAG\n");
1771 return -EINVAL;
1772 }
1773 if (cm2_len > 3) {
1774 DEBUGPC(DRR, "CM2 too long!\n");
1775 return -EINVAL;
1776 }
1777
1778 cm3_len = gh->data[cm2_len+2];
1779 cm3 = &gh->data[cm2_len+3];
1780 if (cm3_len > 14) {
1781 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1782 return -EINVAL;
1783 }
1784 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1785 }
1786 if (subscr) {
Harald Weltef6845a72009-07-05 14:08:13 +02001787 subscr->equipment.classmark2_len = cm2_len;
1788 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Welte59b04682009-06-10 05:40:52 +08001789 if (cm3) {
Harald Weltef6845a72009-07-05 14:08:13 +02001790 subscr->equipment.classmark3_len = cm3_len;
1791 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Welte59b04682009-06-10 05:40:52 +08001792 }
Harald Weltef6845a72009-07-05 14:08:13 +02001793 db_sync_equipment(&subscr->equipment);
Harald Welte59b04682009-06-10 05:40:52 +08001794 }
1795
Harald Welte59b04682009-06-10 05:40:52 +08001796 return 0;
1797}
1798
1799static int gsm48_rx_rr_status(struct msgb *msg)
1800{
1801 struct gsm48_hdr *gh = msgb_l3(msg);
1802
1803 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1804 rr_cause_name(gh->data[0]));
1805
1806 return 0;
1807}
1808
1809static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1810{
1811 struct gsm48_hdr *gh = msgb_l3(msg);
1812 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1813 static struct gsm_meas_rep meas_rep;
1814
Harald Welte02993682009-06-27 02:53:10 +02001815 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Welte59b04682009-06-10 05:40:52 +08001816 parse_meas_rep(&meas_rep, gh->data, payload_len);
1817 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte02993682009-06-27 02:53:10 +02001818 DEBUGPC(DMEAS, "DTX ");
Harald Welte59b04682009-06-10 05:40:52 +08001819 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte02993682009-06-27 02:53:10 +02001820 DEBUGPC(DMEAS, "BA1 ");
Harald Welte59b04682009-06-10 05:40:52 +08001821 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte02993682009-06-27 02:53:10 +02001822 DEBUGPC(DMEAS, "NOT VALID ");
Harald Welte59b04682009-06-10 05:40:52 +08001823 else
Harald Welte02993682009-06-27 02:53:10 +02001824 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Welte59b04682009-06-10 05:40:52 +08001825 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1826 meas_rep.rxqual_sub);
1827
Harald Welte02993682009-06-27 02:53:10 +02001828 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Welte59b04682009-06-10 05:40:52 +08001829
1830 /* FIXME: put the results somwhere */
1831
1832 return 0;
1833}
1834
Harald Welte (local)b5103922009-08-15 23:32:44 +02001835static int gsm48_rx_rr_app_info(struct msgb *msg)
1836{
1837 struct gsm48_hdr *gh = msgb_l3(msg);
1838 u_int8_t apdu_id_flags;
1839 u_int8_t apdu_len;
1840 u_int8_t *apdu_data;
1841
1842 apdu_id_flags = gh->data[0];
1843 apdu_len = gh->data[1];
1844 apdu_data = gh->data+2;
1845
1846 DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
1847 apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
1848
Harald Welte (local)bd72aa22009-08-16 10:40:10 +02001849 return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data);
Harald Welte (local)b5103922009-08-15 23:32:44 +02001850}
1851
1852
Harald Welte59b04682009-06-10 05:40:52 +08001853/* Receive a GSM 04.08 Radio Resource (RR) message */
1854static int gsm0408_rcv_rr(struct msgb *msg)
1855{
1856 struct gsm48_hdr *gh = msgb_l3(msg);
1857 int rc = 0;
1858
1859 switch (gh->msg_type) {
1860 case GSM48_MT_RR_CLSM_CHG:
1861 rc = gsm48_rx_rr_classmark(msg);
1862 break;
1863 case GSM48_MT_RR_GPRS_SUSP_REQ:
1864 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1865 break;
1866 case GSM48_MT_RR_PAG_RESP:
1867 rc = gsm48_rr_rx_pag_resp(msg);
1868 break;
1869 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1870 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welteca745e22009-07-29 12:10:35 +02001871 /* We've successfully modified the MS side of the channel,
1872 * now go on to modify the BTS side of the channel */
Harald Welte39274f42009-07-29 15:41:29 +02001873 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte59b04682009-06-10 05:40:52 +08001874 rc = rsl_chan_mode_modify_req(msg->lchan);
1875 break;
1876 case GSM48_MT_RR_STATUS:
1877 rc = gsm48_rx_rr_status(msg);
1878 break;
1879 case GSM48_MT_RR_MEAS_REP:
1880 rc = gsm48_rx_rr_meas_rep(msg);
1881 break;
Harald Welte (local)b5103922009-08-15 23:32:44 +02001882 case GSM48_MT_RR_APP_INFO:
1883 rc = gsm48_rx_rr_app_info(msg);
1884 break;
Harald Welte59b04682009-06-10 05:40:52 +08001885 default:
1886 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
1887 gh->msg_type);
1888 break;
1889 }
1890
1891 return rc;
1892}
1893
Harald Welte85a163c2009-08-10 11:43:22 +02001894/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Harald Welte59b04682009-06-10 05:40:52 +08001895int gsm48_send_rr_release(struct gsm_lchan *lchan)
1896{
1897 struct msgb *msg = gsm48_msgb_alloc();
1898 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1899 u_int8_t *cause;
1900
1901 msg->lchan = lchan;
1902 gh->proto_discr = GSM48_PDISC_RR;
1903 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1904
1905 cause = msgb_put(msg, 1);
1906 cause[0] = GSM48_RR_CAUSE_NORMAL;
1907
1908 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1909 lchan->nr, lchan->type);
1910
Harald Welteafe3c232009-07-19 18:36:49 +02001911 /* Send actual release request to MS */
Harald Welte36fe2e82009-07-23 21:13:03 +02001912 gsm48_sendmsg(msg, NULL);
Harald Welte68b7df22009-08-08 16:03:15 +02001913 /* FIXME: Start Timer T3109 */
Harald Welteafe3c232009-07-19 18:36:49 +02001914
1915 /* Deactivate the SACCH on the BTS side */
1916 return rsl_deact_sacch(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001917}
1918
Harald Welte (local)b5103922009-08-15 23:32:44 +02001919int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
1920 u_int8_t apdu_len, u_int8_t *apdu)
1921{
1922 struct msgb *msg = gsm48_msgb_alloc();
1923 struct gsm48_hdr *gh;
1924
1925 msg->lchan = lchan;
1926
1927 DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
1928 apdu_id, apdu_len);
1929
1930 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len);
1931 gh->proto_discr = GSM48_PDISC_RR;
1932 gh->msg_type = GSM48_MT_RR_APP_INFO;
1933 gh->data[0] = apdu_id;
1934 gh->data[1] = apdu_len;
1935 memcpy(gh->data+2, apdu, apdu_len);
1936
1937 return gsm48_sendmsg(msg, NULL);
1938}
1939
Harald Welte59b04682009-06-10 05:40:52 +08001940/* Call Control */
1941
1942/* The entire call control code is written in accordance with Figure 7.10c
1943 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1944 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1945 * it for voice */
1946
Harald Welte03740842009-06-10 23:11:52 +08001947static void new_cc_state(struct gsm_trans *trans, int state)
1948{
1949 if (state > 31 || state < 0)
1950 return;
1951
1952 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltec2189a62009-07-23 18:56:43 +02001953 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte03740842009-06-10 23:11:52 +08001954
Harald Weltec2189a62009-07-23 18:56:43 +02001955 trans->cc.state = state;
Harald Welte03740842009-06-10 23:11:52 +08001956}
1957
1958static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08001959{
1960 struct msgb *msg = gsm48_msgb_alloc();
1961 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1962 u_int8_t *cause, *call_state;
1963
Harald Welte59b04682009-06-10 05:40:52 +08001964 gh->msg_type = GSM48_MT_CC_STATUS;
1965
1966 cause = msgb_put(msg, 3);
1967 cause[0] = 2;
1968 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1969 cause[2] = 0x80 | 30; /* response to status inquiry */
1970
1971 call_state = msgb_put(msg, 1);
1972 call_state[0] = 0xc0 | 0x00;
1973
Harald Welte36fe2e82009-07-23 21:13:03 +02001974 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08001975}
1976
1977static int gsm48_tx_simple(struct gsm_lchan *lchan,
1978 u_int8_t pdisc, u_int8_t msg_type)
1979{
1980 struct msgb *msg = gsm48_msgb_alloc();
1981 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1982
1983 msg->lchan = lchan;
1984
1985 gh->proto_discr = pdisc;
1986 gh->msg_type = msg_type;
1987
Harald Welte36fe2e82009-07-23 21:13:03 +02001988 return gsm48_sendmsg(msg, NULL);
Harald Welte59b04682009-06-10 05:40:52 +08001989}
1990
Harald Welte03740842009-06-10 23:11:52 +08001991static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1992{
Harald Weltec2189a62009-07-23 18:56:43 +02001993 if (bsc_timer_pending(&trans->cc.timer)) {
1994 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1995 bsc_del_timer(&trans->cc.timer);
1996 trans->cc.Tcurrent = 0;
Harald Welte03740842009-06-10 23:11:52 +08001997 }
1998}
1999
2000static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
2001 int msg_type, struct gsm_mncc *mncc)
2002{
2003 struct msgb *msg;
2004
2005 if (trans)
2006 if (trans->lchan)
Harald Welte4861c822009-07-23 21:21:14 +02002007 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08002008 "Sending '%s' to MNCC.\n",
2009 trans->lchan->ts->trx->bts->nr,
2010 trans->lchan->ts->trx->nr,
2011 trans->lchan->ts->nr, trans->transaction_id,
2012 (trans->subscr)?(trans->subscr->extension):"-",
2013 get_mncc_name(msg_type));
2014 else
2015 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
2016 "Sending '%s' to MNCC.\n",
2017 (trans->subscr)?(trans->subscr->extension):"-",
2018 get_mncc_name(msg_type));
2019 else
2020 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
2021 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
2022
2023 mncc->msg_type = msg_type;
2024
Harald Welte9cfc9352009-06-26 19:39:35 +02002025 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte03740842009-06-10 23:11:52 +08002026 if (!msg)
2027 return -ENOMEM;
2028 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
2029 msgb_enqueue(&net->upqueue, msg);
2030
2031 return 0;
2032}
2033
2034int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
2035 u_int32_t callref, int location, int value)
2036{
2037 struct gsm_mncc rel;
2038
Harald Weltecb0595f2009-06-12 01:54:08 +08002039 memset(&rel, 0, sizeof(rel));
Harald Welte03740842009-06-10 23:11:52 +08002040 rel.callref = callref;
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002041 mncc_set_cause(&rel, location, value);
Harald Welte03740842009-06-10 23:11:52 +08002042 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
2043}
2044
Harald Weltec2189a62009-07-23 18:56:43 +02002045/* Call Control Specific transaction release.
2046 * gets called by trans_free, DO NOT CALL YOURSELF! */
2047void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte03740842009-06-10 23:11:52 +08002048{
Harald Welte03740842009-06-10 23:11:52 +08002049 gsm48_stop_cc_timer(trans);
2050
2051 /* send release to L4, if callref still exists */
2052 if (trans->callref) {
2053 /* Ressource unavailable */
Harald Welte0abe5a62009-07-23 19:06:52 +02002054 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002055 GSM48_CAUSE_LOC_PRN_S_LU,
2056 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002057 }
Harald Weltec2189a62009-07-23 18:56:43 +02002058 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte03740842009-06-10 23:11:52 +08002059 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltec2189a62009-07-23 18:56:43 +02002060 if (trans->lchan)
2061 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte03740842009-06-10 23:11:52 +08002062}
2063
2064static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
2065
Harald Welte59b04682009-06-10 05:40:52 +08002066/* call-back from paging the B-end of the connection */
2067static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
2068 struct msgb *msg, void *_lchan, void *param)
2069{
2070 struct gsm_lchan *lchan = _lchan;
Harald Welte03740842009-06-10 23:11:52 +08002071 struct gsm_subscriber *subscr = param;
2072 struct gsm_trans *transt, *tmp;
2073 struct gsm_network *net;
Harald Welte1ff81b52009-06-26 20:17:06 +02002074
Harald Welte59b04682009-06-10 05:40:52 +08002075 if (hooknum != GSM_HOOK_RR_PAGING)
2076 return -EINVAL;
Harald Welte03740842009-06-10 23:11:52 +08002077
2078 if (!subscr)
2079 return -EINVAL;
2080 net = subscr->net;
2081 if (!net) {
2082 DEBUGP(DCC, "Error Network not set!\n");
2083 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002084 }
2085
Harald Welte03740842009-06-10 23:11:52 +08002086 /* check all tranactions (without lchan) for subscriber */
2087 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
2088 if (transt->subscr != subscr || transt->lchan)
2089 continue;
2090 switch (event) {
2091 case GSM_PAGING_SUCCEEDED:
2092 if (!lchan) // paranoid
2093 break;
2094 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
2095 subscr->extension);
2096 /* Assign lchan */
2097 if (!transt->lchan) {
2098 transt->lchan = lchan;
2099 use_lchan(lchan);
2100 }
2101 /* send SETUP request to called party */
Harald Weltec2189a62009-07-23 18:56:43 +02002102 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte03740842009-06-10 23:11:52 +08002103 break;
2104 case GSM_PAGING_EXPIRED:
2105 DEBUGP(DCC, "Paging subscr %s expired!\n",
2106 subscr->extension);
2107 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002108 mncc_release_ind(transt->subscr->net, transt,
2109 transt->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002110 GSM48_CAUSE_LOC_PRN_S_LU,
2111 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08002112 transt->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002113 trans_free(transt);
Harald Welte03740842009-06-10 23:11:52 +08002114 break;
2115 }
2116 }
Harald Welte59b04682009-06-10 05:40:52 +08002117 return 0;
2118}
2119
Harald Welte3c062072009-07-28 18:25:29 +02002120/* some other part of the code sends us a signal */
2121static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2122 void *handler_data, void *signal_data)
2123{
2124 struct gsm_lchan *lchan = signal_data;
2125 struct gsm_bts_trx_ts *ts;
2126 int rc;
2127
2128 if (subsys != SS_ABISIP)
2129 return 0;
2130
2131 /* in case we use direct BTS-to-BTS RTP */
2132 if (ipacc_rtp_direct)
2133 return 0;
2134
2135 ts = lchan->ts;
2136
2137 switch (signal) {
2138 case S_ABISIP_BIND_ACK:
2139 /* the BTS has successfully bound a TCH to a local ip/port,
2140 * which means we can connect our UDP socket to it */
2141 if (ts->abis_ip.rtp_socket) {
2142 rtp_socket_free(ts->abis_ip.rtp_socket);
2143 ts->abis_ip.rtp_socket = NULL;
2144 }
2145
2146 ts->abis_ip.rtp_socket = rtp_socket_create();
2147 if (!ts->abis_ip.rtp_socket)
2148 goto out_err;
2149
2150 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2151 ts->abis_ip.bound_ip,
2152 ts->abis_ip.bound_port);
2153 if (rc < 0)
2154 goto out_err;
2155 break;
2156 case S_ABISIP_DISC_IND:
2157 /* the BTS tells us a RTP stream has been disconnected */
2158 if (ts->abis_ip.rtp_socket) {
2159 rtp_socket_free(ts->abis_ip.rtp_socket);
2160 ts->abis_ip.rtp_socket = NULL;
2161 }
2162 break;
2163 }
2164
2165 return 0;
2166out_err:
2167 /* FIXME: do something */
2168 return 0;
2169}
2170
2171/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2172static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2173{
2174 struct gsm_bts_trx_ts *ts = lchan->ts;
2175 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2176 int rc;
2177
2178 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2179 ntohs(rs->rtp.sin_local.sin_port),
2180 ts->abis_ip.conn_id,
2181 /* FIXME: use RTP payload of bound socket, not BTS*/
2182 ts->abis_ip.rtp_payload2);
2183
2184 return rc;
2185}
2186
Harald Welte59b04682009-06-10 05:40:52 +08002187/* map two ipaccess RTP streams onto each other */
2188static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
2189{
2190 struct gsm_bts *bts = lchan->ts->trx->bts;
2191 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
2192 struct gsm_bts_trx_ts *ts;
Harald Welte3c062072009-07-28 18:25:29 +02002193 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08002194
2195 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2196 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2197 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2198
2199 if (bts->type != remote_bts->type) {
2200 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2201 return -EINVAL;
2202 }
2203
2204 switch (bts->type) {
2205 case GSM_BTS_TYPE_NANOBTS_900:
2206 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte3c062072009-07-28 18:25:29 +02002207 if (!ipacc_rtp_direct) {
2208 /* connect the TCH's to our RTP proxy */
2209 rc = ipacc_connect_proxy_bind(lchan);
2210 if (rc < 0)
2211 return rc;
2212 rc = ipacc_connect_proxy_bind(remote_lchan);
2213
2214 /* connect them with each other */
2215 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2216 remote_lchan->ts->abis_ip.rtp_socket);
2217 } else {
2218 /* directly connect TCH RTP streams to each other */
2219 ts = remote_lchan->ts;
2220 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2221 ts->abis_ip.bound_port,
2222 lchan->ts->abis_ip.conn_id,
2223 ts->abis_ip.rtp_payload2);
2224 if (rc < 0)
2225 return rc;
2226 ts = lchan->ts;
2227 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2228 ts->abis_ip.bound_port,
2229 remote_lchan->ts->abis_ip.conn_id,
2230 ts->abis_ip.rtp_payload2);
2231 }
Harald Welte59b04682009-06-10 05:40:52 +08002232 break;
2233 case GSM_BTS_TYPE_BS11:
2234 trau_mux_map_lchan(lchan, remote_lchan);
2235 break;
2236 default:
2237 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte3c062072009-07-28 18:25:29 +02002238 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002239 break;
2240 }
2241
2242 return 0;
2243}
2244
Harald Welte03740842009-06-10 23:11:52 +08002245/* bridge channels of two transactions */
2246static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte59b04682009-06-10 05:40:52 +08002247{
Harald Weltec2189a62009-07-23 18:56:43 +02002248 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2249 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte59b04682009-06-10 05:40:52 +08002250
Harald Welte03740842009-06-10 23:11:52 +08002251 if (!trans1 || !trans2)
Harald Welte59b04682009-06-10 05:40:52 +08002252 return -EIO;
2253
Harald Welte03740842009-06-10 23:11:52 +08002254 if (!trans1->lchan || !trans2->lchan)
2255 return -EIO;
2256
2257 /* through-connect channel */
2258 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08002259}
2260
Harald Welte03740842009-06-10 23:11:52 +08002261/* enable receive of channels to upqueue */
2262static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2263{
2264 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +08002265
Harald Welte03740842009-06-10 23:11:52 +08002266 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002267 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08002268 if (!trans)
2269 return -EIO;
2270 if (!trans->lchan)
2271 return 0;
2272
2273 // todo IPACCESS
2274 if (enable)
2275 return trau_recv_lchan(trans->lchan, data->callref);
2276 return trau_mux_unmap(NULL, data->callref);
2277}
2278
2279/* send a frame to channel */
2280static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2281{
2282 struct gsm_trans *trans;
2283
2284 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02002285 trans = trans_find_by_callref(net, frame->callref);
Harald Welte03740842009-06-10 23:11:52 +08002286 if (!trans)
2287 return -EIO;
2288 if (!trans->lchan)
2289 return 0;
2290 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2291 trans->lchan->type != GSM_LCHAN_TCH_H)
2292 return 0;
2293
2294 // todo IPACCESS
2295 return trau_send_lchan(trans->lchan,
2296 (struct decoded_trau_frame *)frame->data);
2297}
2298
2299
2300static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2301{
2302 DEBUGP(DCC, "-> STATUS ENQ\n");
2303 return gsm48_cc_tx_status(trans, msg);
2304}
2305
2306static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2307static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2308
2309static void gsm48_cc_timeout(void *arg)
2310{
2311 struct gsm_trans *trans = arg;
2312 int disconnect = 0, release = 0;
Harald Weltebbc636a2009-06-11 14:23:20 +08002313 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2314 int mo_location = GSM48_CAUSE_LOC_USER;
2315 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2316 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte03740842009-06-10 23:11:52 +08002317 struct gsm_mncc mo_rel, l4_rel;
2318
2319 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2320 mo_rel.callref = trans->callref;
2321 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2322 l4_rel.callref = trans->callref;
2323
Harald Weltec2189a62009-07-23 18:56:43 +02002324 switch(trans->cc.Tcurrent) {
Harald Welte03740842009-06-10 23:11:52 +08002325 case 0x303:
2326 release = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002327 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002328 break;
2329 case 0x310:
2330 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002331 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002332 break;
2333 case 0x313:
2334 disconnect = 1;
2335 /* unknown, did not find it in the specs */
2336 break;
2337 case 0x301:
2338 disconnect = 1;
Harald Weltebbc636a2009-06-11 14:23:20 +08002339 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte03740842009-06-10 23:11:52 +08002340 break;
2341 case 0x308:
Harald Weltec2189a62009-07-23 18:56:43 +02002342 if (!trans->cc.T308_second) {
Harald Welte03740842009-06-10 23:11:52 +08002343 /* restart T308 a second time */
Harald Weltec2189a62009-07-23 18:56:43 +02002344 gsm48_cc_tx_release(trans, &trans->cc.msg);
2345 trans->cc.T308_second = 1;
Harald Welte03740842009-06-10 23:11:52 +08002346 break; /* stay in release state */
2347 }
Harald Weltec2189a62009-07-23 18:56:43 +02002348 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002349 return;
2350// release = 1;
2351// l4_cause = 14;
2352// break;
2353 case 0x306:
2354 release = 1;
Harald Weltec2189a62009-07-23 18:56:43 +02002355 mo_cause = trans->cc.msg.cause.value;
2356 mo_location = trans->cc.msg.cause.location;
Harald Welte03740842009-06-10 23:11:52 +08002357 break;
2358 case 0x323:
2359 disconnect = 1;
2360 break;
2361 default:
2362 release = 1;
2363 }
2364
2365 if (release && trans->callref) {
2366 /* process release towards layer 4 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002367 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte03740842009-06-10 23:11:52 +08002368 l4_location, l4_cause);
2369 trans->callref = 0;
2370 }
2371
2372 if (disconnect && trans->callref) {
2373 /* process disconnect towards layer 4 */
2374 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte0abe5a62009-07-23 19:06:52 +02002375 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte03740842009-06-10 23:11:52 +08002376 }
2377
2378 /* process disconnect towards mobile station */
2379 if (disconnect || release) {
2380 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltec2189a62009-07-23 18:56:43 +02002381 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2382 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2383 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte03740842009-06-10 23:11:52 +08002384 mo_rel.cause.diag_len = 3;
2385
2386 if (disconnect)
2387 gsm48_cc_tx_disconnect(trans, &mo_rel);
2388 if (release)
2389 gsm48_cc_tx_release(trans, &mo_rel);
2390 }
2391
2392}
2393
2394static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2395 int sec, int micro)
2396{
2397 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltec2189a62009-07-23 18:56:43 +02002398 trans->cc.timer.cb = gsm48_cc_timeout;
2399 trans->cc.timer.data = trans;
2400 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2401 trans->cc.Tcurrent = current;
Harald Welte03740842009-06-10 23:11:52 +08002402}
2403
2404static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2405{
2406 struct gsm48_hdr *gh = msgb_l3(msg);
2407 u_int8_t msg_type = gh->msg_type & 0xbf;
2408 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2409 struct tlv_parsed tp;
2410 struct gsm_mncc setup;
2411
2412 memset(&setup, 0, sizeof(struct gsm_mncc));
2413 setup.callref = trans->callref;
2414 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2415 /* emergency setup is identified by msg_type */
2416 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2417 setup.emergency = 1;
2418
2419 /* use subscriber as calling party number */
2420 if (trans->subscr) {
2421 setup.fields |= MNCC_F_CALLING;
2422 strncpy(setup.calling.number, trans->subscr->extension,
2423 sizeof(setup.calling.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002424 strncpy(setup.imsi, trans->subscr->imsi,
2425 sizeof(setup.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002426 }
2427 /* bearer capability */
2428 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2429 setup.fields |= MNCC_F_BEARER_CAP;
2430 decode_bearer_cap(&setup.bearer_cap,
2431 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2432 }
2433 /* facility */
2434 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2435 setup.fields |= MNCC_F_FACILITY;
2436 decode_facility(&setup.facility,
2437 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2438 }
2439 /* called party bcd number */
2440 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2441 setup.fields |= MNCC_F_CALLED;
2442 decode_called(&setup.called,
2443 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2444 }
2445 /* user-user */
2446 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2447 setup.fields |= MNCC_F_USERUSER;
2448 decode_useruser(&setup.useruser,
2449 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2450 }
2451 /* ss-version */
2452 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2453 setup.fields |= MNCC_F_SSVERSION;
2454 decode_ssversion(&setup.ssversion,
2455 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2456 }
2457 /* CLIR suppression */
2458 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2459 setup.clir.sup = 1;
2460 /* CLIR invocation */
2461 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2462 setup.clir.inv = 1;
2463 /* cc cap */
2464 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2465 setup.fields |= MNCC_F_CCCAP;
2466 decode_cccap(&setup.cccap,
2467 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2468 }
2469
Harald Welte03740842009-06-10 23:11:52 +08002470 new_cc_state(trans, GSM_CSTATE_INITIATED);
2471
2472 /* indicate setup to MNCC */
Harald Welte0abe5a62009-07-23 19:06:52 +02002473 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte03740842009-06-10 23:11:52 +08002474
Harald Welteca745e22009-07-29 12:10:35 +02002475 /* MNCC code will modify the channel asynchronously, we should
2476 * ipaccess-bind only after the modification has been made to the
2477 * lchan->tch_mode */
Harald Welte03740842009-06-10 23:11:52 +08002478 return 0;
2479}
2480
2481static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte59b04682009-06-10 05:40:52 +08002482{
2483 struct msgb *msg = gsm48_msgb_alloc();
2484 struct gsm48_hdr *gh;
Harald Welte03740842009-06-10 23:11:52 +08002485 struct gsm_mncc *setup = arg;
Harald Welte165fc332009-07-23 21:36:44 +02002486 int rc, trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002487
2488 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2489
Harald Welte03740842009-06-10 23:11:52 +08002490 /* transaction id must not be assigned */
2491 if (trans->transaction_id != 0xff) { /* unasssigned */
2492 DEBUGP(DCC, "TX Setup with assigned transaction. "
2493 "This is not allowed!\n");
2494 /* Temporarily out of order */
Harald Welte0abe5a62009-07-23 19:06:52 +02002495 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002496 GSM48_CAUSE_LOC_PRN_S_LU,
2497 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002498 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002499 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002500 return rc;
2501 }
2502
2503 /* Get free transaction_id */
Harald Welte165fc332009-07-23 21:36:44 +02002504 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2505 if (trans_id < 0) {
Harald Welte03740842009-06-10 23:11:52 +08002506 /* no free transaction ID */
Harald Welte0abe5a62009-07-23 19:06:52 +02002507 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08002508 GSM48_CAUSE_LOC_PRN_S_LU,
2509 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08002510 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002511 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002512 return rc;
2513 }
Harald Welte165fc332009-07-23 21:36:44 +02002514 trans->transaction_id = trans_id;
Harald Welte59b04682009-06-10 05:40:52 +08002515
Harald Welte59b04682009-06-10 05:40:52 +08002516 gh->msg_type = GSM48_MT_CC_SETUP;
2517
Harald Welte03740842009-06-10 23:11:52 +08002518 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte59b04682009-06-10 05:40:52 +08002519
Harald Welte03740842009-06-10 23:11:52 +08002520 /* bearer capability */
2521 if (setup->fields & MNCC_F_BEARER_CAP)
2522 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2523 /* facility */
2524 if (setup->fields & MNCC_F_FACILITY)
2525 encode_facility(msg, 0, &setup->facility);
2526 /* progress */
2527 if (setup->fields & MNCC_F_PROGRESS)
2528 encode_progress(msg, 0, &setup->progress);
2529 /* calling party BCD number */
2530 if (setup->fields & MNCC_F_CALLING)
2531 encode_calling(msg, &setup->calling);
2532 /* called party BCD number */
2533 if (setup->fields & MNCC_F_CALLED)
2534 encode_called(msg, &setup->called);
2535 /* user-user */
2536 if (setup->fields & MNCC_F_USERUSER)
2537 encode_useruser(msg, 0, &setup->useruser);
2538 /* redirecting party BCD number */
2539 if (setup->fields & MNCC_F_REDIRECTING)
2540 encode_redirecting(msg, &setup->redirecting);
2541 /* signal */
2542 if (setup->fields & MNCC_F_SIGNAL)
2543 encode_signal(msg, setup->signal);
2544
2545 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte59b04682009-06-10 05:40:52 +08002546
Harald Welte36fe2e82009-07-23 21:13:03 +02002547 return gsm48_sendmsg(msg, trans);
Harald Welte59b04682009-06-10 05:40:52 +08002548}
2549
Harald Welte03740842009-06-10 23:11:52 +08002550static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2551{
2552 struct gsm48_hdr *gh = msgb_l3(msg);
2553 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2554 struct tlv_parsed tp;
2555 struct gsm_mncc call_conf;
2556
2557 gsm48_stop_cc_timer(trans);
2558 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2559
2560 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2561 call_conf.callref = trans->callref;
2562 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2563#if 0
2564 /* repeat */
2565 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2566 call_conf.repeat = 1;
2567 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2568 call_conf.repeat = 2;
2569#endif
2570 /* bearer capability */
2571 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2572 call_conf.fields |= MNCC_F_BEARER_CAP;
2573 decode_bearer_cap(&call_conf.bearer_cap,
2574 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2575 }
2576 /* cause */
2577 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2578 call_conf.fields |= MNCC_F_CAUSE;
2579 decode_cause(&call_conf.cause,
2580 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2581 }
2582 /* cc cap */
2583 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2584 call_conf.fields |= MNCC_F_CCCAP;
2585 decode_cccap(&call_conf.cccap,
2586 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2587 }
2588
2589 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2590
Harald Welte0abe5a62009-07-23 19:06:52 +02002591 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2592 &call_conf);
Harald Welte03740842009-06-10 23:11:52 +08002593}
2594
2595static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2596{
2597 struct gsm_mncc *proceeding = arg;
2598 struct msgb *msg = gsm48_msgb_alloc();
2599 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2600
Harald Welte03740842009-06-10 23:11:52 +08002601 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2602
2603 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2604
2605 /* bearer capability */
2606 if (proceeding->fields & MNCC_F_BEARER_CAP)
2607 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2608 /* facility */
2609 if (proceeding->fields & MNCC_F_FACILITY)
2610 encode_facility(msg, 0, &proceeding->facility);
2611 /* progress */
2612 if (proceeding->fields & MNCC_F_PROGRESS)
2613 encode_progress(msg, 0, &proceeding->progress);
2614
Harald Welte36fe2e82009-07-23 21:13:03 +02002615 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002616}
2617
2618static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2619{
2620 struct gsm48_hdr *gh = msgb_l3(msg);
2621 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2622 struct tlv_parsed tp;
2623 struct gsm_mncc alerting;
2624
2625 gsm48_stop_cc_timer(trans);
2626 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2627
2628 memset(&alerting, 0, sizeof(struct gsm_mncc));
2629 alerting.callref = trans->callref;
2630 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2631 /* facility */
2632 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2633 alerting.fields |= MNCC_F_FACILITY;
2634 decode_facility(&alerting.facility,
2635 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2636 }
2637
2638 /* progress */
2639 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2640 alerting.fields |= MNCC_F_PROGRESS;
2641 decode_progress(&alerting.progress,
2642 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2643 }
2644 /* ss-version */
2645 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2646 alerting.fields |= MNCC_F_SSVERSION;
2647 decode_ssversion(&alerting.ssversion,
2648 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2649 }
2650
2651 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2652
Harald Welte0abe5a62009-07-23 19:06:52 +02002653 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2654 &alerting);
Harald Welte03740842009-06-10 23:11:52 +08002655}
2656
2657static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2658{
2659 struct gsm_mncc *alerting = arg;
2660 struct msgb *msg = gsm48_msgb_alloc();
2661 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2662
Harald Welte03740842009-06-10 23:11:52 +08002663 gh->msg_type = GSM48_MT_CC_ALERTING;
2664
2665 /* facility */
2666 if (alerting->fields & MNCC_F_FACILITY)
2667 encode_facility(msg, 0, &alerting->facility);
2668 /* progress */
2669 if (alerting->fields & MNCC_F_PROGRESS)
2670 encode_progress(msg, 0, &alerting->progress);
2671 /* user-user */
2672 if (alerting->fields & MNCC_F_USERUSER)
2673 encode_useruser(msg, 0, &alerting->useruser);
2674
2675 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2676
Harald Welte36fe2e82009-07-23 21:13:03 +02002677 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002678}
2679
2680static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2681{
2682 struct gsm_mncc *progress = arg;
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_PROGRESS;
2687
2688 /* progress */
2689 encode_progress(msg, 1, &progress->progress);
2690 /* user-user */
2691 if (progress->fields & MNCC_F_USERUSER)
2692 encode_useruser(msg, 0, &progress->useruser);
2693
Harald Welte36fe2e82009-07-23 21:13:03 +02002694 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002695}
2696
2697static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2698{
2699 struct gsm_mncc *connect = arg;
2700 struct msgb *msg = gsm48_msgb_alloc();
2701 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2702
Harald Welte03740842009-06-10 23:11:52 +08002703 gh->msg_type = GSM48_MT_CC_CONNECT;
2704
2705 gsm48_stop_cc_timer(trans);
2706 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2707
2708 /* facility */
2709 if (connect->fields & MNCC_F_FACILITY)
2710 encode_facility(msg, 0, &connect->facility);
2711 /* progress */
2712 if (connect->fields & MNCC_F_PROGRESS)
2713 encode_progress(msg, 0, &connect->progress);
2714 /* connected number */
2715 if (connect->fields & MNCC_F_CONNECTED)
2716 encode_connected(msg, &connect->connected);
2717 /* user-user */
2718 if (connect->fields & MNCC_F_USERUSER)
2719 encode_useruser(msg, 0, &connect->useruser);
2720
2721 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2722
Harald Welte36fe2e82009-07-23 21:13:03 +02002723 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002724}
2725
2726static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2727{
2728 struct gsm48_hdr *gh = msgb_l3(msg);
2729 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2730 struct tlv_parsed tp;
2731 struct gsm_mncc connect;
2732
2733 gsm48_stop_cc_timer(trans);
2734
2735 memset(&connect, 0, sizeof(struct gsm_mncc));
2736 connect.callref = trans->callref;
2737 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2738 /* use subscriber as connected party number */
2739 if (trans->subscr) {
2740 connect.fields |= MNCC_F_CONNECTED;
2741 strncpy(connect.connected.number, trans->subscr->extension,
2742 sizeof(connect.connected.number)-1);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02002743 strncpy(connect.imsi, trans->subscr->imsi,
2744 sizeof(connect.imsi)-1);
Harald Welte03740842009-06-10 23:11:52 +08002745 }
2746 /* facility */
2747 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2748 connect.fields |= MNCC_F_FACILITY;
2749 decode_facility(&connect.facility,
2750 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2751 }
2752 /* user-user */
2753 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2754 connect.fields |= MNCC_F_USERUSER;
2755 decode_useruser(&connect.useruser,
2756 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2757 }
2758 /* ss-version */
2759 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2760 connect.fields |= MNCC_F_SSVERSION;
2761 decode_ssversion(&connect.ssversion,
2762 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2763 }
2764
2765 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2766
Harald Welte0abe5a62009-07-23 19:06:52 +02002767 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte03740842009-06-10 23:11:52 +08002768}
2769
2770
2771static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2772{
2773 struct gsm_mncc connect_ack;
2774
2775 gsm48_stop_cc_timer(trans);
2776
2777 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2778
2779 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2780 connect_ack.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02002781 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte03740842009-06-10 23:11:52 +08002782 &connect_ack);
2783}
2784
2785static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2786{
2787 struct msgb *msg = gsm48_msgb_alloc();
2788 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2789
Harald Welte03740842009-06-10 23:11:52 +08002790 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2791
2792 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2793
Harald Welte36fe2e82009-07-23 21:13:03 +02002794 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002795}
2796
2797static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2798{
2799 struct gsm48_hdr *gh = msgb_l3(msg);
2800 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2801 struct tlv_parsed tp;
2802 struct gsm_mncc disc;
2803
2804 gsm48_stop_cc_timer(trans);
2805
2806 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2807
2808 memset(&disc, 0, sizeof(struct gsm_mncc));
2809 disc.callref = trans->callref;
2810 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2811 /* cause */
2812 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2813 disc.fields |= MNCC_F_CAUSE;
2814 decode_cause(&disc.cause,
2815 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2816 }
2817 /* facility */
2818 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2819 disc.fields |= MNCC_F_FACILITY;
2820 decode_facility(&disc.facility,
2821 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2822 }
2823 /* user-user */
2824 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2825 disc.fields |= MNCC_F_USERUSER;
2826 decode_useruser(&disc.useruser,
2827 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2828 }
2829 /* ss-version */
2830 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2831 disc.fields |= MNCC_F_SSVERSION;
2832 decode_ssversion(&disc.ssversion,
2833 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2834 }
2835
Harald Welte0abe5a62009-07-23 19:06:52 +02002836 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte03740842009-06-10 23:11:52 +08002837
2838}
2839
Harald Weltebbc636a2009-06-11 14:23:20 +08002840static struct gsm_mncc_cause default_cause = {
2841 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2842 .coding = 0,
2843 .rec = 0,
2844 .rec_val = 0,
2845 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2846 .diag_len = 0,
2847 .diag = { 0 },
2848};
Harald Welte03740842009-06-10 23:11:52 +08002849
2850static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2851{
2852 struct gsm_mncc *disc = arg;
2853 struct msgb *msg = gsm48_msgb_alloc();
2854 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2855
Harald Welte03740842009-06-10 23:11:52 +08002856 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2857
2858 gsm48_stop_cc_timer(trans);
2859 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2860
2861 /* cause */
2862 if (disc->fields & MNCC_F_CAUSE)
2863 encode_cause(msg, 1, &disc->cause);
2864 else
2865 encode_cause(msg, 1, &default_cause);
2866
2867 /* facility */
2868 if (disc->fields & MNCC_F_FACILITY)
2869 encode_facility(msg, 0, &disc->facility);
2870 /* progress */
2871 if (disc->fields & MNCC_F_PROGRESS)
2872 encode_progress(msg, 0, &disc->progress);
2873 /* user-user */
2874 if (disc->fields & MNCC_F_USERUSER)
2875 encode_useruser(msg, 0, &disc->useruser);
2876
2877 /* store disconnect cause for T306 expiry */
Harald Weltec2189a62009-07-23 18:56:43 +02002878 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002879
2880 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2881
Harald Welte36fe2e82009-07-23 21:13:03 +02002882 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002883}
2884
2885static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2886{
2887 struct gsm48_hdr *gh = msgb_l3(msg);
2888 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2889 struct tlv_parsed tp;
2890 struct gsm_mncc rel;
2891 int rc;
2892
2893 gsm48_stop_cc_timer(trans);
2894
2895 memset(&rel, 0, sizeof(struct gsm_mncc));
2896 rel.callref = trans->callref;
2897 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2898 /* cause */
2899 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2900 rel.fields |= MNCC_F_CAUSE;
2901 decode_cause(&rel.cause,
2902 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2903 }
2904 /* facility */
2905 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2906 rel.fields |= MNCC_F_FACILITY;
2907 decode_facility(&rel.facility,
2908 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2909 }
2910 /* user-user */
2911 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2912 rel.fields |= MNCC_F_USERUSER;
2913 decode_useruser(&rel.useruser,
2914 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2915 }
2916 /* ss-version */
2917 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2918 rel.fields |= MNCC_F_SSVERSION;
2919 decode_ssversion(&rel.ssversion,
2920 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2921 }
2922
Harald Weltec2189a62009-07-23 18:56:43 +02002923 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08002924 /* release collision 5.4.5 */
Harald Welte0abe5a62009-07-23 19:06:52 +02002925 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002926 } else {
Harald Welte0abe5a62009-07-23 19:06:52 +02002927 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02002928 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte0abe5a62009-07-23 19:06:52 +02002929 GSM48_MT_CC_RELEASE_COMPL);
2930 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte03740842009-06-10 23:11:52 +08002931 }
2932
2933 new_cc_state(trans, GSM_CSTATE_NULL);
2934
2935 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02002936 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08002937
2938 return rc;
2939}
2940
2941static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2942{
2943 struct gsm_mncc *rel = arg;
2944 struct msgb *msg = gsm48_msgb_alloc();
2945 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2946
Harald Welte03740842009-06-10 23:11:52 +08002947 gh->msg_type = GSM48_MT_CC_RELEASE;
2948
2949 trans->callref = 0;
2950
2951 gsm48_stop_cc_timer(trans);
2952 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2953
2954 /* cause */
2955 if (rel->fields & MNCC_F_CAUSE)
2956 encode_cause(msg, 0, &rel->cause);
2957 /* facility */
2958 if (rel->fields & MNCC_F_FACILITY)
2959 encode_facility(msg, 0, &rel->facility);
2960 /* user-user */
2961 if (rel->fields & MNCC_F_USERUSER)
2962 encode_useruser(msg, 0, &rel->useruser);
2963
Harald Weltec2189a62009-07-23 18:56:43 +02002964 trans->cc.T308_second = 0;
2965 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte03740842009-06-10 23:11:52 +08002966
Harald Weltec2189a62009-07-23 18:56:43 +02002967 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte03740842009-06-10 23:11:52 +08002968 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2969
Harald Welte36fe2e82009-07-23 21:13:03 +02002970 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08002971}
2972
2973static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2974{
2975 struct gsm48_hdr *gh = msgb_l3(msg);
2976 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2977 struct tlv_parsed tp;
2978 struct gsm_mncc rel;
2979 int rc = 0;
2980
2981 gsm48_stop_cc_timer(trans);
2982
2983 memset(&rel, 0, sizeof(struct gsm_mncc));
2984 rel.callref = trans->callref;
2985 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2986 /* cause */
2987 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2988 rel.fields |= MNCC_F_CAUSE;
2989 decode_cause(&rel.cause,
2990 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2991 }
2992 /* facility */
2993 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2994 rel.fields |= MNCC_F_FACILITY;
2995 decode_facility(&rel.facility,
2996 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2997 }
2998 /* user-user */
2999 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3000 rel.fields |= MNCC_F_USERUSER;
3001 decode_useruser(&rel.useruser,
3002 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3003 }
3004 /* ss-version */
3005 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3006 rel.fields |= MNCC_F_SSVERSION;
3007 decode_ssversion(&rel.ssversion,
3008 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3009 }
3010
3011 if (trans->callref) {
Harald Weltec2189a62009-07-23 18:56:43 +02003012 switch (trans->cc.state) {
Harald Welte03740842009-06-10 23:11:52 +08003013 case GSM_CSTATE_CALL_PRESENT:
Harald Welte0abe5a62009-07-23 19:06:52 +02003014 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08003015 MNCC_REJ_IND, &rel);
3016 break;
3017 case GSM_CSTATE_RELEASE_REQ:
Harald Welte0abe5a62009-07-23 19:06:52 +02003018 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08003019 MNCC_REL_CNF, &rel);
3020 break;
3021 default:
Harald Welte0abe5a62009-07-23 19:06:52 +02003022 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte03740842009-06-10 23:11:52 +08003023 MNCC_REL_IND, &rel);
3024 }
3025 }
3026
3027 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003028 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003029
3030 return rc;
3031}
3032
3033static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
3034{
3035 struct gsm_mncc *rel = arg;
3036 struct msgb *msg = gsm48_msgb_alloc();
3037 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3038
Harald Welte03740842009-06-10 23:11:52 +08003039 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
3040
3041 trans->callref = 0;
3042
3043 gsm48_stop_cc_timer(trans);
3044
3045 /* cause */
3046 if (rel->fields & MNCC_F_CAUSE)
3047 encode_cause(msg, 0, &rel->cause);
3048 /* facility */
3049 if (rel->fields & MNCC_F_FACILITY)
3050 encode_facility(msg, 0, &rel->facility);
3051 /* user-user */
3052 if (rel->fields & MNCC_F_USERUSER)
3053 encode_useruser(msg, 0, &rel->useruser);
3054
Harald Weltec2189a62009-07-23 18:56:43 +02003055 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003056
Harald Welte36fe2e82009-07-23 21:13:03 +02003057 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003058}
3059
3060static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
3061{
3062 struct gsm48_hdr *gh = msgb_l3(msg);
3063 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3064 struct tlv_parsed tp;
3065 struct gsm_mncc fac;
3066
3067 memset(&fac, 0, sizeof(struct gsm_mncc));
3068 fac.callref = trans->callref;
3069 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
3070 /* facility */
3071 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
3072 fac.fields |= MNCC_F_FACILITY;
3073 decode_facility(&fac.facility,
3074 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
3075 }
3076 /* ss-version */
3077 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3078 fac.fields |= MNCC_F_SSVERSION;
3079 decode_ssversion(&fac.ssversion,
3080 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3081 }
3082
Harald Welte0abe5a62009-07-23 19:06:52 +02003083 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte03740842009-06-10 23:11:52 +08003084}
3085
3086static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
3087{
3088 struct gsm_mncc *fac = arg;
3089 struct msgb *msg = gsm48_msgb_alloc();
3090 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3091
Harald Welte03740842009-06-10 23:11:52 +08003092 gh->msg_type = GSM48_MT_CC_FACILITY;
3093
3094 /* facility */
3095 encode_facility(msg, 1, &fac->facility);
3096
Harald Welte36fe2e82009-07-23 21:13:03 +02003097 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003098}
3099
3100static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
3101{
3102 struct gsm_mncc hold;
3103
3104 memset(&hold, 0, sizeof(struct gsm_mncc));
3105 hold.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003106 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte03740842009-06-10 23:11:52 +08003107}
3108
3109static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3110{
3111 struct msgb *msg = gsm48_msgb_alloc();
3112 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3113
Harald Welte03740842009-06-10 23:11:52 +08003114 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3115
Harald Welte36fe2e82009-07-23 21:13:03 +02003116 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003117}
3118
3119static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3120{
3121 struct gsm_mncc *hold_rej = arg;
3122 struct msgb *msg = gsm48_msgb_alloc();
3123 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3124
Harald Welte03740842009-06-10 23:11:52 +08003125 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3126
3127 /* cause */
3128 if (hold_rej->fields & MNCC_F_CAUSE)
3129 encode_cause(msg, 1, &hold_rej->cause);
3130 else
3131 encode_cause(msg, 1, &default_cause);
3132
Harald Welte36fe2e82009-07-23 21:13:03 +02003133 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003134}
3135
3136static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3137{
3138 struct gsm_mncc retrieve;
3139
3140 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3141 retrieve.callref = trans->callref;
Harald Welte0abe5a62009-07-23 19:06:52 +02003142 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3143 &retrieve);
Harald Welte03740842009-06-10 23:11:52 +08003144}
3145
3146static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3147{
3148 struct msgb *msg = gsm48_msgb_alloc();
3149 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3150
Harald Welte03740842009-06-10 23:11:52 +08003151 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3152
Harald Welte36fe2e82009-07-23 21:13:03 +02003153 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003154}
3155
3156static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3157{
3158 struct gsm_mncc *retrieve_rej = arg;
3159 struct msgb *msg = gsm48_msgb_alloc();
3160 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3161
Harald Welte03740842009-06-10 23:11:52 +08003162 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3163
3164 /* cause */
3165 if (retrieve_rej->fields & MNCC_F_CAUSE)
3166 encode_cause(msg, 1, &retrieve_rej->cause);
3167 else
3168 encode_cause(msg, 1, &default_cause);
3169
Harald Welte36fe2e82009-07-23 21:13:03 +02003170 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003171}
3172
3173static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3174{
3175 struct gsm48_hdr *gh = msgb_l3(msg);
3176 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3177 struct tlv_parsed tp;
3178 struct gsm_mncc dtmf;
3179
3180 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3181 dtmf.callref = trans->callref;
3182 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3183 /* keypad facility */
3184 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3185 dtmf.fields |= MNCC_F_KEYPAD;
3186 decode_keypad(&dtmf.keypad,
3187 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3188 }
3189
Harald Welte0abe5a62009-07-23 19:06:52 +02003190 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003191}
3192
3193static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3194{
3195 struct gsm_mncc *dtmf = arg;
3196 struct msgb *msg = gsm48_msgb_alloc();
3197 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3198
Harald Welte03740842009-06-10 23:11:52 +08003199 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3200
3201 /* keypad */
3202 if (dtmf->fields & MNCC_F_KEYPAD)
3203 encode_keypad(msg, dtmf->keypad);
3204
Harald Welte36fe2e82009-07-23 21:13:03 +02003205 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003206}
3207
3208static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3209{
3210 struct gsm_mncc *dtmf = arg;
3211 struct msgb *msg = gsm48_msgb_alloc();
3212 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3213
Harald Welte03740842009-06-10 23:11:52 +08003214 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3215
3216 /* cause */
3217 if (dtmf->fields & MNCC_F_CAUSE)
3218 encode_cause(msg, 1, &dtmf->cause);
3219 else
3220 encode_cause(msg, 1, &default_cause);
3221
Harald Welte36fe2e82009-07-23 21:13:03 +02003222 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003223}
3224
3225static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3226{
3227 struct msgb *msg = gsm48_msgb_alloc();
3228 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3229
Harald Welte03740842009-06-10 23:11:52 +08003230 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3231
Harald Welte36fe2e82009-07-23 21:13:03 +02003232 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003233}
3234
3235static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3236{
3237 struct gsm_mncc dtmf;
3238
3239 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3240 dtmf.callref = trans->callref;
3241
Harald Welte0abe5a62009-07-23 19:06:52 +02003242 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte03740842009-06-10 23:11:52 +08003243}
3244
3245static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3246{
3247 struct gsm48_hdr *gh = msgb_l3(msg);
3248 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3249 struct tlv_parsed tp;
3250 struct gsm_mncc modify;
3251
3252 memset(&modify, 0, sizeof(struct gsm_mncc));
3253 modify.callref = trans->callref;
3254 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3255 /* bearer capability */
3256 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3257 modify.fields |= MNCC_F_BEARER_CAP;
3258 decode_bearer_cap(&modify.bearer_cap,
3259 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3260 }
3261
3262 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3263
Harald Welte0abe5a62009-07-23 19:06:52 +02003264 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003265}
3266
3267static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3268{
3269 struct gsm_mncc *modify = arg;
3270 struct msgb *msg = gsm48_msgb_alloc();
3271 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3272
Harald Welte03740842009-06-10 23:11:52 +08003273 gh->msg_type = GSM48_MT_CC_MODIFY;
3274
3275 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3276
3277 /* bearer capability */
3278 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3279
3280 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3281
Harald Welte36fe2e82009-07-23 21:13:03 +02003282 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003283}
3284
3285static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3286{
3287 struct gsm48_hdr *gh = msgb_l3(msg);
3288 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3289 struct tlv_parsed tp;
3290 struct gsm_mncc modify;
3291
3292 gsm48_stop_cc_timer(trans);
3293
3294 memset(&modify, 0, sizeof(struct gsm_mncc));
3295 modify.callref = trans->callref;
3296 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3297 /* bearer capability */
3298 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3299 modify.fields |= MNCC_F_BEARER_CAP;
3300 decode_bearer_cap(&modify.bearer_cap,
3301 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3302 }
3303
3304 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3305
Harald Welte0abe5a62009-07-23 19:06:52 +02003306 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003307}
3308
3309static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3310{
3311 struct gsm_mncc *modify = arg;
3312 struct msgb *msg = gsm48_msgb_alloc();
3313 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3314
Harald Welte03740842009-06-10 23:11:52 +08003315 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3316
3317 /* bearer capability */
3318 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3319
3320 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3321
Harald Welte36fe2e82009-07-23 21:13:03 +02003322 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003323}
3324
3325static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3326{
3327 struct gsm48_hdr *gh = msgb_l3(msg);
3328 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3329 struct tlv_parsed tp;
3330 struct gsm_mncc modify;
3331
3332 gsm48_stop_cc_timer(trans);
3333
3334 memset(&modify, 0, sizeof(struct gsm_mncc));
3335 modify.callref = trans->callref;
3336 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3337 /* bearer capability */
3338 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3339 modify.fields |= GSM48_IE_BEARER_CAP;
3340 decode_bearer_cap(&modify.bearer_cap,
3341 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3342 }
3343 /* cause */
3344 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3345 modify.fields |= MNCC_F_CAUSE;
3346 decode_cause(&modify.cause,
3347 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3348 }
3349
3350 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3351
Harald Welte0abe5a62009-07-23 19:06:52 +02003352 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte03740842009-06-10 23:11:52 +08003353}
3354
3355static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3356{
3357 struct gsm_mncc *modify = arg;
3358 struct msgb *msg = gsm48_msgb_alloc();
3359 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3360
Harald Welte03740842009-06-10 23:11:52 +08003361 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3362
3363 /* bearer capability */
3364 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3365 /* cause */
3366 encode_cause(msg, 1, &modify->cause);
3367
3368 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3369
Harald Welte36fe2e82009-07-23 21:13:03 +02003370 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003371}
3372
3373static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3374{
3375 struct gsm_mncc *notify = arg;
3376 struct msgb *msg = gsm48_msgb_alloc();
3377 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3378
Harald Welte03740842009-06-10 23:11:52 +08003379 gh->msg_type = GSM48_MT_CC_NOTIFY;
3380
3381 /* notify */
3382 encode_notify(msg, notify->notify);
3383
Harald Welte36fe2e82009-07-23 21:13:03 +02003384 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003385}
3386
3387static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3388{
3389 struct gsm48_hdr *gh = msgb_l3(msg);
3390 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3391// struct tlv_parsed tp;
3392 struct gsm_mncc notify;
3393
3394 memset(&notify, 0, sizeof(struct gsm_mncc));
3395 notify.callref = trans->callref;
3396// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3397 if (payload_len >= 1)
3398 decode_notify(&notify.notify, gh->data);
3399
Harald Welte0abe5a62009-07-23 19:06:52 +02003400 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte03740842009-06-10 23:11:52 +08003401}
3402
3403static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3404{
3405 struct gsm_mncc *user = arg;
3406 struct msgb *msg = gsm48_msgb_alloc();
3407 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3408
Harald Welte03740842009-06-10 23:11:52 +08003409 gh->msg_type = GSM48_MT_CC_USER_INFO;
3410
3411 /* user-user */
3412 if (user->fields & MNCC_F_USERUSER)
3413 encode_useruser(msg, 1, &user->useruser);
3414 /* more data */
3415 if (user->more)
3416 encode_more(msg);
3417
Harald Welte36fe2e82009-07-23 21:13:03 +02003418 return gsm48_sendmsg(msg, trans);
Harald Welte03740842009-06-10 23:11:52 +08003419}
3420
3421static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3422{
3423 struct gsm48_hdr *gh = msgb_l3(msg);
3424 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3425 struct tlv_parsed tp;
3426 struct gsm_mncc user;
3427
3428 memset(&user, 0, sizeof(struct gsm_mncc));
3429 user.callref = trans->callref;
3430 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3431 /* user-user */
3432 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3433 user.fields |= MNCC_F_USERUSER;
3434 decode_useruser(&user.useruser,
3435 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3436 }
3437 /* more data */
3438 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3439 user.more = 1;
3440
Harald Welte0abe5a62009-07-23 19:06:52 +02003441 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte03740842009-06-10 23:11:52 +08003442}
3443
3444static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3445{
3446 struct gsm_mncc *mode = arg;
Harald Welteca745e22009-07-29 12:10:35 +02003447 int rc;
Harald Welte03740842009-06-10 23:11:52 +08003448
Harald Welteca745e22009-07-29 12:10:35 +02003449 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3450 if (rc < 0)
3451 return rc;
3452
3453 /* FIXME: we not only need to do this after mode modify, but
3454 * also after channel activation */
3455 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3456 mode->lchan_mode != GSM48_CMODE_SIGN)
3457 rc = rsl_ipacc_bind(trans->lchan);
3458
3459 return rc;
Harald Welte03740842009-06-10 23:11:52 +08003460}
3461
3462static struct downstate {
3463 u_int32_t states;
3464 int type;
3465 int (*rout) (struct gsm_trans *trans, void *arg);
3466} downstatelist[] = {
3467 /* mobile originating call establishment */
3468 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3469 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3470 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3471 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3472 {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 */
3473 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3474 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3475 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3476 /* mobile terminating call establishment */
3477 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3478 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3479 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3480 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3481 /* signalling during call */
3482 {SBIT(GSM_CSTATE_ACTIVE),
3483 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3484 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3485 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3486 {ALL_STATES,
3487 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3488 {ALL_STATES,
3489 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3490 {ALL_STATES,
3491 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3492 {SBIT(GSM_CSTATE_ACTIVE),
3493 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3494 {SBIT(GSM_CSTATE_ACTIVE),
3495 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3496 {SBIT(GSM_CSTATE_ACTIVE),
3497 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3498 {SBIT(GSM_CSTATE_ACTIVE),
3499 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3500 {SBIT(GSM_CSTATE_ACTIVE),
3501 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3502 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3503 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3504 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3505 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3506 {SBIT(GSM_CSTATE_ACTIVE),
3507 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3508 /* clearing */
3509 {SBIT(GSM_CSTATE_INITIATED),
3510 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3511 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3512 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3513 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3514 MNCC_REL_REQ, gsm48_cc_tx_release},
3515 /* special */
3516 {ALL_STATES,
3517 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3518};
3519
3520#define DOWNSLLEN \
3521 (sizeof(downstatelist) / sizeof(struct downstate))
3522
3523
3524int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3525{
Harald Welteaa60edb2009-08-09 18:52:33 +02003526 int i, rc = 0;
Harald Welte03740842009-06-10 23:11:52 +08003527 struct gsm_trans *trans = NULL, *transt;
3528 struct gsm_subscriber *subscr;
Harald Welteaa60edb2009-08-09 18:52:33 +02003529 struct gsm_lchan *lchan = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003530 struct gsm_bts *bts = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003531 struct gsm_mncc *data = arg, rel;
3532
3533 /* handle special messages */
3534 switch(msg_type) {
3535 case MNCC_BRIDGE:
3536 return tch_bridge(net, arg);
3537 case MNCC_FRAME_DROP:
3538 return tch_recv(net, arg, 0);
3539 case MNCC_FRAME_RECV:
3540 return tch_recv(net, arg, 1);
3541 case GSM_TRAU_FRAME:
3542 return tch_frame(net, arg);
3543 }
3544
3545 memset(&rel, 0, sizeof(struct gsm_mncc));
3546 rel.callref = data->callref;
3547
3548 /* Find callref */
Harald Weltec2189a62009-07-23 18:56:43 +02003549 trans = trans_find_by_callref(net, data->callref);
Harald Welte03740842009-06-10 23:11:52 +08003550
3551 /* Callref unknown */
3552 if (!trans) {
Harald Welte6e1536e2009-07-04 10:11:24 +02003553 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte03740842009-06-10 23:11:52 +08003554 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3555 "Received '%s' from MNCC with "
3556 "unknown callref %d\n", data->called.number,
3557 get_mncc_name(msg_type), data->callref);
3558 /* Invalid call reference */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003559 return mncc_release_ind(net, NULL, data->callref,
3560 GSM48_CAUSE_LOC_PRN_S_LU,
3561 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte03740842009-06-10 23:11:52 +08003562 }
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003563 if (!data->called.number[0] && !data->imsi[0]) {
3564 DEBUGP(DCC, "(bts - trx - ts - ti) "
3565 "Received '%s' from MNCC with "
3566 "no number or IMSI\n", get_mncc_name(msg_type));
3567 /* Invalid number */
3568 return mncc_release_ind(net, NULL, data->callref,
3569 GSM48_CAUSE_LOC_PRN_S_LU,
3570 GSM48_CC_CAUSE_INV_NR_FORMAT);
3571 }
Harald Welte03740842009-06-10 23:11:52 +08003572 /* New transaction due to setup, find subscriber */
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003573 if (data->called.number[0])
Harald Welte75350412009-07-23 18:46:00 +02003574 subscr = subscr_get_by_extension(net,
3575 data->called.number);
Andreas Eversberg9eaa5da2009-06-15 23:22:09 +02003576 else
Harald Welte75350412009-07-23 18:46:00 +02003577 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte03740842009-06-10 23:11:52 +08003578 /* If subscriber is not found */
3579 if (!subscr) {
3580 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3581 "Received '%s' from MNCC with "
3582 "unknown subscriber %s\n", data->called.number,
3583 get_mncc_name(msg_type), data->called.number);
3584 /* Unknown subscriber */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003585 return mncc_release_ind(net, NULL, data->callref,
3586 GSM48_CAUSE_LOC_PRN_S_LU,
3587 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte03740842009-06-10 23:11:52 +08003588 }
3589 /* If subscriber is not "attached" */
3590 if (!subscr->lac) {
3591 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3592 "Received '%s' from MNCC with "
3593 "detached subscriber %s\n", data->called.number,
3594 get_mncc_name(msg_type), data->called.number);
3595 subscr_put(subscr);
3596 /* Temporarily out of order */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003597 return mncc_release_ind(net, NULL, data->callref,
3598 GSM48_CAUSE_LOC_PRN_S_LU,
3599 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte03740842009-06-10 23:11:52 +08003600 }
3601 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003602 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3603 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003604 DEBUGP(DCC, "No memory for trans.\n");
3605 subscr_put(subscr);
3606 /* Ressource unavailable */
Andreas Eversbergb992a8a2009-06-14 22:14:12 +08003607 mncc_release_ind(net, NULL, data->callref,
3608 GSM48_CAUSE_LOC_PRN_S_LU,
3609 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte03740842009-06-10 23:11:52 +08003610 return -ENOMEM;
3611 }
Harald Welte03740842009-06-10 23:11:52 +08003612 /* Find lchan */
Harald Welteaa60edb2009-08-09 18:52:33 +02003613 lchan = lchan_for_subscr(subscr);
Harald Welte03740842009-06-10 23:11:52 +08003614 /* If subscriber has no lchan */
3615 if (!lchan) {
3616 /* find transaction with this subscriber already paging */
3617 llist_for_each_entry(transt, &net->trans_list, entry) {
3618 /* Transaction of our lchan? */
3619 if (transt == trans ||
3620 transt->subscr != subscr)
3621 continue;
3622 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3623 "Received '%s' from MNCC with "
3624 "unallocated channel, paging already "
3625 "started.\n", bts->nr,
3626 data->called.number,
3627 get_mncc_name(msg_type));
3628 return 0;
3629 }
3630 /* store setup informations until paging was successfull */
Harald Weltec2189a62009-07-23 18:56:43 +02003631 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Welte2a3a81b2009-08-01 19:31:47 +02003632 /* Trigger paging */
3633 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3634 setup_trig_pag_evt, subscr);
Harald Welte03740842009-06-10 23:11:52 +08003635 return 0;
3636 }
3637 /* Assign lchan */
3638 trans->lchan = lchan;
3639 use_lchan(lchan);
3640 }
3641 lchan = trans->lchan;
3642
3643 /* if paging did not respond yet */
3644 if (!lchan) {
3645 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3646 "Received '%s' from MNCC in paging state\n",
3647 (trans->subscr)?(trans->subscr->extension):"-",
3648 get_mncc_name(msg_type));
Harald Weltebbc636a2009-06-11 14:23:20 +08003649 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3650 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte03740842009-06-10 23:11:52 +08003651 if (msg_type == MNCC_REL_REQ)
3652 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3653 else
3654 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3655 trans->callref = 0;
Harald Weltec2189a62009-07-23 18:56:43 +02003656 trans_free(trans);
Harald Welte03740842009-06-10 23:11:52 +08003657 return rc;
3658 }
3659
3660 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3661 "Received '%s' from MNCC in state %d (%s)\n",
3662 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3663 trans->transaction_id,
3664 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003665 get_mncc_name(msg_type), trans->cc.state,
3666 cc_state_names[trans->cc.state]);
Harald Welte03740842009-06-10 23:11:52 +08003667
3668 /* Find function for current state and message */
3669 for (i = 0; i < DOWNSLLEN; i++)
3670 if ((msg_type == downstatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003671 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003672 break;
3673 if (i == DOWNSLLEN) {
3674 DEBUGP(DCC, "Message unhandled at this state.\n");
3675 return 0;
3676 }
3677
3678 rc = downstatelist[i].rout(trans, arg);
3679
3680 return rc;
3681}
3682
3683
3684static struct datastate {
3685 u_int32_t states;
3686 int type;
3687 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3688} datastatelist[] = {
3689 /* mobile originating call establishment */
3690 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3691 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3692 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3693 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3694 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3695 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3696 /* mobile terminating call establishment */
3697 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3698 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3699 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3700 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3701 {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 */
3702 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3703 /* signalling during call */
3704 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3705 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3706 {SBIT(GSM_CSTATE_ACTIVE),
3707 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3708 {ALL_STATES,
3709 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3710 {ALL_STATES,
3711 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3712 {ALL_STATES,
3713 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3714 {SBIT(GSM_CSTATE_ACTIVE),
3715 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3716 {SBIT(GSM_CSTATE_ACTIVE),
3717 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3718 {SBIT(GSM_CSTATE_ACTIVE),
3719 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3720 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3721 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3722 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3723 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3724 {SBIT(GSM_CSTATE_ACTIVE),
3725 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3726 /* clearing */
3727 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3728 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3729 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3730 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3731 {ALL_STATES, /* 5.4.3.4 */
3732 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3733};
3734
3735#define DATASLLEN \
3736 (sizeof(datastatelist) / sizeof(struct datastate))
3737
Harald Welte59b04682009-06-10 05:40:52 +08003738static int gsm0408_rcv_cc(struct msgb *msg)
3739{
3740 struct gsm48_hdr *gh = msgb_l3(msg);
3741 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4861c822009-07-23 21:21:14 +02003742 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte03740842009-06-10 23:11:52 +08003743 struct gsm_lchan *lchan = msg->lchan;
Harald Weltec2189a62009-07-23 18:56:43 +02003744 struct gsm_trans *trans = NULL;
Harald Welte03740842009-06-10 23:11:52 +08003745 int i, rc = 0;
Harald Welte59b04682009-06-10 05:40:52 +08003746
Harald Welte03740842009-06-10 23:11:52 +08003747 if (msg_type & 0x80) {
3748 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3749 return -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08003750 }
Harald Welte03740842009-06-10 23:11:52 +08003751
3752 /* Find transaction */
Harald Welte0d824162009-07-23 21:58:40 +02003753 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltec2189a62009-07-23 18:56:43 +02003754
Harald Welte4861c822009-07-23 21:21:14 +02003755 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte03740842009-06-10 23:11:52 +08003756 "Received '%s' from MS in state %d (%s)\n",
3757 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3758 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltec2189a62009-07-23 18:56:43 +02003759 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3760 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte03740842009-06-10 23:11:52 +08003761
3762 /* Create transaction */
3763 if (!trans) {
Harald Welte4861c822009-07-23 21:21:14 +02003764 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte03740842009-06-10 23:11:52 +08003765 "creating new trans.\n", transaction_id);
3766 /* Create transaction */
Harald Weltec2189a62009-07-23 18:56:43 +02003767 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3768 transaction_id, new_callref++);
3769 if (!trans) {
Harald Welte03740842009-06-10 23:11:52 +08003770 DEBUGP(DCC, "No memory for trans.\n");
3771 rc = gsm48_tx_simple(msg->lchan,
Harald Welte4861c822009-07-23 21:21:14 +02003772 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte03740842009-06-10 23:11:52 +08003773 GSM48_MT_CC_RELEASE_COMPL);
3774 return -ENOMEM;
3775 }
Harald Welte03740842009-06-10 23:11:52 +08003776 /* Assign transaction */
Harald Welte03740842009-06-10 23:11:52 +08003777 trans->lchan = lchan;
3778 use_lchan(lchan);
Harald Welte03740842009-06-10 23:11:52 +08003779 }
3780
3781 /* find function for current state and message */
3782 for (i = 0; i < DATASLLEN; i++)
3783 if ((msg_type == datastatelist[i].type)
Harald Weltec2189a62009-07-23 18:56:43 +02003784 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte03740842009-06-10 23:11:52 +08003785 break;
3786 if (i == DATASLLEN) {
3787 DEBUGP(DCC, "Message unhandled at this state.\n");
3788 return 0;
3789 }
3790
3791 rc = datastatelist[i].rout(trans, msg);
Harald Welte59b04682009-06-10 05:40:52 +08003792
3793 return rc;
3794}
3795
3796/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
Harald Welte (local)64994ce2009-08-14 11:41:12 +02003797int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +08003798{
3799 struct gsm48_hdr *gh = msgb_l3(msg);
3800 u_int8_t pdisc = gh->proto_discr & 0x0f;
3801 int rc = 0;
3802
3803 switch (pdisc) {
3804 case GSM48_PDISC_CC:
3805 rc = gsm0408_rcv_cc(msg);
3806 break;
3807 case GSM48_PDISC_MM:
3808 rc = gsm0408_rcv_mm(msg);
3809 break;
3810 case GSM48_PDISC_RR:
3811 rc = gsm0408_rcv_rr(msg);
3812 break;
3813 case GSM48_PDISC_SMS:
Harald Welte (local)64994ce2009-08-14 11:41:12 +02003814 rc = gsm0411_rcv_sms(msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +08003815 break;
3816 case GSM48_PDISC_MM_GPRS:
3817 case GSM48_PDISC_SM_GPRS:
3818 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3819 pdisc);
3820 break;
3821 default:
3822 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3823 pdisc);
3824 break;
3825 }
3826
3827 return rc;
3828}
3829
Harald Welte59b04682009-06-10 05:40:52 +08003830/* Section 9.1.8 / Table 9.9 */
3831struct chreq {
3832 u_int8_t val;
3833 u_int8_t mask;
3834 enum chreq_type type;
3835};
3836
3837/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3838static const struct chreq chreq_type_neci1[] = {
3839 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3840 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3841 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3842 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3843 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3844 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3845 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3846 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3847 { 0x10, 0xf0, CHREQ_T_SDCCH },
3848 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3849 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3850 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3851};
3852
3853/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3854static const struct chreq chreq_type_neci0[] = {
3855 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3856 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3857 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3858 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3859 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3860 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3861 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3862 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3863};
3864
3865static const enum gsm_chan_t ctype_by_chreq[] = {
3866 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3867 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3868 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3869 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3870 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3871 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3872 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3873 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3874 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3875 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3876 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3877 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3878};
3879
3880static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3881 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3882 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3883 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3884 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3885 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3886 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3887 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3888 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3889 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3890 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3891 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3892 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3893};
3894
3895enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3896{
3897 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003898 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003899
Harald Welte1ab707e2009-08-10 02:14:46 +02003900 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3901 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003902 if ((ra & chr->mask) == chr->val)
3903 return ctype_by_chreq[chr->type];
3904 }
3905 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3906 return GSM_LCHAN_SDCCH;
3907}
3908
3909enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3910{
3911 int i;
Harald Welte1ab707e2009-08-10 02:14:46 +02003912 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte59b04682009-06-10 05:40:52 +08003913
Harald Welte1ab707e2009-08-10 02:14:46 +02003914 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3915 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte59b04682009-06-10 05:40:52 +08003916 if ((ra & chr->mask) == chr->val)
3917 return reason_by_chreq[chr->type];
3918 }
3919 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3920 return GSM_CHREQ_REASON_OTHER;
3921}
Harald Welte03740842009-06-10 23:11:52 +08003922
3923/* dequeue messages to layer 4 */
3924int bsc_upqueue(struct gsm_network *net)
3925{
3926 struct gsm_mncc *mncc;
3927 struct msgb *msg;
3928 int work = 0;
3929
3930 if (net)
3931 while ((msg = msgb_dequeue(&net->upqueue))) {
3932 mncc = (struct gsm_mncc *)msg->data;
3933 if (net->mncc_recv)
3934 net->mncc_recv(net, mncc->msg_type, mncc);
3935 work = 1; /* work done */
Harald Weltebaf4d3a2009-06-26 19:40:48 +02003936 talloc_free(msg);
Harald Welte03740842009-06-10 23:11:52 +08003937 }
3938
3939 return work;
3940}
Harald Weltec2189a62009-07-23 18:56:43 +02003941
Harald Welte3c062072009-07-28 18:25:29 +02003942/*
3943 * This will be ran by the linker when loading the DSO. We use it to
3944 * do system initialization, e.g. registration of signal handlers.
3945 */
3946static __attribute__((constructor)) void on_dso_load_0408(void)
3947{
Harald Welte3c062072009-07-28 18:25:29 +02003948 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3949 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3950}