blob: 117fb1224e838715f1f1443bf8af6f3fa047f0ff [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* 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
Harald Weltebf5e8df2009-02-03 12:59:45 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte498b0bb2009-01-09 21:27:43 +00005 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * 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>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
Harald Welte7584aea2009-02-11 11:44:12 +000035#include <openbsc/tlv.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000040#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000042#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000043#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000044#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000045#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000046#include <openbsc/trau_mux.h>
Harald Welte52b1f982008-12-23 20:25:15 +000047
Harald Welte8470bf22008-12-25 23:28:35 +000048#define GSM48_ALLOC_SIZE 1024
49#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000050
Harald Welte0c389302009-06-10 12:08:54 +080051#define GSM_MAX_FACILITY 128
52#define GSM_MAX_SSVERSION 128
53#define GSM_MAX_USERUSER 128
54
Harald Welte09e38af2009-02-16 22:52:23 +000055static const struct tlv_definition rsl_att_tlvdef = {
56 .def = {
57 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
58 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
59 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
60 [GSM48_IE_UTC] = { TLV_TYPE_TV },
61 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
62 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
63
64 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
65 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
66 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
67 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
68 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
69 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
70 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080071 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000072 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
73 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080074 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
75 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000076 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
77 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
78 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
79 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
80 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
81 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
82 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
83 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
84 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
85 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
86 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
87 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
88 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
89 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080090 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
91 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +000092 /* FIXME: more elements */
93 },
94};
Harald Weltecf5b3592009-05-01 18:28:42 +000095
96static const char *rr_cause_names[] = {
97 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
98 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
99 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
100 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
101 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
102 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
103 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
104 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
105 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
106 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
107 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
108 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
109 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
110 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
111 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
112 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
113 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
114};
115
Harald Welte4bfdfe72009-06-10 23:11:52 +0800116static const char *cc_state_names[] = {
117 "NULL",
118 "INITIATED",
119 "illegal state 2",
120 "MO_CALL_PROC",
121 "CALL_DELIVERED",
122 "illegal state 5",
123 "CALL_PRESENT",
124 "CALL_RECEIVED",
125 "CONNECT_REQUEST",
126 "MO_TERM_CALL_CONF",
127 "ACTIVE",
128 "DISCONNECT_REQ",
129 "DISCONNECT_IND",
130 "illegal state 13",
131 "illegal state 14",
132 "illegal state 15",
133 "illegal state 16",
134 "illegal state 17",
135 "illegal state 18",
136 "RELEASE_REQ",
137 "illegal state 20",
138 "illegal state 21",
139 "illegal state 22",
140 "illegal state 23",
141 "illegal state 24",
142 "illegal state 25",
143 "MO_ORIG_MODIFY",
144 "MO_TERM_MODIFY",
145 "CONNECT_IND",
146 "illegal state 29",
147 "illegal state 30",
148 "illegal state 31",
149};
150
151static const char *cc_msg_names[] = {
152 "unknown 0x00",
153 "ALERTING",
154 "CALL_PROC",
155 "PROGRESS",
156 "ESTAB",
157 "SETUP",
158 "ESTAB_CONF",
159 "CONNECT",
160 "CALL_CONF",
161 "START_CC",
162 "unknown 0x0a",
163 "RECALL",
164 "unknown 0x0c",
165 "unknown 0x0d",
166 "EMERG_SETUP",
167 "CONNECT_ACK",
168 "USER_INFO",
169 "unknown 0x11",
170 "unknown 0x12",
171 "MODIFY_REJECT",
172 "unknown 0x14",
173 "unknown 0x15",
174 "unknown 0x16",
175 "MODIFY",
176 "HOLD",
177 "HOLD_ACK",
178 "HOLD_REJ",
179 "unknown 0x1b",
180 "RETR",
181 "RETR_ACK",
182 "RETR_REJ",
183 "MODIFY_COMPL",
184 "unknown 0x20",
185 "unknown 0x21",
186 "unknown 0x22",
187 "unknown 0x23",
188 "unknown 0x24",
189 "DISCONNECT",
190 "unknown 0x26",
191 "unknown 0x27",
192 "unknown 0x28",
193 "unknown 0x29",
194 "RELEASE_COMPL",
195 "unknown 0x2b",
196 "unknown 0x2c",
197 "RELEASE",
198 "unknown 0x2e",
199 "unknown 0x2f",
200 "unknown 0x30",
201 "STOP_DTMF",
202 "STOP_DTMF_ACK",
203 "unknown 0x33",
204 "STATUS_ENQ",
205 "START_DTMF",
206 "START_DTMF_ACK",
207 "START_DTMF_REJ",
208 "unknown 0x38",
209 "CONG_CTRL",
210 "FACILITY",
211 "unknown 0x3b",
212 "STATUS",
213 "unknown 0x3c",
214 "NOTIFY",
215 "unknown 0x3f",
216};
217
Harald Weltecf5b3592009-05-01 18:28:42 +0000218static char strbuf[64];
219
220static const char *rr_cause_name(u_int8_t cause)
221{
222 if (cause < ARRAY_SIZE(rr_cause_names) &&
223 rr_cause_names[cause])
224 return rr_cause_names[cause];
225
226 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
227 return strbuf;
228}
229
Harald Weltef7c43522009-06-09 20:24:21 +0000230static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
231 int len)
232{
233 memset(rep, 0, sizeof(*rep));
234
235 if (data[0] & 0x80)
236 rep->flags |= MEAS_REP_F_BA1;
237 if (data[0] & 0x40)
238 rep->flags |= MEAS_REP_F_DTX;
239 if (data[1] & 0x40)
240 rep->flags |= MEAS_REP_F_VALID;
241
242 rep->rxlev_full = data[0] & 0x3f;
243 rep->rxlev_sub = data[1] & 0x3f;
244 rep->rxqual_full = (data[3] >> 4) & 0x7;
245 rep->rxqual_sub = (data[3] >> 1) & 0x7;
246 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
247 if (rep->num_cell < 1)
248 return;
249
250 /* an encoding nightmare in perfection */
251
252 rep->cell[0].rxlev = data[4] & 0x3f;
253 rep->cell[0].bcch_freq = data[5] >> 2;
254 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
255 if (rep->num_cell < 2)
256 return;
257
258 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
259 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
260 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
261 if (rep->num_cell < 3)
262 return;
263
264 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
265 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
266 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
267 if (rep->num_cell < 4)
268 return;
269
270 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
271 rep->cell[3].bcch_freq = data[11] & 0x1f;
272 rep->cell[3].bsic = data[12] >> 2;
273 if (rep->num_cell < 5)
274 return;
275
276 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
277 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
278 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
279 if (rep->num_cell < 6)
280 return;
281
282 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
283 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
284 rep->cell[5].bsic = data[16] & 0x3f;
285}
286
Holger Freytherd51524f2009-06-09 08:27:07 +0000287int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000288static int gsm48_tx_simple(struct gsm_lchan *lchan,
289 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000290static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800291void free_trans(struct gsm_trans *trans);
Harald Welte65e74cc2008-12-29 01:55:35 +0000292
Harald Welte52b1f982008-12-23 20:25:15 +0000293struct gsm_lai {
294 u_int16_t mcc;
295 u_int16_t mnc;
296 u_int16_t lac;
297};
298
Holger Freyther89824fc2008-12-30 16:18:18 +0000299static int authorize_everonye = 0;
300void gsm0408_allow_everyone(int everyone)
301{
302 printf("Allowing everyone?\n");
303 authorize_everonye = everyone;
304}
305
Holger Freythere97f7fb2008-12-31 18:52:11 +0000306static int reject_cause = 0;
307void gsm0408_set_reject_cause(int cause)
308{
309 reject_cause = cause;
310}
311
Harald Welte4bfdfe72009-06-10 23:11:52 +0800312static u_int32_t new_callref = 0x80000001;
313
Holger Freyther73487a22008-12-31 18:53:57 +0000314static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
315 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000316{
317 if (!subscriber)
318 return 0;
319
Holger Freyther73487a22008-12-31 18:53:57 +0000320 /*
321 * Do not send accept yet as more information should arrive. Some
322 * phones will not send us the information and we will have to check
323 * what we want to do with that.
324 */
325 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
326 return 0;
327
Holger Freyther89824fc2008-12-30 16:18:18 +0000328 if (authorize_everonye)
329 return 1;
330
331 return subscriber->authorized;
332}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000333
Holger Freyther73487a22008-12-31 18:53:57 +0000334static void release_loc_updating_req(struct gsm_lchan *lchan)
335{
Harald Welte179f0642008-12-31 23:59:18 +0000336 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000337 return;
338
Harald Welteff117a82009-05-23 05:22:08 +0000339 bsc_del_timer(&lchan->loc_operation->updating_timer);
Holger Freyther73487a22008-12-31 18:53:57 +0000340 free(lchan->loc_operation);
341 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000342 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000343}
344
345static void allocate_loc_updating_req(struct gsm_lchan *lchan)
346{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000347 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000348 release_loc_updating_req(lchan);
349
350 lchan->loc_operation = (struct gsm_loc_updating_operation *)
351 malloc(sizeof(*lchan->loc_operation));
352 memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
353}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000354
Holger Freytherd51524f2009-06-09 08:27:07 +0000355static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
356{
357 u_int32_t tmsi;
358
359 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
360 db_subscriber_alloc_tmsi(lchan->subscr);
361 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
362 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
363 release_loc_updating_req(lchan);
364 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
365 }
366
367 return 0;
368}
369
Holger Freyther7c19f742009-06-06 13:54:35 +0000370static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
371 void *handler_data, void *signal_data)
372{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800373 struct gsm_trans *trans, *temp;
374
Holger Freyther7c19f742009-06-06 13:54:35 +0000375 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
376 return 0;
377
378 /*
379 * Cancel any outstanding location updating request
380 * operation taking place on the lchan.
381 */
382 struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
383 release_loc_updating_req(lchan);
384
Harald Welte4bfdfe72009-06-10 23:11:52 +0800385 /* Free all transactions that are associated with the released lchan */
386 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
387 if (trans->lchan == lchan)
388 free_trans(trans);
389 }
390
Holger Freyther7c19f742009-06-06 13:54:35 +0000391 return 0;
392}
393
394/*
395 * This will be ran by the linker when loading the DSO. We use it to
396 * do system initialization, e.g. registration of signal handlers.
397 */
398static __attribute__((constructor)) void on_dso_load_0408(void)
399{
400 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
401}
402
Harald Welte52b1f982008-12-23 20:25:15 +0000403static void to_bcd(u_int8_t *bcd, u_int16_t val)
404{
Harald Welte4b634542008-12-27 01:55:51 +0000405 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000406 val = val / 10;
407 bcd[1] = val % 10;
408 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000409 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000410 val = val / 10;
411}
412
Holger Freyther17746612008-12-28 16:32:44 +0000413void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000414 u_int16_t mnc, u_int16_t lac)
415{
416 u_int8_t bcd[3];
417
418 to_bcd(bcd, mcc);
419 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
420 lai48->digits[1] = bcd[2];
421
422 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000423 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
424#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000425 lai48->digits[1] |= bcd[2] << 4;
426 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000427#else
428 lai48->digits[1] |= 0xf << 4;
429 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
430#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000431
Harald Welte4b634542008-12-27 01:55:51 +0000432 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000433}
434
Harald Welte255539c2008-12-28 02:26:27 +0000435#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000436#define MID_TMSI_LEN (TMSI_LEN + 2)
437
Harald Welte255539c2008-12-28 02:26:27 +0000438int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000439{
Harald Welte65e74cc2008-12-29 01:55:35 +0000440 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000441
Harald Welte4b634542008-12-27 01:55:51 +0000442 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000443 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000444 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000445 *tptr = htonl(tmsi);
446
447 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000448}
449
Harald Welte09e38af2009-02-16 22:52:23 +0000450static const char bcd_num_digits[] = {
451 '0', '1', '2', '3', '4', '5', '6', '7',
452 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
453};
454
Harald Welte0c389302009-06-10 12:08:54 +0800455/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
456int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
457 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000458{
459 u_int8_t in_len = bcd_lv[0];
460 int i;
461
Harald Welte0c389302009-06-10 12:08:54 +0800462 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000463 /* lower nibble */
464 output_len--;
465 if (output_len <= 1)
466 break;
467 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
468
469 /* higher nibble */
470 output_len--;
471 if (output_len <= 1)
472 break;
473 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
474 }
475 if (output_len >= 1)
476 *output++ = '\0';
477
Harald Welte0c389302009-06-10 12:08:54 +0800478 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000479}
480
481/* convert a single ASCII character to call-control BCD */
482static int asc_to_bcd(const char asc)
483{
484 int i;
485
486 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
487 if (bcd_num_digits[i] == asc)
488 return i;
489 }
490 return -EINVAL;
491}
492
Harald Welte0c389302009-06-10 12:08:54 +0800493/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000494int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800495 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000496{
497 int in_len = strlen(input);
498 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800499 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000500
501 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800502 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000503 if (in_len % 2)
504 bcd_lv[0]++;
505
Harald Welte0c389302009-06-10 12:08:54 +0800506 if (bcd_lv[0] > max_len)
507 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000508
509 for (i = 0; i < in_len; i++) {
510 int rc = asc_to_bcd(input[i]);
511 if (rc < 0)
512 return rc;
513 if (i % 2 == 0)
514 *bcd_cur = rc;
515 else
516 *bcd_cur++ |= (rc << 4);
517 }
518 /* append padding nibble in case of odd length */
519 if (i % 2)
520 *bcd_cur++ |= 0xf0;
521
522 /* return how many bytes we used */
523 return (bcd_cur - bcd_lv);
524}
525
Harald Welte0c389302009-06-10 12:08:54 +0800526/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800527static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800528 const u_int8_t *lv)
529{
530 u_int8_t in_len = lv[0];
531 int i, s;
532
533 if (in_len < 1)
534 return -EINVAL;
535
Harald Welte4bfdfe72009-06-10 23:11:52 +0800536 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800537
538 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800539 bcap->transfer = lv[1] & 0x07;
540 bcap->mode = (lv[1] & 0x08) >> 3;
541 bcap->coding = (lv[1] & 0x10) >> 4;
542 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800543
544 i = 1;
545 s = 0;
546 while(!(lv[i] & 0x80)) {
547 i++; /* octet 3a etc */
548 if (in_len < i)
549 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800550 bcap->speech_ver[s++] = lv[i] & 0x0f;
551 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800552 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800553 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800554 if (s == 7) /* maximum speech versions + end of list */
555 return 0;
556 }
557
558 return 0;
559}
560
561/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800562static int encode_bearer_cap(struct msgb *msg, int lv_only,
563 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800564{
565 u_int8_t lv[32 + 1];
566 int i, s;
567
Harald Welte4bfdfe72009-06-10 23:11:52 +0800568 lv[1] = bcap->transfer;
569 lv[1] |= bcap->mode << 3;
570 lv[1] |= bcap->coding << 4;
571 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800572
573 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800574 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800575 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800576 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800577 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800578 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800579 }
580 lv[i] |= 0x80; /* last IE of octet 3 etc */
581
582 lv[0] = i;
583 if (lv_only)
584 msgb_lv_put(msg, lv[0], lv+1);
585 else
586 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
587
588 return 0;
589}
590
591/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800592static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800593{
594 u_int8_t in_len = lv[0];
595
596 if (in_len < 1)
597 return -EINVAL;
598
599 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800600 ccap->dtmf = lv[1] & 0x01;
601 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800602
603 return 0;
604}
605
606/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800607static int decode_called(struct gsm_mncc_number *called,
608 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800609{
610 u_int8_t in_len = lv[0];
611
612 if (in_len < 1)
613 return -EINVAL;
614
615 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800616 called->plan = lv[1] & 0x0f;
617 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800618
619 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800620 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800621
622 return 0;
623}
624
625/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800626static int encode_called(struct msgb *msg,
627 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800628{
629 u_int8_t lv[18];
630 int ret;
631
632 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800633 lv[1] = called->plan;
634 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800635
636 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800637 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800638 if (ret < 0)
639 return ret;
640
641 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
642
643 return 0;
644}
645
646/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800647static int encode_callerid(struct msgb *msg, int ie,
648 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800649{
650 u_int8_t lv[13];
651 int h_len = 1;
652 int ret;
653
654 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800655 lv[1] = callerid->plan;
656 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800657
Harald Welte4bfdfe72009-06-10 23:11:52 +0800658 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800659 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800660 lv[2] = callerid->screen;
661 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800662 lv[2] |= 0x80;
663 h_len++;
664 } else
665 lv[1] |= 0x80;
666
667 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800668 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800669 if (ret < 0)
670 return ret;
671
672 msgb_tlv_put(msg, ie, lv[0], lv+1);
673
674 return 0;
675}
676
677/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800678static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800679 const u_int8_t *lv)
680{
681 u_int8_t in_len = lv[0];
682 int i;
683
684 if (in_len < 2)
685 return -EINVAL;
686
Harald Welte4bfdfe72009-06-10 23:11:52 +0800687 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800688
689 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800690 cause->location = lv[1] & 0x0f;
691 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800692
693 i = 1;
694 if (!(lv[i] & 0x80)) {
695 i++; /* octet 3a */
696 if (in_len < i+1)
697 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800698 cause->rec = 1;
699 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800700
701 }
702 i++;
703
704 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800705 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800706 i++;
707
708 if (in_len < i) /* no diag */
709 return 0;
710
711 if (in_len - (i-1) > 32) /* maximum 32 octets */
712 return 0;
713
714 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800715 memcpy(cause->diag, lv + i, in_len - (i-1));
716 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800717
718 return 0;
719}
720
721/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800722static int encode_cause(struct msgb *msg, int lv_only,
723 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800724{
725 u_int8_t lv[32+4];
726 int i;
727
Harald Welte4bfdfe72009-06-10 23:11:52 +0800728 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800729 return -EINVAL;
730
731 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800732 lv[1] = cause->location;
733 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800734
735 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800736 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800737 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800738 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800739 }
740 lv[i] |= 0x80; /* end of octet 3 */
741
742 /* octet 4 */
743 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800744 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800745
746 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 if (cause->diag_len) {
748 memcpy(lv + i, cause->diag, cause->diag_len);
749 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800750 }
751
752 lv[0] = i;
753 if (lv_only)
754 msgb_lv_put(msg, lv[0], lv+1);
755 else
756 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
757
758 return 0;
759}
760
761/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800762static int encode_calling(struct msgb *msg,
763 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800764{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800765 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800766}
767
768/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800769static int encode_connected(struct msgb *msg,
770 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800771{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800772 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800773}
774
775/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800776static int encode_redirecting(struct msgb *msg,
777 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800778{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800779 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800780}
781
782/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800783static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800784 const u_int8_t *lv)
785{
786 u_int8_t in_len = lv[0];
787
788 if (in_len < 1)
789 return -EINVAL;
790
Harald Welte4bfdfe72009-06-10 23:11:52 +0800791 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800792 return -EINVAL;
793
Harald Welte4bfdfe72009-06-10 23:11:52 +0800794 memcpy(facility->info, lv+1, in_len);
795 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800796
797 return 0;
798}
799
800/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800801static int encode_facility(struct msgb *msg, int lv_only,
802 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800803{
804 u_int8_t lv[GSM_MAX_FACILITY + 1];
805
Harald Welte4bfdfe72009-06-10 23:11:52 +0800806 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800807 return -EINVAL;
808
Harald Welte4bfdfe72009-06-10 23:11:52 +0800809 memcpy(lv+1, facility->info, facility->len);
810 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800811 if (lv_only)
812 msgb_lv_put(msg, lv[0], lv+1);
813 else
814 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
815
816 return 0;
817}
818
819/* decode 'notify' */
820static int decode_notify(int *notify, const u_int8_t *v)
821{
822 *notify = v[0] & 0x7f;
823
824 return 0;
825}
826
827/* encode 'notify' */
828static int encode_notify(struct msgb *msg, int notify)
829{
830 msgb_v_put(msg, notify | 0x80);
831
832 return 0;
833}
834
835/* encode 'signal' */
836static int encode_signal(struct msgb *msg, int signal)
837{
838 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
839
840 return 0;
841}
842
843/* decode 'keypad' */
844static int decode_keypad(int *keypad, const u_int8_t *lv)
845{
846 u_int8_t in_len = lv[0];
847
848 if (in_len < 1)
849 return -EINVAL;
850
851 *keypad = lv[1] & 0x7f;
852
853 return 0;
854}
855
856/* encode 'keypad' */
857static int encode_keypad(struct msgb *msg, int keypad)
858{
859 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
860
861 return 0;
862}
863
864/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800865static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800866 const u_int8_t *lv)
867{
868 u_int8_t in_len = lv[0];
869
870 if (in_len < 2)
871 return -EINVAL;
872
Harald Welte4bfdfe72009-06-10 23:11:52 +0800873 progress->coding = (lv[1] & 0x60) >> 5;
874 progress->location = lv[1] & 0x0f;
875 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800876
877 return 0;
878}
879
880/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800881static int encode_progress(struct msgb *msg, int lv_only,
882 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800883{
884 u_int8_t lv[3];
885
886 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800887 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
888 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800889 if (lv_only)
890 msgb_lv_put(msg, lv[0], lv+1);
891 else
892 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
893
894 return 0;
895}
896
897/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800898static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800899 const u_int8_t *lv)
900{
901 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800902 char *info = uu->info;
903 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800904 int i;
905
906 if (in_len < 1)
907 return -EINVAL;
908
Harald Welte4bfdfe72009-06-10 23:11:52 +0800909 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800910
911 for (i = 2; i <= in_len; i++) {
912 info_len--;
913 if (info_len <= 1)
914 break;
915 *info++ = lv[i];
916 }
917 if (info_len >= 1)
918 *info++ = '\0';
919
920 return 0;
921}
922
923/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800924static int encode_useruser(struct msgb *msg, int lv_only,
925 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800926{
927 u_int8_t lv[GSM_MAX_USERUSER + 2];
928
Harald Welte4bfdfe72009-06-10 23:11:52 +0800929 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800930 return -EINVAL;
931
Harald Welte4bfdfe72009-06-10 23:11:52 +0800932 lv[0] = 1 + strlen(uu->info);
933 lv[1] = uu->proto;
934 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800935 if (lv_only)
936 msgb_lv_put(msg, lv[0], lv+1);
937 else
938 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
939
940 return 0;
941}
942
943/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800944static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800945 const u_int8_t *lv)
946{
947 u_int8_t in_len = lv[0];
948
Harald Welte4bfdfe72009-06-10 23:11:52 +0800949 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800950 return -EINVAL;
951
Harald Welte4bfdfe72009-06-10 23:11:52 +0800952 memcpy(ssv->info, lv + 1, in_len);
953 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800954
955 return 0;
956}
957
958/* encode 'more data' */
959static int encode_more(struct msgb *msg)
960{
961 u_int8_t *ie;
962
963 ie = msgb_put(msg, 1);
964 ie[0] = GSM48_IE_MORE_DATA;
965
966 return 0;
967}
968
Holger Freyther819dd202009-01-04 03:52:50 +0000969struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000970{
971 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM);
972}
973
Holger Freyther3e2c3232009-01-04 03:55:31 +0000974int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000975{
Harald Welte65e74cc2008-12-29 01:55:35 +0000976 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800977 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000978 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000979
Harald Welte4bfdfe72009-06-10 23:11:52 +0800980 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
981 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
982 "Sending '%s' to MS.\n", msg->trx->bts->nr,
983 msg->trx->nr, msg->lchan->ts->nr,
984 gh->proto_discr & 0xf0,
985 cc_msg_names[gh->msg_type & 0x3f]);
986 else
987 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
988 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
989 msg->trx->nr, msg->lchan->ts->nr,
990 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +0000991 }
992
Harald Welte4b634542008-12-27 01:55:51 +0000993 msg->l3h = msg->data;
994
Harald Welte8470bf22008-12-25 23:28:35 +0000995 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +0000996}
997
Holger Freyther429e7762008-12-30 13:28:30 +0000998/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +0000999int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001000{
Harald Welte8470bf22008-12-25 23:28:35 +00001001 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001002 struct gsm48_hdr *gh;
1003
Harald Welte8470bf22008-12-25 23:28:35 +00001004 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001005
1006 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1007 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001008 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001009 gh->data[0] = cause;
1010
Harald Weltedb253af2008-12-30 17:56:55 +00001011 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1012
Harald Welte65e74cc2008-12-29 01:55:35 +00001013 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001014}
1015
1016/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001017int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001018{
Harald Welte8470bf22008-12-25 23:28:35 +00001019 struct gsm_bts *bts = lchan->ts->trx->bts;
1020 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001021 struct gsm48_hdr *gh;
1022 struct gsm48_loc_area_id *lai;
1023 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001024 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001025
Harald Welte8470bf22008-12-25 23:28:35 +00001026 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001027
1028 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1029 gh->proto_discr = GSM48_PDISC_MM;
1030 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1031
1032 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001033 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001034 bts->network->network_code, bts->location_area_code);
1035
1036 mid = msgb_put(msg, MID_TMSI_LEN);
1037 generate_mid_from_tmsi(mid, tmsi);
1038
1039 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1040
Harald Weltedb253af2008-12-30 17:56:55 +00001041 ret = gsm48_sendmsg(msg);
1042
Harald Weltedb253af2008-12-30 17:56:55 +00001043 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001044
Holger Freyther07cc8d82008-12-29 06:23:46 +00001045 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001046}
1047
Harald Weltefc977a82008-12-27 10:19:37 +00001048static char bcd2char(u_int8_t bcd)
1049{
1050 if (bcd < 0xa)
1051 return '0' + bcd;
1052 else
1053 return 'A' + (bcd - 0xa);
1054}
1055
Harald Weltebf5e8df2009-02-03 12:59:45 +00001056/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001057static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1058{
1059 int i;
1060 u_int8_t mi_type;
1061 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001062 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001063
1064 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1065
1066 switch (mi_type) {
1067 case GSM_MI_TYPE_NONE:
1068 break;
1069 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001070 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1071 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1072 memcpy(&tmsi, &mi[1], 4);
1073 tmsi = ntohl(tmsi);
1074 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001075 }
1076 break;
1077 case GSM_MI_TYPE_IMSI:
1078 case GSM_MI_TYPE_IMEI:
1079 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001080 *str_cur++ = bcd2char(mi[0] >> 4);
1081
1082 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001083 if (str_cur + 2 >= string + str_len)
1084 return str_cur - string;
1085 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001086 /* skip last nibble in last input byte when GSM_EVEN */
1087 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1088 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001089 }
1090 break;
1091 default:
1092 break;
1093 }
Harald Weltefc977a82008-12-27 10:19:37 +00001094 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001095
Harald Weltefc977a82008-12-27 10:19:37 +00001096 return str_cur - string;
1097}
1098
Harald Weltebf5e8df2009-02-03 12:59:45 +00001099/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001100static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1101{
1102 struct msgb *msg = gsm48_msgb_alloc();
1103 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001104
Harald Welte231ad4f2008-12-27 11:15:38 +00001105 msg->lchan = lchan;
1106
1107 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1108 gh->proto_discr = GSM48_PDISC_MM;
1109 gh->msg_type = GSM48_MT_MM_ID_REQ;
1110 gh->data[0] = id_type;
1111
Harald Welte65e74cc2008-12-29 01:55:35 +00001112 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001113}
1114
1115#define MI_SIZE 32
1116
Harald Weltebf5e8df2009-02-03 12:59:45 +00001117/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001118static int mm_rx_id_resp(struct msgb *msg)
1119{
1120 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001121 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001122 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1123 char mi_string[MI_SIZE];
1124
1125 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001126 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001127 mi_type, mi_string);
1128
Harald Welte75a983f2008-12-27 21:34:06 +00001129 switch (mi_type) {
1130 case GSM_MI_TYPE_IMSI:
1131 if (!lchan->subscr)
1132 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001133 if (lchan->loc_operation)
1134 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001135 break;
1136 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001137 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001138 /* update subscribe <-> IMEI mapping */
1139 if (lchan->subscr)
1140 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001141 if (lchan->loc_operation)
1142 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001143 break;
1144 }
Holger Freyther73487a22008-12-31 18:53:57 +00001145
1146 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001147 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001148}
1149
Harald Welte255539c2008-12-28 02:26:27 +00001150
1151static void loc_upd_rej_cb(void *data)
1152{
1153 struct gsm_lchan *lchan = data;
1154
Holger Freyther73487a22008-12-31 18:53:57 +00001155 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001156 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001157 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001158}
1159
Holger Freytherb7193e42008-12-29 17:44:08 +00001160static void schedule_reject(struct gsm_lchan *lchan)
1161{
Holger Freyther73487a22008-12-31 18:53:57 +00001162 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1163 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001164 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001165}
1166
Harald Welte2a139372009-02-22 21:14:55 +00001167static const char *lupd_name(u_int8_t type)
1168{
1169 switch (type) {
1170 case GSM48_LUPD_NORMAL:
1171 return "NORMAL";
1172 case GSM48_LUPD_PERIODIC:
1173 return "PEROIDOC";
1174 case GSM48_LUPD_IMSI_ATT:
1175 return "IMSI ATTACH";
1176 default:
1177 return "UNKNOWN";
1178 }
1179}
1180
Harald Welte231ad4f2008-12-27 11:15:38 +00001181#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001182/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001183static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001184{
Harald Welte8470bf22008-12-25 23:28:35 +00001185 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001186 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001187 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001188 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001189 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001190 char mi_string[MI_SIZE];
1191 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001192
Harald Welte8470bf22008-12-25 23:28:35 +00001193 lu = (struct gsm48_loc_upd_req *) gh->data;
1194
1195 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001196
Harald Weltefc977a82008-12-27 10:19:37 +00001197 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1198
Holger Freyther79f4ae62009-06-02 03:25:04 +00001199 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001200 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001201
Holger Freythereaf04692009-06-06 13:54:44 +00001202 /*
1203 * Pseudo Spoof detection: Just drop a second/concurrent
1204 * location updating request.
1205 */
1206 if (lchan->loc_operation) {
1207 DEBUGP(DMM, "LUPDREQ: ignoring request due an existing one: %p.\n",
1208 lchan->loc_operation);
1209 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1210 return 0;
1211 }
1212
Holger Freyther73487a22008-12-31 18:53:57 +00001213 allocate_loc_updating_req(lchan);
1214
Harald Welte52b1f982008-12-23 20:25:15 +00001215 switch (mi_type) {
1216 case GSM_MI_TYPE_IMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001217 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001218 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001219 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001220 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001221
Harald Welte52b1f982008-12-23 20:25:15 +00001222 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001223 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001224 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001225 case GSM_MI_TYPE_TMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001226 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001227 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001228 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001229 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001230
Harald Welte52b1f982008-12-23 20:25:15 +00001231 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001232 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001233 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001234 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001235 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001236 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001237 }
1238 break;
1239 case GSM_MI_TYPE_IMEI:
1240 case GSM_MI_TYPE_IMEISV:
1241 /* no sim card... FIXME: what to do ? */
Harald Welte2a139372009-02-22 21:14:55 +00001242 DEBUGP(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001243 break;
1244 default:
Harald Welte2a139372009-02-22 21:14:55 +00001245 DEBUGP(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001246 break;
1247 }
1248
Harald Welte4bfdfe72009-06-10 23:11:52 +08001249 if (!subscr) {
1250 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1251 /* FIXME: request id? close channel? */
1252 return -EINVAL;
1253 }
1254
Harald Welte255539c2008-12-28 02:26:27 +00001255 lchan->subscr = subscr;
1256
Holger Freyther73487a22008-12-31 18:53:57 +00001257 /*
1258 * Schedule the reject timer and check if we can let the
1259 * subscriber into our network immediately or if we need to wait
1260 * for identity responses.
1261 */
1262 schedule_reject(lchan);
Holger Freytherd51524f2009-06-09 08:27:07 +00001263 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001264}
1265
Harald Welte7584aea2009-02-11 11:44:12 +00001266/* 9.1.5 Channel mode modify */
1267int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1268{
1269 struct msgb *msg = gsm48_msgb_alloc();
1270 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1271 struct gsm48_chan_mode_modify *cmm =
1272 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001273 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001274
Harald Welte4a543e82009-02-28 13:17:55 +00001275 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001276
Harald Welte45b407a2009-05-23 15:51:12 +00001277 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001278 msg->lchan = lchan;
1279 gh->proto_discr = GSM48_PDISC_RR;
1280 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1281
1282 /* fill the channel information element, this code
1283 * should probably be shared with rsl_rx_chan_rqd() */
1284 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001285 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001286 cmm->chan_desc.h0.h = 0;
1287 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1288 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1289 cmm->mode = mode;
1290
1291 return gsm48_sendmsg(msg);
1292}
1293
Harald Welte4bfdfe72009-06-10 23:11:52 +08001294#if 0
1295static u_int8_t to_bcd8(u_int8_t val)
1296{
1297 return ((val / 10) << 4) | (val % 10);
1298}
1299#endif
1300
Harald Weltedb253af2008-12-30 17:56:55 +00001301/* Section 9.2.15a */
1302int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1303{
1304 struct msgb *msg = gsm48_msgb_alloc();
1305 struct gsm48_hdr *gh;
1306 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001307 u_int8_t *ptr8;
1308 u_int16_t *ptr16;
1309 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001310 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001311#if 0
1312 time_t cur_t;
1313 struct tm* cur_time;
1314 int tz15min;
1315#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001316
1317 msg->lchan = lchan;
1318
1319 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1320 gh->proto_discr = GSM48_PDISC_MM;
1321 gh->msg_type = GSM48_MT_MM_INFO;
1322
1323 if (net->name_long) {
1324 name_len = strlen(net->name_long);
1325 /* 10.5.3.5a */
1326 ptr8 = msgb_put(msg, 3);
1327 ptr8[0] = GSM48_IE_NAME_LONG;
1328 ptr8[1] = name_len*2 +1;
1329 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1330
1331 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1332 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001333 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001334
1335 /* FIXME: Use Cell Broadcast, not UCS-2, since
1336 * UCS-2 is only supported by later revisions of the spec */
1337 }
1338
1339 if (net->name_short) {
1340 name_len = strlen(net->name_short);
1341 /* 10.5.3.5a */
1342 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1343 ptr8[0] = GSM48_IE_NAME_LONG;
1344 ptr8[1] = name_len*2 + 1;
1345 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1346
Harald Weltee872cb12009-01-01 00:33:37 +00001347 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001348 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001349 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001350 }
1351
1352#if 0
1353 /* Section 10.5.3.9 */
1354 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001355 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001356 ptr8 = msgb_put(msg, 8);
1357 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1358 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1359 ptr8[2] = to_bcd8(cur_time->tm_mon);
1360 ptr8[3] = to_bcd8(cur_time->tm_mday);
1361 ptr8[4] = to_bcd8(cur_time->tm_hour);
1362 ptr8[5] = to_bcd8(cur_time->tm_min);
1363 ptr8[6] = to_bcd8(cur_time->tm_sec);
1364 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1365 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001366 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001367 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001368 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001369#endif
1370
1371 return gsm48_sendmsg(msg);
1372}
1373
Harald Welte4b634542008-12-27 01:55:51 +00001374static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1375{
Harald Welte4b634542008-12-27 01:55:51 +00001376 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001377 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001378}
Harald Welteba4cf162009-01-10 01:49:35 +00001379
1380/* 9.2.6 CM service reject */
1381static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1382 enum gsm48_reject_value value)
1383{
1384 struct msgb *msg = gsm48_msgb_alloc();
1385 struct gsm48_hdr *gh;
1386
1387 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1388
1389 msg->lchan = lchan;
1390 use_lchan(lchan);
1391
1392 gh->proto_discr = GSM48_PDISC_MM;
1393 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1394 gh->data[0] = value;
1395 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1396
1397 return gsm48_sendmsg(msg);
1398}
1399
Harald Welte4ed0e922009-01-10 03:17:30 +00001400
1401/*
1402 * Handle CM Service Requests
1403 * a) Verify that the packet is long enough to contain the information
1404 * we require otherwsie reject with INCORRECT_MESSAGE
1405 * b) Try to parse the TMSI. If we do not have one reject
1406 * c) Check that we know the subscriber with the TMSI otherwise reject
1407 * with a HLR cause
1408 * d) Set the subscriber on the gsm_lchan and accept
1409 */
Harald Welte4b634542008-12-27 01:55:51 +00001410static int gsm48_rx_mm_serv_req(struct msgb *msg)
1411{
Harald Welteba4cf162009-01-10 01:49:35 +00001412 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001413 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001414
Harald Welteba4cf162009-01-10 01:49:35 +00001415 struct gsm_subscriber *subscr;
1416 struct gsm48_hdr *gh = msgb_l3(msg);
1417 struct gsm48_service_request *req =
1418 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001419 /* unfortunately in Phase1 the classmar2 length is variable */
1420 u_int8_t classmark2_len = gh->data[1];
1421 u_int8_t *classmark2 = gh->data+2;
1422 u_int8_t mi_len = *(classmark2 + classmark2_len);
1423 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001424
Harald Weltec9e02182009-05-01 19:07:53 +00001425 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001426 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001427 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001428 return gsm48_tx_mm_serv_rej(msg->lchan,
1429 GSM48_REJECT_INCORRECT_MESSAGE);
1430 }
1431
1432 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001433 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001434 return gsm48_tx_mm_serv_rej(msg->lchan,
1435 GSM48_REJECT_INCORRECT_MESSAGE);
1436 }
1437
Harald Weltec9e02182009-05-01 19:07:53 +00001438 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001439 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001440 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001441 return gsm48_tx_mm_serv_rej(msg->lchan,
1442 GSM48_REJECT_INCORRECT_MESSAGE);
1443 }
1444
Harald Weltec9e02182009-05-01 19:07:53 +00001445 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001446 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001447 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001448
Holger Freythereb443982009-06-04 13:58:42 +00001449 subscr = subscr_get_by_tmsi(mi_string);
1450
Harald Welte2a139372009-02-22 21:14:55 +00001451 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001452 if (!subscr)
1453 return gsm48_tx_mm_serv_rej(msg->lchan,
1454 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1455
1456 if (!msg->lchan->subscr)
1457 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001458 else if (msg->lchan->subscr != subscr) {
1459 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1460 subscr_put(subscr);
1461 }
1462
Harald Weltef7c43522009-06-09 20:24:21 +00001463 subscr->classmark2_len = classmark2_len;
1464 memcpy(subscr->classmark2, classmark2, classmark2_len);
1465
Harald Welte4b634542008-12-27 01:55:51 +00001466 return gsm48_tx_mm_serv_ack(msg->lchan);
1467}
1468
Harald Welte2a139372009-02-22 21:14:55 +00001469static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1470{
1471 struct gsm48_hdr *gh = msgb_l3(msg);
1472 struct gsm48_imsi_detach_ind *idi =
1473 (struct gsm48_imsi_detach_ind *) gh->data;
1474 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1475 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001476 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001477
1478 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1479 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1480 mi_type, mi_string);
1481
1482 switch (mi_type) {
1483 case GSM_MI_TYPE_TMSI:
1484 subscr = subscr_get_by_tmsi(mi_string);
1485 break;
1486 case GSM_MI_TYPE_IMSI:
1487 subscr = subscr_get_by_imsi(mi_string);
1488 break;
1489 case GSM_MI_TYPE_IMEI:
1490 case GSM_MI_TYPE_IMEISV:
1491 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001492 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001493 break;
1494 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001495 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001496 break;
1497 }
1498
Holger Freyther4a49e772009-04-12 05:37:29 +00001499 if (subscr) {
1500 subscr_update(subscr, msg->trx->bts,
1501 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001502 DEBUGP(DMM, "Subscriber: %s\n",
1503 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001504 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001505 } else
Harald Welte2a139372009-02-22 21:14:55 +00001506 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1507
Harald Welte2a139372009-02-22 21:14:55 +00001508 return 0;
1509}
1510
Harald Welted2a7f5a2009-06-05 20:08:20 +00001511static int gsm48_rx_mm_status(struct msgb *msg)
1512{
1513 struct gsm48_hdr *gh = msgb_l3(msg);
1514
1515 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1516
1517 return 0;
1518}
1519
Harald Weltebf5e8df2009-02-03 12:59:45 +00001520/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001521static int gsm0408_rcv_mm(struct msgb *msg)
1522{
1523 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001524 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001525
1526 switch (gh->msg_type & 0xbf) {
1527 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +00001528 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001529 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001530 break;
1531 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001532 rc = mm_rx_id_resp(msg);
1533 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001534 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001535 rc = gsm48_rx_mm_serv_req(msg);
1536 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001537 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001538 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001539 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001540 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001541 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1542 msg->lchan->subscr ?
1543 msg->lchan->subscr->imsi :
1544 "unknown subscriber");
1545 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001546 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001547 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1548 break;
1549 case GSM48_MT_MM_CM_REEST_REQ:
1550 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1551 break;
1552 case GSM48_MT_MM_AUTH_RESP:
1553 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001554 break;
1555 default:
1556 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1557 gh->msg_type);
1558 break;
1559 }
1560
1561 return rc;
1562}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001563
Harald Welte2d35ae62009-02-06 12:02:13 +00001564/* Receive a PAGING RESPONSE message from the MS */
1565static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1566{
1567 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001568 u_int8_t *classmark2_lv = gh->data + 1;
1569 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1570 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001571 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001572 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001573 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001574 int rc = 0;
1575
Harald Welte61548982009-02-22 21:26:29 +00001576 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001577 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1578 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001579 switch (mi_type) {
1580 case GSM_MI_TYPE_TMSI:
1581 subscr = subscr_get_by_tmsi(mi_string);
1582 break;
1583 case GSM_MI_TYPE_IMSI:
1584 subscr = subscr_get_by_imsi(mi_string);
1585 break;
1586 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001587
1588 if (!subscr) {
1589 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001590 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001591 return -EINVAL;
1592 }
1593 DEBUGP(DRR, "<- Channel was requested by %s\n",
1594 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001595
Harald Weltef7c43522009-06-09 20:24:21 +00001596 subscr->classmark2_len = *classmark2_lv;
1597 memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv);
1598
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001599 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001600 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001601 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001602 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1603 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001604 return -EINVAL;
1605 } else {
1606 DEBUGP(DRR, "<- Channel already owned by us\n");
1607 subscr_put(subscr);
1608 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001609 }
1610
Harald Welte595ad7b2009-02-16 22:05:44 +00001611 sig_data.subscr = subscr;
1612 sig_data.bts = msg->lchan->ts->trx->bts;
1613 sig_data.lchan = msg->lchan;
1614
1615 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001616
1617 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001618 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001619
Harald Welte7584aea2009-02-11 11:44:12 +00001620 /* FIXME: somehow signal the completion of the PAGING to
1621 * the entity that requested the paging */
1622
Harald Welte2d35ae62009-02-06 12:02:13 +00001623 return rc;
1624}
1625
Harald Weltef7c43522009-06-09 20:24:21 +00001626static int gsm48_rx_rr_classmark(struct msgb *msg)
1627{
1628 struct gsm48_hdr *gh = msgb_l3(msg);
1629 struct gsm_subscriber *subscr = msg->lchan->subscr;
1630 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1631 u_int8_t cm2_len, cm3_len = 0;
1632 u_int8_t *cm2, *cm3 = NULL;
1633
1634 DEBUGP(DRR, "CLASSMARK CHANGE ");
1635
1636 /* classmark 2 */
1637 cm2_len = gh->data[0];
1638 cm2 = &gh->data[1];
1639 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1640
1641 if (payload_len > cm2_len + 1) {
1642 /* we must have a classmark3 */
1643 if (gh->data[cm2_len+1] != 0x20) {
1644 DEBUGPC(DRR, "ERR CM3 TAG\n");
1645 return -EINVAL;
1646 }
1647 if (cm2_len > 3) {
1648 DEBUGPC(DRR, "CM2 too long!\n");
1649 return -EINVAL;
1650 }
1651
1652 cm3_len = gh->data[cm2_len+2];
1653 cm3 = &gh->data[cm2_len+3];
1654 if (cm3_len > 14) {
1655 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1656 return -EINVAL;
1657 }
1658 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1659 }
1660 if (subscr) {
1661 subscr->classmark2_len = cm2_len;
1662 memcpy(subscr->classmark2, cm2, cm2_len);
1663 if (cm3) {
1664 subscr->classmark3_len = cm3_len;
1665 memcpy(subscr->classmark3, cm3, cm3_len);
1666 }
1667 }
1668
1669 /* FIXME: store the classmark2/3 values with the equipment register */
1670
1671 return 0;
1672}
1673
Harald Weltecf5b3592009-05-01 18:28:42 +00001674static int gsm48_rx_rr_status(struct msgb *msg)
1675{
1676 struct gsm48_hdr *gh = msgb_l3(msg);
1677
1678 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1679 rr_cause_name(gh->data[0]));
1680
1681 return 0;
1682}
1683
Harald Weltef7c43522009-06-09 20:24:21 +00001684static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1685{
1686 struct gsm48_hdr *gh = msgb_l3(msg);
1687 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1688 static struct gsm_meas_rep meas_rep;
1689
1690 DEBUGP(DRR, "MEASUREMENT REPORT ");
1691 parse_meas_rep(&meas_rep, gh->data, payload_len);
1692 if (meas_rep.flags & MEAS_REP_F_DTX)
1693 DEBUGPC(DRR, "DTX ");
1694 if (meas_rep.flags & MEAS_REP_F_BA1)
1695 DEBUGPC(DRR, "BA1 ");
1696 if (!(meas_rep.flags & MEAS_REP_F_VALID))
1697 DEBUGPC(DRR, "NOT VALID ");
1698 else
1699 DEBUGPC(DRR, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
1700 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1701 meas_rep.rxqual_sub);
1702
1703 DEBUGPC(DRR, "NUM_NEIGH=%u\n", meas_rep.num_cell);
1704
1705 /* FIXME: put the results somwhere */
1706
1707 return 0;
1708}
1709
Harald Weltebf5e8df2009-02-03 12:59:45 +00001710/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001711static int gsm0408_rcv_rr(struct msgb *msg)
1712{
1713 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001714 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001715
1716 switch (gh->msg_type) {
1717 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001718 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001719 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001720 case GSM48_MT_RR_GPRS_SUSP_REQ:
1721 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1722 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001723 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001724 rc = gsm48_rr_rx_pag_resp(msg);
1725 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001726 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1727 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001728 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001729 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001730 case GSM48_MT_RR_STATUS:
1731 rc = gsm48_rx_rr_status(msg);
1732 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001733 case GSM48_MT_RR_MEAS_REP:
1734 rc = gsm48_rx_rr_meas_rep(msg);
1735 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001736 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001737 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001738 gh->msg_type);
1739 break;
1740 }
1741
Harald Welte2d35ae62009-02-06 12:02:13 +00001742 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001743}
1744
Holger Freythere64a7a32009-02-06 21:55:37 +00001745/* 7.1.7 and 9.1.7 Channel release*/
1746int gsm48_send_rr_release(struct gsm_lchan *lchan)
1747{
1748 struct msgb *msg = gsm48_msgb_alloc();
1749 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1750 u_int8_t *cause;
1751
1752 msg->lchan = lchan;
1753 gh->proto_discr = GSM48_PDISC_RR;
1754 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1755
1756 cause = msgb_put(msg, 1);
1757 cause[0] = GSM48_RR_CAUSE_NORMAL;
1758
1759 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1760 lchan->nr, lchan->type);
1761
1762 return gsm48_sendmsg(msg);
1763}
1764
Harald Welte4bc90a12008-12-27 16:32:52 +00001765/* Call Control */
1766
Harald Welte7584aea2009-02-11 11:44:12 +00001767/* The entire call control code is written in accordance with Figure 7.10c
1768 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1769 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1770 * it for voice */
1771
Harald Welte4bfdfe72009-06-10 23:11:52 +08001772static void new_cc_state(struct gsm_trans *trans, int state)
1773{
1774 if (state > 31 || state < 0)
1775 return;
1776
1777 DEBUGP(DCC, "new state %s -> %s\n",
1778 cc_state_names[trans->state], cc_state_names[state]);
1779
1780 trans->state = state;
1781}
1782
1783static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001784{
1785 struct msgb *msg = gsm48_msgb_alloc();
1786 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1787 u_int8_t *cause, *call_state;
1788
Harald Welte4bfdfe72009-06-10 23:11:52 +08001789 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1790 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001791 gh->msg_type = GSM48_MT_CC_STATUS;
1792
1793 cause = msgb_put(msg, 3);
1794 cause[0] = 2;
1795 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1796 cause[2] = 0x80 | 30; /* response to status inquiry */
1797
1798 call_state = msgb_put(msg, 1);
1799 call_state[0] = 0xc0 | 0x00;
1800
Harald Welte65e74cc2008-12-29 01:55:35 +00001801 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001802}
1803
Harald Welte6f4b7532008-12-29 00:39:37 +00001804static int gsm48_tx_simple(struct gsm_lchan *lchan,
1805 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001806{
1807 struct msgb *msg = gsm48_msgb_alloc();
1808 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1809
1810 msg->lchan = lchan;
1811
Harald Welte6f4b7532008-12-29 00:39:37 +00001812 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001813 gh->msg_type = msg_type;
1814
Harald Welte65e74cc2008-12-29 01:55:35 +00001815 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001816}
1817
Harald Welte4bfdfe72009-06-10 23:11:52 +08001818static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1819{
1820 if (bsc_timer_pending(&trans->cc_timer)) {
1821 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1822 bsc_del_timer(&trans->cc_timer);
1823 trans->Tcurrent = 0;
1824 }
1825}
1826
1827static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1828 int msg_type, struct gsm_mncc *mncc)
1829{
1830 struct msgb *msg;
1831
1832 if (trans)
1833 if (trans->lchan)
1834 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1835 "Sending '%s' to MNCC.\n",
1836 trans->lchan->ts->trx->bts->nr,
1837 trans->lchan->ts->trx->nr,
1838 trans->lchan->ts->nr, trans->transaction_id,
1839 (trans->subscr)?(trans->subscr->extension):"-",
1840 get_mncc_name(msg_type));
1841 else
1842 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1843 "Sending '%s' to MNCC.\n",
1844 (trans->subscr)?(trans->subscr->extension):"-",
1845 get_mncc_name(msg_type));
1846 else
1847 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1848 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1849
1850 mncc->msg_type = msg_type;
1851
1852 msg = msgb_alloc(sizeof(struct gsm_mncc));
1853 if (!msg)
1854 return -ENOMEM;
1855 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1856 msgb_enqueue(&net->upqueue, msg);
1857
1858 return 0;
1859}
1860
1861int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1862 u_int32_t callref, int location, int value)
1863{
1864 struct gsm_mncc rel;
1865
Harald Welte92f70c52009-06-12 01:54:08 +08001866 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001867 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001868 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001869 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1870}
1871
1872void free_trans(struct gsm_trans *trans)
1873{
1874 struct gsm_bts *bts;
1875
1876 gsm48_stop_cc_timer(trans);
1877
1878 /* send release to L4, if callref still exists */
1879 if (trans->callref) {
1880 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001881 mncc_release_ind(trans->network, trans, trans->callref,
1882 GSM48_CAUSE_LOC_PRN_S_LU,
1883 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001884 if (trans->state != GSM_CSTATE_NULL)
1885 new_cc_state(trans, GSM_CSTATE_NULL);
1886 }
1887
1888 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1889 /* Stop paging on all bts' */
1890 bts = NULL;
1891 do {
1892 bts = gsm_bts_by_lac(trans->subscr->net,
1893 trans->subscr->lac, bts);
1894 if (!bts)
1895 break;
1896 /* Stop paging */
1897 paging_request_stop(bts, trans->subscr, NULL);
1898 } while (1);
1899 }
1900
1901 if (trans->lchan) {
1902 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1903 put_lchan(trans->lchan);
1904 }
1905
1906 if (trans->subscr)
1907 subscr_put(trans->subscr);
1908
1909 if (trans->state != GSM_CSTATE_NULL)
1910 new_cc_state(trans, GSM_CSTATE_NULL);
1911
1912 llist_del(&trans->entry);
1913
1914 free(trans);
1915}
1916
1917static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1918
Harald Welte09e38af2009-02-16 22:52:23 +00001919/* call-back from paging the B-end of the connection */
1920static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001921 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001922{
Harald Welte7ccf7782009-02-17 01:43:01 +00001923 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001924 struct gsm_subscriber *subscr = param;
1925 struct gsm_trans *transt, *tmp;
1926 struct gsm_network *net;
1927
Harald Welte09e38af2009-02-16 22:52:23 +00001928 if (hooknum != GSM_HOOK_RR_PAGING)
1929 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001930
1931 if (!subscr)
1932 return -EINVAL;
1933 net = subscr->net;
1934 if (!net) {
1935 DEBUGP(DCC, "Error Network not set!\n");
1936 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001937 }
Harald Welte7584aea2009-02-11 11:44:12 +00001938
Harald Welte4bfdfe72009-06-10 23:11:52 +08001939 /* check all tranactions (without lchan) for subscriber */
1940 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1941 if (transt->subscr != subscr || transt->lchan)
1942 continue;
1943 switch (event) {
1944 case GSM_PAGING_SUCCEEDED:
1945 if (!lchan) // paranoid
1946 break;
1947 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1948 subscr->extension);
1949 /* Assign lchan */
1950 if (!transt->lchan) {
1951 transt->lchan = lchan;
1952 use_lchan(lchan);
1953 }
1954 /* send SETUP request to called party */
1955 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1956 if (is_ipaccess_bts(lchan->ts->trx->bts))
1957 rsl_ipacc_bind(lchan);
1958 break;
1959 case GSM_PAGING_EXPIRED:
1960 DEBUGP(DCC, "Paging subscr %s expired!\n",
1961 subscr->extension);
1962 /* Temporarily out of order */
1963 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001964 GSM48_CAUSE_LOC_PRN_S_LU,
1965 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001966 transt->callref = 0;
1967 free_trans(transt);
1968 break;
1969 }
1970 }
Harald Welte09e38af2009-02-16 22:52:23 +00001971 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001972}
Harald Welte7584aea2009-02-11 11:44:12 +00001973
Harald Welte49f48b82009-02-17 15:29:33 +00001974/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001975static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001976{
Harald Welte11fa29c2009-02-19 17:24:39 +00001977 struct gsm_bts *bts = lchan->ts->trx->bts;
1978 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001979 struct gsm_bts_trx_ts *ts;
1980
Harald Welte11fa29c2009-02-19 17:24:39 +00001981 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1982 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1983 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1984
1985 if (bts->type != remote_bts->type) {
1986 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1987 return -EINVAL;
1988 }
Harald Welte49f48b82009-02-17 15:29:33 +00001989
Harald Welte11fa29c2009-02-19 17:24:39 +00001990 switch (bts->type) {
1991 case GSM_BTS_TYPE_NANOBTS_900:
1992 case GSM_BTS_TYPE_NANOBTS_1800:
1993 ts = remote_lchan->ts;
1994 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
1995 lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
1996
1997 ts = lchan->ts;
1998 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
1999 remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2000 break;
2001 case GSM_BTS_TYPE_BS11:
2002 trau_mux_map_lchan(lchan, remote_lchan);
2003 break;
2004 default:
2005 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2006 break;
2007 }
Harald Welte49f48b82009-02-17 15:29:33 +00002008
2009 return 0;
2010}
2011
Harald Welte4bfdfe72009-06-10 23:11:52 +08002012static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002013{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002014 struct gsm_trans *trans;
2015 llist_for_each_entry(trans, &net->trans_list, entry) {
2016 if (trans->callref == callref)
2017 return trans;
2018 }
2019 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002020}
2021
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022/* bridge channels of two transactions */
2023static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002024{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002025 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2026 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002027
Harald Welte4bfdfe72009-06-10 23:11:52 +08002028 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002029 return -EIO;
2030
Harald Welte4bfdfe72009-06-10 23:11:52 +08002031 if (!trans1->lchan || !trans2->lchan)
2032 return -EIO;
2033
2034 /* through-connect channel */
2035 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002036}
2037
Harald Welte4bfdfe72009-06-10 23:11:52 +08002038/* enable receive of channels to upqueue */
2039static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2040{
2041 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002042
Harald Welte4bfdfe72009-06-10 23:11:52 +08002043 /* Find callref */
2044 trans = get_trans_ref(net, data->callref);
2045 if (!trans)
2046 return -EIO;
2047 if (!trans->lchan)
2048 return 0;
2049
2050 // todo IPACCESS
2051 if (enable)
2052 return trau_recv_lchan(trans->lchan, data->callref);
2053 return trau_mux_unmap(NULL, data->callref);
2054}
2055
2056/* send a frame to channel */
2057static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2058{
2059 struct gsm_trans *trans;
2060
2061 /* Find callref */
2062 trans = get_trans_ref(net, frame->callref);
2063 if (!trans)
2064 return -EIO;
2065 if (!trans->lchan)
2066 return 0;
2067 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2068 trans->lchan->type != GSM_LCHAN_TCH_H)
2069 return 0;
2070
2071 // todo IPACCESS
2072 return trau_send_lchan(trans->lchan,
2073 (struct decoded_trau_frame *)frame->data);
2074}
2075
2076
2077static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2078{
2079 DEBUGP(DCC, "-> STATUS ENQ\n");
2080 return gsm48_cc_tx_status(trans, msg);
2081}
2082
2083static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2084static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2085
2086static void gsm48_cc_timeout(void *arg)
2087{
2088 struct gsm_trans *trans = arg;
2089 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002090 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2091 int mo_location = GSM48_CAUSE_LOC_USER;
2092 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2093 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002094 struct gsm_mncc mo_rel, l4_rel;
2095
2096 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2097 mo_rel.callref = trans->callref;
2098 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2099 l4_rel.callref = trans->callref;
2100
2101 switch(trans->Tcurrent) {
2102 case 0x303:
2103 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002104 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002105 break;
2106 case 0x310:
2107 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002108 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002109 break;
2110 case 0x313:
2111 disconnect = 1;
2112 /* unknown, did not find it in the specs */
2113 break;
2114 case 0x301:
2115 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002116 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002117 break;
2118 case 0x308:
2119 if (!trans->T308_second) {
2120 /* restart T308 a second time */
2121 gsm48_cc_tx_release(trans, &trans->cc_msg);
2122 trans->T308_second = 1;
2123 break; /* stay in release state */
2124 }
2125 free_trans(trans);
2126 return;
2127// release = 1;
2128// l4_cause = 14;
2129// break;
2130 case 0x306:
2131 release = 1;
2132 mo_cause = trans->cc_msg.cause.value;
2133 mo_location = trans->cc_msg.cause.location;
2134 break;
2135 case 0x323:
2136 disconnect = 1;
2137 break;
2138 default:
2139 release = 1;
2140 }
2141
2142 if (release && trans->callref) {
2143 /* process release towards layer 4 */
2144 mncc_release_ind(trans->network, trans, trans->callref,
2145 l4_location, l4_cause);
2146 trans->callref = 0;
2147 }
2148
2149 if (disconnect && trans->callref) {
2150 /* process disconnect towards layer 4 */
2151 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2152 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2153 }
2154
2155 /* process disconnect towards mobile station */
2156 if (disconnect || release) {
2157 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2158 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2159 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2160 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2161 mo_rel.cause.diag_len = 3;
2162
2163 if (disconnect)
2164 gsm48_cc_tx_disconnect(trans, &mo_rel);
2165 if (release)
2166 gsm48_cc_tx_release(trans, &mo_rel);
2167 }
2168
2169}
2170
2171static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2172 int sec, int micro)
2173{
2174 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2175 trans->cc_timer.cb = gsm48_cc_timeout;
2176 trans->cc_timer.data = trans;
2177 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2178 trans->Tcurrent = current;
2179}
2180
2181static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2182{
2183 struct gsm48_hdr *gh = msgb_l3(msg);
2184 u_int8_t msg_type = gh->msg_type & 0xbf;
2185 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2186 struct tlv_parsed tp;
2187 struct gsm_mncc setup;
2188
2189 memset(&setup, 0, sizeof(struct gsm_mncc));
2190 setup.callref = trans->callref;
2191 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2192 /* emergency setup is identified by msg_type */
2193 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2194 setup.emergency = 1;
2195
2196 /* use subscriber as calling party number */
2197 if (trans->subscr) {
2198 setup.fields |= MNCC_F_CALLING;
2199 strncpy(setup.calling.number, trans->subscr->extension,
2200 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002201 strncpy(setup.imsi, trans->subscr->imsi,
2202 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002203 }
2204 /* bearer capability */
2205 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2206 setup.fields |= MNCC_F_BEARER_CAP;
2207 decode_bearer_cap(&setup.bearer_cap,
2208 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2209 }
2210 /* facility */
2211 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2212 setup.fields |= MNCC_F_FACILITY;
2213 decode_facility(&setup.facility,
2214 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2215 }
2216 /* called party bcd number */
2217 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2218 setup.fields |= MNCC_F_CALLED;
2219 decode_called(&setup.called,
2220 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2221 }
2222 /* user-user */
2223 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2224 setup.fields |= MNCC_F_USERUSER;
2225 decode_useruser(&setup.useruser,
2226 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2227 }
2228 /* ss-version */
2229 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2230 setup.fields |= MNCC_F_SSVERSION;
2231 decode_ssversion(&setup.ssversion,
2232 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2233 }
2234 /* CLIR suppression */
2235 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2236 setup.clir.sup = 1;
2237 /* CLIR invocation */
2238 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2239 setup.clir.inv = 1;
2240 /* cc cap */
2241 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2242 setup.fields |= MNCC_F_CCCAP;
2243 decode_cccap(&setup.cccap,
2244 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2245 }
2246
2247 if (is_ipaccess_bts(msg->trx->bts))
2248 rsl_ipacc_bind(msg->lchan);
2249
2250 new_cc_state(trans, GSM_CSTATE_INITIATED);
2251
2252 /* indicate setup to MNCC */
2253 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2254
2255 return 0;
2256}
2257
2258static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002259{
2260 struct msgb *msg = gsm48_msgb_alloc();
2261 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002262 struct gsm_mncc *setup = arg;
2263 struct gsm_trans *transt;
2264 u_int16_t trans_id_mask = 0;
2265 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002266
Harald Welte7ccf7782009-02-17 01:43:01 +00002267 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002268
Harald Welte4bfdfe72009-06-10 23:11:52 +08002269 /* transaction id must not be assigned */
2270 if (trans->transaction_id != 0xff) { /* unasssigned */
2271 DEBUGP(DCC, "TX Setup with assigned transaction. "
2272 "This is not allowed!\n");
2273 /* Temporarily out of order */
2274 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002275 GSM48_CAUSE_LOC_PRN_S_LU,
2276 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002277 trans->callref = 0;
2278 free_trans(trans);
2279 return rc;
2280 }
2281
2282 /* Get free transaction_id */
2283 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2284 /* Transaction of our lchan? */
2285 if (transt->lchan == trans->lchan &&
2286 transt->transaction_id != 0xff)
2287 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2288 }
2289 /* Assign free transaction ID */
2290 if ((trans_id_mask & 0x007f) == 0x7f) {
2291 /* no free transaction ID */
2292 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002293 GSM48_CAUSE_LOC_PRN_S_LU,
2294 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002295 trans->callref = 0;
2296 free_trans(trans);
2297 return rc;
2298 }
2299 for (i = 0; i < 7; i++) {
2300 if ((trans_id_mask & (1 << i)) == 0) {
2301 trans->transaction_id = i << 4; /* flag = 0 */
2302 break;
2303 }
2304 }
Harald Welte49f48b82009-02-17 15:29:33 +00002305
Harald Welte4bfdfe72009-06-10 23:11:52 +08002306 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2307 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002308 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002309
Harald Welte4bfdfe72009-06-10 23:11:52 +08002310 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002311
Harald Welte4bfdfe72009-06-10 23:11:52 +08002312 /* bearer capability */
2313 if (setup->fields & MNCC_F_BEARER_CAP)
2314 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2315 /* facility */
2316 if (setup->fields & MNCC_F_FACILITY)
2317 encode_facility(msg, 0, &setup->facility);
2318 /* progress */
2319 if (setup->fields & MNCC_F_PROGRESS)
2320 encode_progress(msg, 0, &setup->progress);
2321 /* calling party BCD number */
2322 if (setup->fields & MNCC_F_CALLING)
2323 encode_calling(msg, &setup->calling);
2324 /* called party BCD number */
2325 if (setup->fields & MNCC_F_CALLED)
2326 encode_called(msg, &setup->called);
2327 /* user-user */
2328 if (setup->fields & MNCC_F_USERUSER)
2329 encode_useruser(msg, 0, &setup->useruser);
2330 /* redirecting party BCD number */
2331 if (setup->fields & MNCC_F_REDIRECTING)
2332 encode_redirecting(msg, &setup->redirecting);
2333 /* signal */
2334 if (setup->fields & MNCC_F_SIGNAL)
2335 encode_signal(msg, setup->signal);
2336
2337 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002338
2339 return gsm48_sendmsg(msg);
2340}
2341
Harald Welte4bfdfe72009-06-10 23:11:52 +08002342static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2343{
2344 struct gsm48_hdr *gh = msgb_l3(msg);
2345 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2346 struct tlv_parsed tp;
2347 struct gsm_mncc call_conf;
2348
2349 gsm48_stop_cc_timer(trans);
2350 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2351
2352 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2353 call_conf.callref = trans->callref;
2354 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2355#if 0
2356 /* repeat */
2357 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2358 call_conf.repeat = 1;
2359 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2360 call_conf.repeat = 2;
2361#endif
2362 /* bearer capability */
2363 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2364 call_conf.fields |= MNCC_F_BEARER_CAP;
2365 decode_bearer_cap(&call_conf.bearer_cap,
2366 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2367 }
2368 /* cause */
2369 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2370 call_conf.fields |= MNCC_F_CAUSE;
2371 decode_cause(&call_conf.cause,
2372 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2373 }
2374 /* cc cap */
2375 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2376 call_conf.fields |= MNCC_F_CCCAP;
2377 decode_cccap(&call_conf.cccap,
2378 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2379 }
2380
2381 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2382
2383 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2384}
2385
2386static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2387{
2388 struct gsm_mncc *proceeding = arg;
2389 struct msgb *msg = gsm48_msgb_alloc();
2390 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2391
2392 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2393 msg->lchan = trans->lchan;
2394 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2395
2396 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2397
2398 /* bearer capability */
2399 if (proceeding->fields & MNCC_F_BEARER_CAP)
2400 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2401 /* facility */
2402 if (proceeding->fields & MNCC_F_FACILITY)
2403 encode_facility(msg, 0, &proceeding->facility);
2404 /* progress */
2405 if (proceeding->fields & MNCC_F_PROGRESS)
2406 encode_progress(msg, 0, &proceeding->progress);
2407
2408 return gsm48_sendmsg(msg);
2409}
2410
2411static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2412{
2413 struct gsm48_hdr *gh = msgb_l3(msg);
2414 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2415 struct tlv_parsed tp;
2416 struct gsm_mncc alerting;
2417
2418 gsm48_stop_cc_timer(trans);
2419 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2420
2421 memset(&alerting, 0, sizeof(struct gsm_mncc));
2422 alerting.callref = trans->callref;
2423 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2424 /* facility */
2425 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2426 alerting.fields |= MNCC_F_FACILITY;
2427 decode_facility(&alerting.facility,
2428 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2429 }
2430
2431 /* progress */
2432 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2433 alerting.fields |= MNCC_F_PROGRESS;
2434 decode_progress(&alerting.progress,
2435 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2436 }
2437 /* ss-version */
2438 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2439 alerting.fields |= MNCC_F_SSVERSION;
2440 decode_ssversion(&alerting.ssversion,
2441 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2442 }
2443
2444 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2445
2446 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2447}
2448
2449static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2450{
2451 struct gsm_mncc *alerting = arg;
2452 struct msgb *msg = gsm48_msgb_alloc();
2453 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2454
2455 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2456 msg->lchan = trans->lchan;
2457 gh->msg_type = GSM48_MT_CC_ALERTING;
2458
2459 /* facility */
2460 if (alerting->fields & MNCC_F_FACILITY)
2461 encode_facility(msg, 0, &alerting->facility);
2462 /* progress */
2463 if (alerting->fields & MNCC_F_PROGRESS)
2464 encode_progress(msg, 0, &alerting->progress);
2465 /* user-user */
2466 if (alerting->fields & MNCC_F_USERUSER)
2467 encode_useruser(msg, 0, &alerting->useruser);
2468
2469 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2470
2471 return gsm48_sendmsg(msg);
2472}
2473
2474static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2475{
2476 struct gsm_mncc *progress = arg;
2477 struct msgb *msg = gsm48_msgb_alloc();
2478 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2479
2480 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2481 msg->lchan = trans->lchan;
2482 gh->msg_type = GSM48_MT_CC_PROGRESS;
2483
2484 /* progress */
2485 encode_progress(msg, 1, &progress->progress);
2486 /* user-user */
2487 if (progress->fields & MNCC_F_USERUSER)
2488 encode_useruser(msg, 0, &progress->useruser);
2489
2490 return gsm48_sendmsg(msg);
2491}
2492
2493static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2494{
2495 struct gsm_mncc *connect = arg;
2496 struct msgb *msg = gsm48_msgb_alloc();
2497 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2498
2499 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2500 msg->lchan = trans->lchan;
2501 gh->msg_type = GSM48_MT_CC_CONNECT;
2502
2503 gsm48_stop_cc_timer(trans);
2504 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2505
2506 /* facility */
2507 if (connect->fields & MNCC_F_FACILITY)
2508 encode_facility(msg, 0, &connect->facility);
2509 /* progress */
2510 if (connect->fields & MNCC_F_PROGRESS)
2511 encode_progress(msg, 0, &connect->progress);
2512 /* connected number */
2513 if (connect->fields & MNCC_F_CONNECTED)
2514 encode_connected(msg, &connect->connected);
2515 /* user-user */
2516 if (connect->fields & MNCC_F_USERUSER)
2517 encode_useruser(msg, 0, &connect->useruser);
2518
2519 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2520
2521 return gsm48_sendmsg(msg);
2522}
2523
2524static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2525{
2526 struct gsm48_hdr *gh = msgb_l3(msg);
2527 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2528 struct tlv_parsed tp;
2529 struct gsm_mncc connect;
2530
2531 gsm48_stop_cc_timer(trans);
2532
2533 memset(&connect, 0, sizeof(struct gsm_mncc));
2534 connect.callref = trans->callref;
2535 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2536 /* use subscriber as connected party number */
2537 if (trans->subscr) {
2538 connect.fields |= MNCC_F_CONNECTED;
2539 strncpy(connect.connected.number, trans->subscr->extension,
2540 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002541 strncpy(connect.imsi, trans->subscr->imsi,
2542 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002543 }
2544 /* facility */
2545 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2546 connect.fields |= MNCC_F_FACILITY;
2547 decode_facility(&connect.facility,
2548 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2549 }
2550 /* user-user */
2551 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2552 connect.fields |= MNCC_F_USERUSER;
2553 decode_useruser(&connect.useruser,
2554 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2555 }
2556 /* ss-version */
2557 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2558 connect.fields |= MNCC_F_SSVERSION;
2559 decode_ssversion(&connect.ssversion,
2560 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2561 }
2562
2563 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2564
2565 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2566}
2567
2568
2569static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2570{
2571 struct gsm_mncc connect_ack;
2572
2573 gsm48_stop_cc_timer(trans);
2574
2575 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2576
2577 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2578 connect_ack.callref = trans->callref;
2579 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2580 &connect_ack);
2581}
2582
2583static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2584{
2585 struct msgb *msg = gsm48_msgb_alloc();
2586 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2587
2588 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2589 msg->lchan = trans->lchan;
2590 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2591
2592 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2593
2594 return gsm48_sendmsg(msg);
2595}
2596
2597static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2598{
2599 struct gsm48_hdr *gh = msgb_l3(msg);
2600 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2601 struct tlv_parsed tp;
2602 struct gsm_mncc disc;
2603
2604 gsm48_stop_cc_timer(trans);
2605
2606 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2607
2608 memset(&disc, 0, sizeof(struct gsm_mncc));
2609 disc.callref = trans->callref;
2610 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2611 /* cause */
2612 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2613 disc.fields |= MNCC_F_CAUSE;
2614 decode_cause(&disc.cause,
2615 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2616 }
2617 /* facility */
2618 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2619 disc.fields |= MNCC_F_FACILITY;
2620 decode_facility(&disc.facility,
2621 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2622 }
2623 /* user-user */
2624 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2625 disc.fields |= MNCC_F_USERUSER;
2626 decode_useruser(&disc.useruser,
2627 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2628 }
2629 /* ss-version */
2630 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2631 disc.fields |= MNCC_F_SSVERSION;
2632 decode_ssversion(&disc.ssversion,
2633 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2634 }
2635
2636 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2637
2638}
2639
Harald Weltec66b71c2009-06-11 14:23:20 +08002640static struct gsm_mncc_cause default_cause = {
2641 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2642 .coding = 0,
2643 .rec = 0,
2644 .rec_val = 0,
2645 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2646 .diag_len = 0,
2647 .diag = { 0 },
2648};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002649
2650static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2651{
2652 struct gsm_mncc *disc = arg;
2653 struct msgb *msg = gsm48_msgb_alloc();
2654 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2655
2656 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2657 msg->lchan = trans->lchan;
2658 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2659
2660 gsm48_stop_cc_timer(trans);
2661 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2662
2663 /* cause */
2664 if (disc->fields & MNCC_F_CAUSE)
2665 encode_cause(msg, 1, &disc->cause);
2666 else
2667 encode_cause(msg, 1, &default_cause);
2668
2669 /* facility */
2670 if (disc->fields & MNCC_F_FACILITY)
2671 encode_facility(msg, 0, &disc->facility);
2672 /* progress */
2673 if (disc->fields & MNCC_F_PROGRESS)
2674 encode_progress(msg, 0, &disc->progress);
2675 /* user-user */
2676 if (disc->fields & MNCC_F_USERUSER)
2677 encode_useruser(msg, 0, &disc->useruser);
2678
2679 /* store disconnect cause for T306 expiry */
2680 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2681
2682 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2683
2684 return gsm48_sendmsg(msg);
2685}
2686
2687static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2688{
2689 struct gsm48_hdr *gh = msgb_l3(msg);
2690 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2691 struct tlv_parsed tp;
2692 struct gsm_mncc rel;
2693 int rc;
2694
2695 gsm48_stop_cc_timer(trans);
2696
2697 memset(&rel, 0, sizeof(struct gsm_mncc));
2698 rel.callref = trans->callref;
2699 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2700 /* cause */
2701 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2702 rel.fields |= MNCC_F_CAUSE;
2703 decode_cause(&rel.cause,
2704 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2705 }
2706 /* facility */
2707 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2708 rel.fields |= MNCC_F_FACILITY;
2709 decode_facility(&rel.facility,
2710 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2711 }
2712 /* user-user */
2713 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2714 rel.fields |= MNCC_F_USERUSER;
2715 decode_useruser(&rel.useruser,
2716 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2717 }
2718 /* ss-version */
2719 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2720 rel.fields |= MNCC_F_SSVERSION;
2721 decode_ssversion(&rel.ssversion,
2722 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2723 }
2724
2725 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2726 /* release collision 5.4.5 */
2727 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2728 } else {
2729 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2730 GSM48_MT_CC_RELEASE_COMPL);
2731 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2732 }
2733
2734 new_cc_state(trans, GSM_CSTATE_NULL);
2735
2736 trans->callref = 0;
2737 free_trans(trans);
2738
2739 return rc;
2740}
2741
2742static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2743{
2744 struct gsm_mncc *rel = arg;
2745 struct msgb *msg = gsm48_msgb_alloc();
2746 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2747
2748 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2749 msg->lchan = trans->lchan;
2750 gh->msg_type = GSM48_MT_CC_RELEASE;
2751
2752 trans->callref = 0;
2753
2754 gsm48_stop_cc_timer(trans);
2755 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2756
2757 /* cause */
2758 if (rel->fields & MNCC_F_CAUSE)
2759 encode_cause(msg, 0, &rel->cause);
2760 /* facility */
2761 if (rel->fields & MNCC_F_FACILITY)
2762 encode_facility(msg, 0, &rel->facility);
2763 /* user-user */
2764 if (rel->fields & MNCC_F_USERUSER)
2765 encode_useruser(msg, 0, &rel->useruser);
2766
2767 trans->T308_second = 0;
2768 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2769
2770 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2771 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2772
2773 return gsm48_sendmsg(msg);
2774}
2775
2776static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2777{
2778 struct gsm48_hdr *gh = msgb_l3(msg);
2779 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2780 struct tlv_parsed tp;
2781 struct gsm_mncc rel;
2782 int rc = 0;
2783
2784 gsm48_stop_cc_timer(trans);
2785
2786 memset(&rel, 0, sizeof(struct gsm_mncc));
2787 rel.callref = trans->callref;
2788 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2789 /* cause */
2790 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2791 rel.fields |= MNCC_F_CAUSE;
2792 decode_cause(&rel.cause,
2793 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2794 }
2795 /* facility */
2796 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2797 rel.fields |= MNCC_F_FACILITY;
2798 decode_facility(&rel.facility,
2799 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2800 }
2801 /* user-user */
2802 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2803 rel.fields |= MNCC_F_USERUSER;
2804 decode_useruser(&rel.useruser,
2805 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2806 }
2807 /* ss-version */
2808 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2809 rel.fields |= MNCC_F_SSVERSION;
2810 decode_ssversion(&rel.ssversion,
2811 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2812 }
2813
2814 if (trans->callref) {
2815 switch (trans->state) {
2816 case GSM_CSTATE_CALL_PRESENT:
2817 rc = mncc_recvmsg(trans->network, trans,
2818 MNCC_REJ_IND, &rel);
2819 break;
2820 case GSM_CSTATE_RELEASE_REQ:
2821 rc = mncc_recvmsg(trans->network, trans,
2822 MNCC_REL_CNF, &rel);
2823 break;
2824 default:
2825 rc = mncc_recvmsg(trans->network, trans,
2826 MNCC_REL_IND, &rel);
2827 }
2828 }
2829
2830 trans->callref = 0;
2831 free_trans(trans);
2832
2833 return rc;
2834}
2835
2836static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2837{
2838 struct gsm_mncc *rel = arg;
2839 struct msgb *msg = gsm48_msgb_alloc();
2840 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2841
2842 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2843 msg->lchan = trans->lchan;
2844 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2845
2846 trans->callref = 0;
2847
2848 gsm48_stop_cc_timer(trans);
2849
2850 /* cause */
2851 if (rel->fields & MNCC_F_CAUSE)
2852 encode_cause(msg, 0, &rel->cause);
2853 /* facility */
2854 if (rel->fields & MNCC_F_FACILITY)
2855 encode_facility(msg, 0, &rel->facility);
2856 /* user-user */
2857 if (rel->fields & MNCC_F_USERUSER)
2858 encode_useruser(msg, 0, &rel->useruser);
2859
2860 free_trans(trans);
2861
2862 return gsm48_sendmsg(msg);
2863}
2864
2865static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2866{
2867 struct gsm48_hdr *gh = msgb_l3(msg);
2868 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2869 struct tlv_parsed tp;
2870 struct gsm_mncc fac;
2871
2872 memset(&fac, 0, sizeof(struct gsm_mncc));
2873 fac.callref = trans->callref;
2874 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2875 /* facility */
2876 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2877 fac.fields |= MNCC_F_FACILITY;
2878 decode_facility(&fac.facility,
2879 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2880 }
2881 /* ss-version */
2882 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2883 fac.fields |= MNCC_F_SSVERSION;
2884 decode_ssversion(&fac.ssversion,
2885 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2886 }
2887
2888 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2889}
2890
2891static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2892{
2893 struct gsm_mncc *fac = arg;
2894 struct msgb *msg = gsm48_msgb_alloc();
2895 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2896
2897 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2898 msg->lchan = trans->lchan;
2899 gh->msg_type = GSM48_MT_CC_FACILITY;
2900
2901 /* facility */
2902 encode_facility(msg, 1, &fac->facility);
2903
2904 return gsm48_sendmsg(msg);
2905}
2906
2907static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2908{
2909 struct gsm_mncc hold;
2910
2911 memset(&hold, 0, sizeof(struct gsm_mncc));
2912 hold.callref = trans->callref;
2913 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2914}
2915
2916static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2917{
2918 struct msgb *msg = gsm48_msgb_alloc();
2919 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2920
2921 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2922 msg->lchan = trans->lchan;
2923 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2924
2925 return gsm48_sendmsg(msg);
2926}
2927
2928static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2929{
2930 struct gsm_mncc *hold_rej = arg;
2931 struct msgb *msg = gsm48_msgb_alloc();
2932 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2933
2934 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2935 msg->lchan = trans->lchan;
2936 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2937
2938 /* cause */
2939 if (hold_rej->fields & MNCC_F_CAUSE)
2940 encode_cause(msg, 1, &hold_rej->cause);
2941 else
2942 encode_cause(msg, 1, &default_cause);
2943
2944 return gsm48_sendmsg(msg);
2945}
2946
2947static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2948{
2949 struct gsm_mncc retrieve;
2950
2951 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2952 retrieve.callref = trans->callref;
2953 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2954}
2955
2956static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2957{
2958 struct msgb *msg = gsm48_msgb_alloc();
2959 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2960
2961 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2962 msg->lchan = trans->lchan;
2963 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2964
2965 return gsm48_sendmsg(msg);
2966}
2967
2968static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2969{
2970 struct gsm_mncc *retrieve_rej = arg;
2971 struct msgb *msg = gsm48_msgb_alloc();
2972 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2973
2974 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2975 msg->lchan = trans->lchan;
2976 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2977
2978 /* cause */
2979 if (retrieve_rej->fields & MNCC_F_CAUSE)
2980 encode_cause(msg, 1, &retrieve_rej->cause);
2981 else
2982 encode_cause(msg, 1, &default_cause);
2983
2984 return gsm48_sendmsg(msg);
2985}
2986
2987static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2988{
2989 struct gsm48_hdr *gh = msgb_l3(msg);
2990 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2991 struct tlv_parsed tp;
2992 struct gsm_mncc dtmf;
2993
2994 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2995 dtmf.callref = trans->callref;
2996 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2997 /* keypad facility */
2998 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
2999 dtmf.fields |= MNCC_F_KEYPAD;
3000 decode_keypad(&dtmf.keypad,
3001 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3002 }
3003
3004 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3005}
3006
3007static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3008{
3009 struct gsm_mncc *dtmf = arg;
3010 struct msgb *msg = gsm48_msgb_alloc();
3011 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3012
3013 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3014 msg->lchan = trans->lchan;
3015 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3016
3017 /* keypad */
3018 if (dtmf->fields & MNCC_F_KEYPAD)
3019 encode_keypad(msg, dtmf->keypad);
3020
3021 return gsm48_sendmsg(msg);
3022}
3023
3024static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3025{
3026 struct gsm_mncc *dtmf = arg;
3027 struct msgb *msg = gsm48_msgb_alloc();
3028 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3029
3030 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3031 msg->lchan = trans->lchan;
3032 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3033
3034 /* cause */
3035 if (dtmf->fields & MNCC_F_CAUSE)
3036 encode_cause(msg, 1, &dtmf->cause);
3037 else
3038 encode_cause(msg, 1, &default_cause);
3039
3040 return gsm48_sendmsg(msg);
3041}
3042
3043static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3044{
3045 struct msgb *msg = gsm48_msgb_alloc();
3046 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3047
3048 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3049 msg->lchan = trans->lchan;
3050 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3051
3052 return gsm48_sendmsg(msg);
3053}
3054
3055static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3056{
3057 struct gsm_mncc dtmf;
3058
3059 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3060 dtmf.callref = trans->callref;
3061
3062 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3063}
3064
3065static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3066{
3067 struct gsm48_hdr *gh = msgb_l3(msg);
3068 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3069 struct tlv_parsed tp;
3070 struct gsm_mncc modify;
3071
3072 memset(&modify, 0, sizeof(struct gsm_mncc));
3073 modify.callref = trans->callref;
3074 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3075 /* bearer capability */
3076 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3077 modify.fields |= MNCC_F_BEARER_CAP;
3078 decode_bearer_cap(&modify.bearer_cap,
3079 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3080 }
3081
3082 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3083
3084 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3085}
3086
3087static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3088{
3089 struct gsm_mncc *modify = arg;
3090 struct msgb *msg = gsm48_msgb_alloc();
3091 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3092
3093 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3094 msg->lchan = trans->lchan;
3095 gh->msg_type = GSM48_MT_CC_MODIFY;
3096
3097 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3098
3099 /* bearer capability */
3100 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3101
3102 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3103
3104 return gsm48_sendmsg(msg);
3105}
3106
3107static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3108{
3109 struct gsm48_hdr *gh = msgb_l3(msg);
3110 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3111 struct tlv_parsed tp;
3112 struct gsm_mncc modify;
3113
3114 gsm48_stop_cc_timer(trans);
3115
3116 memset(&modify, 0, sizeof(struct gsm_mncc));
3117 modify.callref = trans->callref;
3118 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3119 /* bearer capability */
3120 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3121 modify.fields |= MNCC_F_BEARER_CAP;
3122 decode_bearer_cap(&modify.bearer_cap,
3123 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3124 }
3125
3126 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3127
3128 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3129}
3130
3131static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3132{
3133 struct gsm_mncc *modify = arg;
3134 struct msgb *msg = gsm48_msgb_alloc();
3135 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3136
3137 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3138 msg->lchan = trans->lchan;
3139 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3140
3141 /* bearer capability */
3142 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3143
3144 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3145
3146 return gsm48_sendmsg(msg);
3147}
3148
3149static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3150{
3151 struct gsm48_hdr *gh = msgb_l3(msg);
3152 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3153 struct tlv_parsed tp;
3154 struct gsm_mncc modify;
3155
3156 gsm48_stop_cc_timer(trans);
3157
3158 memset(&modify, 0, sizeof(struct gsm_mncc));
3159 modify.callref = trans->callref;
3160 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3161 /* bearer capability */
3162 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3163 modify.fields |= GSM48_IE_BEARER_CAP;
3164 decode_bearer_cap(&modify.bearer_cap,
3165 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3166 }
3167 /* cause */
3168 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3169 modify.fields |= MNCC_F_CAUSE;
3170 decode_cause(&modify.cause,
3171 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3172 }
3173
3174 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3175
3176 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3177}
3178
3179static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3180{
3181 struct gsm_mncc *modify = arg;
3182 struct msgb *msg = gsm48_msgb_alloc();
3183 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3184
3185 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3186 msg->lchan = trans->lchan;
3187 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3188
3189 /* bearer capability */
3190 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3191 /* cause */
3192 encode_cause(msg, 1, &modify->cause);
3193
3194 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3195
3196 return gsm48_sendmsg(msg);
3197}
3198
3199static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3200{
3201 struct gsm_mncc *notify = arg;
3202 struct msgb *msg = gsm48_msgb_alloc();
3203 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3204
3205 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3206 msg->lchan = trans->lchan;
3207 gh->msg_type = GSM48_MT_CC_NOTIFY;
3208
3209 /* notify */
3210 encode_notify(msg, notify->notify);
3211
3212 return gsm48_sendmsg(msg);
3213}
3214
3215static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3216{
3217 struct gsm48_hdr *gh = msgb_l3(msg);
3218 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3219// struct tlv_parsed tp;
3220 struct gsm_mncc notify;
3221
3222 memset(&notify, 0, sizeof(struct gsm_mncc));
3223 notify.callref = trans->callref;
3224// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3225 if (payload_len >= 1)
3226 decode_notify(&notify.notify, gh->data);
3227
3228 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3229}
3230
3231static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3232{
3233 struct gsm_mncc *user = arg;
3234 struct msgb *msg = gsm48_msgb_alloc();
3235 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3236
3237 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3238 msg->lchan = trans->lchan;
3239 gh->msg_type = GSM48_MT_CC_USER_INFO;
3240
3241 /* user-user */
3242 if (user->fields & MNCC_F_USERUSER)
3243 encode_useruser(msg, 1, &user->useruser);
3244 /* more data */
3245 if (user->more)
3246 encode_more(msg);
3247
3248 return gsm48_sendmsg(msg);
3249}
3250
3251static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3252{
3253 struct gsm48_hdr *gh = msgb_l3(msg);
3254 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3255 struct tlv_parsed tp;
3256 struct gsm_mncc user;
3257
3258 memset(&user, 0, sizeof(struct gsm_mncc));
3259 user.callref = trans->callref;
3260 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3261 /* user-user */
3262 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3263 user.fields |= MNCC_F_USERUSER;
3264 decode_useruser(&user.useruser,
3265 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3266 }
3267 /* more data */
3268 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3269 user.more = 1;
3270
3271 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3272}
3273
3274static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3275{
3276 struct gsm_mncc *mode = arg;
3277
3278 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3279}
3280
3281static struct downstate {
3282 u_int32_t states;
3283 int type;
3284 int (*rout) (struct gsm_trans *trans, void *arg);
3285} downstatelist[] = {
3286 /* mobile originating call establishment */
3287 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3288 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3289 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3290 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3291 {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 */
3292 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3293 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3294 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3295 /* mobile terminating call establishment */
3296 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3297 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3298 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3299 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3300 /* signalling during call */
3301 {SBIT(GSM_CSTATE_ACTIVE),
3302 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3303 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3304 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3305 {ALL_STATES,
3306 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3307 {ALL_STATES,
3308 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3309 {ALL_STATES,
3310 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3311 {SBIT(GSM_CSTATE_ACTIVE),
3312 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3313 {SBIT(GSM_CSTATE_ACTIVE),
3314 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3315 {SBIT(GSM_CSTATE_ACTIVE),
3316 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3317 {SBIT(GSM_CSTATE_ACTIVE),
3318 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3319 {SBIT(GSM_CSTATE_ACTIVE),
3320 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3321 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3322 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3323 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3324 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3325 {SBIT(GSM_CSTATE_ACTIVE),
3326 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3327 /* clearing */
3328 {SBIT(GSM_CSTATE_INITIATED),
3329 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3330 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3331 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3332 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3333 MNCC_REL_REQ, gsm48_cc_tx_release},
3334 /* special */
3335 {ALL_STATES,
3336 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3337};
3338
3339#define DOWNSLLEN \
3340 (sizeof(downstatelist) / sizeof(struct downstate))
3341
3342
3343int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3344{
3345 int i, j, k, l, rc = 0;
3346 struct gsm_trans *trans = NULL, *transt;
3347 struct gsm_subscriber *subscr;
3348 struct gsm_lchan *lchan = NULL, *lchant;
3349 struct gsm_bts *bts = NULL;
3350 struct gsm_bts_trx *trx;
3351 struct gsm_bts_trx_ts *ts;
3352 struct gsm_mncc *data = arg, rel;
3353
3354 /* handle special messages */
3355 switch(msg_type) {
3356 case MNCC_BRIDGE:
3357 return tch_bridge(net, arg);
3358 case MNCC_FRAME_DROP:
3359 return tch_recv(net, arg, 0);
3360 case MNCC_FRAME_RECV:
3361 return tch_recv(net, arg, 1);
3362 case GSM_TRAU_FRAME:
3363 return tch_frame(net, arg);
3364 }
3365
3366 memset(&rel, 0, sizeof(struct gsm_mncc));
3367 rel.callref = data->callref;
3368
3369 /* Find callref */
3370 trans = get_trans_ref(net, data->callref);
3371
3372 /* Callref unknown */
3373 if (!trans) {
Andreas Eversbergc079be42009-06-15 23:22:09 +02003374 if (msg_type != MNCC_SETUP_REQ ||
3375 (!data->called.number[0] && !data->imsi[0])) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003376 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3377 "Received '%s' from MNCC with "
3378 "unknown callref %d\n", data->called.number,
3379 get_mncc_name(msg_type), data->callref);
3380 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003381 return mncc_release_ind(net, NULL, data->callref,
3382 GSM48_CAUSE_LOC_PRN_S_LU,
3383 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003384 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003385 if (!data->called.number[0] && !data->imsi[0]) {
3386 DEBUGP(DCC, "(bts - trx - ts - ti) "
3387 "Received '%s' from MNCC with "
3388 "no number or IMSI\n", get_mncc_name(msg_type));
3389 /* Invalid number */
3390 return mncc_release_ind(net, NULL, data->callref,
3391 GSM48_CAUSE_LOC_PRN_S_LU,
3392 GSM48_CC_CAUSE_INV_NR_FORMAT);
3393 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003394 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003395 if (data->called.number[0])
3396 subscr = subscr_get_by_extension(data->called.number);
3397 else
3398 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003399 /* If subscriber is not found */
3400 if (!subscr) {
3401 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3402 "Received '%s' from MNCC with "
3403 "unknown subscriber %s\n", data->called.number,
3404 get_mncc_name(msg_type), data->called.number);
3405 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003406 return mncc_release_ind(net, NULL, data->callref,
3407 GSM48_CAUSE_LOC_PRN_S_LU,
3408 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003409 }
3410 /* If subscriber is not "attached" */
3411 if (!subscr->lac) {
3412 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3413 "Received '%s' from MNCC with "
3414 "detached subscriber %s\n", data->called.number,
3415 get_mncc_name(msg_type), data->called.number);
3416 subscr_put(subscr);
3417 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003418 return mncc_release_ind(net, NULL, data->callref,
3419 GSM48_CAUSE_LOC_PRN_S_LU,
3420 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003421 }
3422 /* Create transaction */
3423 if (!(trans = calloc(1, sizeof(struct gsm_trans)))) {
3424 DEBUGP(DCC, "No memory for trans.\n");
3425 subscr_put(subscr);
3426 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003427 mncc_release_ind(net, NULL, data->callref,
3428 GSM48_CAUSE_LOC_PRN_S_LU,
3429 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003430 return -ENOMEM;
3431 }
3432 trans->callref = data->callref;
3433 trans->network = net;
3434 trans->transaction_id = 0xff; /* unassigned */
3435 llist_add_tail(&trans->entry, &net->trans_list);
3436 /* Assign subscriber to transaction */
3437 trans->subscr = subscr;
3438 /* Find lchan */
3439 for (i = 0; i < net->num_bts; i++) {
3440 bts = &net->bts[i];
3441 for (j = 0; j < bts->num_trx; j++) {
3442 trx = &bts->trx[j];
3443 for (k = 0; k < TRX_NR_TS; k++) {
3444 ts = &trx->ts[k];
3445 for (l = 0; l < TS_MAX_LCHAN; l++) {
3446 lchant = &ts->lchan[l];
3447 if (lchant->subscr == subscr) {
3448 lchan = lchant;
3449 break;
3450 }
3451 }
3452 }
3453 }
3454 }
3455
3456 /* If subscriber has no lchan */
3457 if (!lchan) {
3458 /* find transaction with this subscriber already paging */
3459 llist_for_each_entry(transt, &net->trans_list, entry) {
3460 /* Transaction of our lchan? */
3461 if (transt == trans ||
3462 transt->subscr != subscr)
3463 continue;
3464 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3465 "Received '%s' from MNCC with "
3466 "unallocated channel, paging already "
3467 "started.\n", bts->nr,
3468 data->called.number,
3469 get_mncc_name(msg_type));
3470 return 0;
3471 }
3472 /* store setup informations until paging was successfull */
3473 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3474 /* start paging subscriber on all BTS with her location */
3475 subscr->net = net;
3476 bts = NULL;
3477 do {
3478 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3479 if (!bts)
3480 break;
3481 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3482 "Received '%s' from MNCC with "
3483 "unallocated channel, paging.\n",
3484 bts->nr, data->called.number,
3485 get_mncc_name(msg_type));
3486 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003487 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003488 setup_trig_pag_evt, subscr);
3489 } while (1);
3490 return 0;
3491 }
3492 /* Assign lchan */
3493 trans->lchan = lchan;
3494 use_lchan(lchan);
3495 }
3496 lchan = trans->lchan;
3497
3498 /* if paging did not respond yet */
3499 if (!lchan) {
3500 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3501 "Received '%s' from MNCC in paging state\n",
3502 (trans->subscr)?(trans->subscr->extension):"-",
3503 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003504 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3505 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003506 if (msg_type == MNCC_REL_REQ)
3507 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3508 else
3509 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3510 trans->callref = 0;
3511 free_trans(trans);
3512 return rc;
3513 }
3514
3515 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3516 "Received '%s' from MNCC in state %d (%s)\n",
3517 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3518 trans->transaction_id,
3519 (lchan->subscr)?(lchan->subscr->extension):"-",
3520 get_mncc_name(msg_type), trans->state,
3521 cc_state_names[trans->state]);
3522
3523 /* Find function for current state and message */
3524 for (i = 0; i < DOWNSLLEN; i++)
3525 if ((msg_type == downstatelist[i].type)
3526 && ((1 << trans->state) & downstatelist[i].states))
3527 break;
3528 if (i == DOWNSLLEN) {
3529 DEBUGP(DCC, "Message unhandled at this state.\n");
3530 return 0;
3531 }
3532
3533 rc = downstatelist[i].rout(trans, arg);
3534
3535 return rc;
3536}
3537
3538
3539static struct datastate {
3540 u_int32_t states;
3541 int type;
3542 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3543} datastatelist[] = {
3544 /* mobile originating call establishment */
3545 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3546 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3547 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3548 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3549 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3550 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3551 /* mobile terminating call establishment */
3552 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3553 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3554 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3555 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3556 {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 */
3557 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3558 /* signalling during call */
3559 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3560 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3561 {SBIT(GSM_CSTATE_ACTIVE),
3562 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3563 {ALL_STATES,
3564 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3565 {ALL_STATES,
3566 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3567 {ALL_STATES,
3568 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3569 {SBIT(GSM_CSTATE_ACTIVE),
3570 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3571 {SBIT(GSM_CSTATE_ACTIVE),
3572 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3573 {SBIT(GSM_CSTATE_ACTIVE),
3574 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3575 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3576 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3577 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3578 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3579 {SBIT(GSM_CSTATE_ACTIVE),
3580 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3581 /* clearing */
3582 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3583 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3584 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3585 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3586 {ALL_STATES, /* 5.4.3.4 */
3587 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3588};
3589
3590#define DATASLLEN \
3591 (sizeof(datastatelist) / sizeof(struct datastate))
3592
Harald Welte4bc90a12008-12-27 16:32:52 +00003593static int gsm0408_rcv_cc(struct msgb *msg)
3594{
3595 struct gsm48_hdr *gh = msgb_l3(msg);
3596 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003597 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3598 struct gsm_lchan *lchan = msg->lchan;
3599 struct gsm_trans *trans = NULL, *transt;
3600 struct gsm_network *net = lchan->ts->trx->bts->network;
3601 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003602
Harald Welte4bfdfe72009-06-10 23:11:52 +08003603 if (msg_type & 0x80) {
3604 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3605 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003606 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003607
3608 /* Find transaction */
3609 llist_for_each_entry(transt, &net->trans_list, entry) {
3610 /* Transaction of our lchan? */
3611 if (transt->lchan == lchan
3612 && transt->transaction_id == transaction_id) {
3613 trans = transt;
3614 }
3615 }
3616
3617 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3618 "Received '%s' from MS in state %d (%s)\n",
3619 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3620 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3621 cc_msg_names[msg_type], trans?(trans->state):0,
3622 cc_state_names[trans?(trans->state):0]);
3623
3624 /* Create transaction */
3625 if (!trans) {
3626 DEBUGP(DCC, "Unknown transaction ID %02x, "
3627 "creating new trans.\n", transaction_id);
3628 /* Create transaction */
3629 if (!(trans = calloc(1, sizeof(struct gsm_trans)))) {
3630 DEBUGP(DCC, "No memory for trans.\n");
3631 rc = gsm48_tx_simple(msg->lchan,
3632 GSM48_PDISC_CC | transaction_id,
3633 GSM48_MT_CC_RELEASE_COMPL);
3634 return -ENOMEM;
3635 }
3636 llist_add_tail(&trans->entry, &net->trans_list);
3637 /* Assign transaction */
3638 trans->callref = new_callref++;
3639 trans->network = net;
3640 trans->transaction_id = transaction_id;
3641 trans->lchan = lchan;
3642 use_lchan(lchan);
3643 if (lchan->subscr) {
3644 trans->subscr = lchan->subscr;
3645 subscr_get(trans->subscr);
3646 }
3647 }
3648
3649 /* find function for current state and message */
3650 for (i = 0; i < DATASLLEN; i++)
3651 if ((msg_type == datastatelist[i].type)
3652 && ((1 << trans->state) & datastatelist[i].states))
3653 break;
3654 if (i == DATASLLEN) {
3655 DEBUGP(DCC, "Message unhandled at this state.\n");
3656 return 0;
3657 }
3658
3659 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003660
3661 return rc;
3662}
3663
Harald Welte52b1f982008-12-23 20:25:15 +00003664/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3665int gsm0408_rcvmsg(struct msgb *msg)
3666{
3667 struct gsm48_hdr *gh = msgb_l3(msg);
3668 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003669 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003670
3671 switch (pdisc) {
3672 case GSM48_PDISC_CC:
3673 rc = gsm0408_rcv_cc(msg);
3674 break;
3675 case GSM48_PDISC_MM:
3676 rc = gsm0408_rcv_mm(msg);
3677 break;
3678 case GSM48_PDISC_RR:
3679 rc = gsm0408_rcv_rr(msg);
3680 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003681 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003682 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003683 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003684 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003685 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003686 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3687 pdisc);
3688 break;
3689 default:
3690 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3691 pdisc);
3692 break;
3693 }
3694
3695 return rc;
3696}
Harald Welte8470bf22008-12-25 23:28:35 +00003697
Harald Welte8470bf22008-12-25 23:28:35 +00003698/* Section 9.1.8 / Table 9.9 */
3699struct chreq {
3700 u_int8_t val;
3701 u_int8_t mask;
3702 enum chreq_type type;
3703};
3704
3705/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3706static const struct chreq chreq_type_neci1[] = {
3707 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3708 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3709 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3710 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3711 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3712 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3713 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3714 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3715 { 0x10, 0xf0, CHREQ_T_SDCCH },
3716 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3717 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3718 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3719};
3720
3721/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3722static const struct chreq chreq_type_neci0[] = {
3723 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3724 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3725 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3726 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3727 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3728 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3729 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3730 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3731};
3732
3733static const enum gsm_chan_t ctype_by_chreq[] = {
3734 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3735 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3736 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3737 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3738 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3739 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3740 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3741 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3742 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3743 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3744 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3745 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3746};
3747
Harald Weltee14a57c2008-12-29 04:08:28 +00003748static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3749 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3750 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3751 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3752 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3753 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3754 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3755 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3756 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3757 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3758 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3759 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3760 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3761};
3762
Harald Welte8470bf22008-12-25 23:28:35 +00003763enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3764{
3765 int i;
3766 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3767
3768 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3769 const struct chreq *chr = &chreq_type_neci0[i];
3770 if ((ra & chr->mask) == chr->val)
3771 return ctype_by_chreq[chr->type];
3772 }
3773 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3774 return GSM_LCHAN_SDCCH;
3775}
Harald Weltee14a57c2008-12-29 04:08:28 +00003776
3777enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3778{
3779 int i;
3780 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3781
3782 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3783 const struct chreq *chr = &chreq_type_neci0[i];
3784 if ((ra & chr->mask) == chr->val)
3785 return reason_by_chreq[chr->type];
3786 }
3787 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3788 return GSM_CHREQ_REASON_OTHER;
3789}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003790
3791/* dequeue messages to layer 4 */
3792int bsc_upqueue(struct gsm_network *net)
3793{
3794 struct gsm_mncc *mncc;
3795 struct msgb *msg;
3796 int work = 0;
3797
3798 if (net)
3799 while ((msg = msgb_dequeue(&net->upqueue))) {
3800 mncc = (struct gsm_mncc *)msg->data;
3801 if (net->mncc_recv)
3802 net->mncc_recv(net, mncc->msg_type, mncc);
3803 work = 1; /* work done */
3804 }
3805
3806 return work;
3807}