blob: d6f131e231c623663baea91b4c072bdee8515354 [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 Welte2cf161b2009-06-20 22:36:41 +020047#include <openbsc/talloc.h>
Harald Welte52b1f982008-12-23 20:25:15 +000048
Harald Welte8470bf22008-12-25 23:28:35 +000049#define GSM48_ALLOC_SIZE 1024
50#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000051
Harald Welte0c389302009-06-10 12:08:54 +080052#define GSM_MAX_FACILITY 128
53#define GSM_MAX_SSVERSION 128
54#define GSM_MAX_USERUSER 128
55
Harald Welte2cf161b2009-06-20 22:36:41 +020056static void *tall_locop_ctx;
57static void *tall_trans_ctx;
58
Harald Welte09e38af2009-02-16 22:52:23 +000059static const struct tlv_definition rsl_att_tlvdef = {
60 .def = {
61 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
62 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
63 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
64 [GSM48_IE_UTC] = { TLV_TYPE_TV },
65 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
66 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
67
68 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
69 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
70 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
71 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
72 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
73 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
74 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080075 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000076 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
77 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080078 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
79 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000080 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
81 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
82 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
83 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
84 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
86 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
87 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
88 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
89 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
90 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
91 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
92 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
93 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080094 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
95 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +000096 /* FIXME: more elements */
97 },
98};
Harald Weltecf5b3592009-05-01 18:28:42 +000099
100static const char *rr_cause_names[] = {
101 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
102 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
103 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
104 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
105 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
106 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
107 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
108 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
109 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
110 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
111 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
112 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
113 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
114 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
115 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
116 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
117 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
118};
119
Harald Welte4bfdfe72009-06-10 23:11:52 +0800120static const char *cc_state_names[] = {
121 "NULL",
122 "INITIATED",
123 "illegal state 2",
124 "MO_CALL_PROC",
125 "CALL_DELIVERED",
126 "illegal state 5",
127 "CALL_PRESENT",
128 "CALL_RECEIVED",
129 "CONNECT_REQUEST",
130 "MO_TERM_CALL_CONF",
131 "ACTIVE",
132 "DISCONNECT_REQ",
133 "DISCONNECT_IND",
134 "illegal state 13",
135 "illegal state 14",
136 "illegal state 15",
137 "illegal state 16",
138 "illegal state 17",
139 "illegal state 18",
140 "RELEASE_REQ",
141 "illegal state 20",
142 "illegal state 21",
143 "illegal state 22",
144 "illegal state 23",
145 "illegal state 24",
146 "illegal state 25",
147 "MO_ORIG_MODIFY",
148 "MO_TERM_MODIFY",
149 "CONNECT_IND",
150 "illegal state 29",
151 "illegal state 30",
152 "illegal state 31",
153};
154
155static const char *cc_msg_names[] = {
156 "unknown 0x00",
157 "ALERTING",
158 "CALL_PROC",
159 "PROGRESS",
160 "ESTAB",
161 "SETUP",
162 "ESTAB_CONF",
163 "CONNECT",
164 "CALL_CONF",
165 "START_CC",
166 "unknown 0x0a",
167 "RECALL",
168 "unknown 0x0c",
169 "unknown 0x0d",
170 "EMERG_SETUP",
171 "CONNECT_ACK",
172 "USER_INFO",
173 "unknown 0x11",
174 "unknown 0x12",
175 "MODIFY_REJECT",
176 "unknown 0x14",
177 "unknown 0x15",
178 "unknown 0x16",
179 "MODIFY",
180 "HOLD",
181 "HOLD_ACK",
182 "HOLD_REJ",
183 "unknown 0x1b",
184 "RETR",
185 "RETR_ACK",
186 "RETR_REJ",
187 "MODIFY_COMPL",
188 "unknown 0x20",
189 "unknown 0x21",
190 "unknown 0x22",
191 "unknown 0x23",
192 "unknown 0x24",
193 "DISCONNECT",
194 "unknown 0x26",
195 "unknown 0x27",
196 "unknown 0x28",
197 "unknown 0x29",
198 "RELEASE_COMPL",
199 "unknown 0x2b",
200 "unknown 0x2c",
201 "RELEASE",
202 "unknown 0x2e",
203 "unknown 0x2f",
204 "unknown 0x30",
205 "STOP_DTMF",
206 "STOP_DTMF_ACK",
207 "unknown 0x33",
208 "STATUS_ENQ",
209 "START_DTMF",
210 "START_DTMF_ACK",
211 "START_DTMF_REJ",
212 "unknown 0x38",
213 "CONG_CTRL",
214 "FACILITY",
215 "unknown 0x3b",
216 "STATUS",
217 "unknown 0x3c",
218 "NOTIFY",
219 "unknown 0x3f",
220};
221
Harald Weltecf5b3592009-05-01 18:28:42 +0000222static char strbuf[64];
223
224static const char *rr_cause_name(u_int8_t cause)
225{
226 if (cause < ARRAY_SIZE(rr_cause_names) &&
227 rr_cause_names[cause])
228 return rr_cause_names[cause];
229
230 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
231 return strbuf;
232}
233
Harald Weltef7c43522009-06-09 20:24:21 +0000234static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
235 int len)
236{
237 memset(rep, 0, sizeof(*rep));
238
239 if (data[0] & 0x80)
240 rep->flags |= MEAS_REP_F_BA1;
241 if (data[0] & 0x40)
242 rep->flags |= MEAS_REP_F_DTX;
243 if (data[1] & 0x40)
244 rep->flags |= MEAS_REP_F_VALID;
245
246 rep->rxlev_full = data[0] & 0x3f;
247 rep->rxlev_sub = data[1] & 0x3f;
248 rep->rxqual_full = (data[3] >> 4) & 0x7;
249 rep->rxqual_sub = (data[3] >> 1) & 0x7;
250 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
251 if (rep->num_cell < 1)
252 return;
253
254 /* an encoding nightmare in perfection */
255
256 rep->cell[0].rxlev = data[4] & 0x3f;
257 rep->cell[0].bcch_freq = data[5] >> 2;
258 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
259 if (rep->num_cell < 2)
260 return;
261
262 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
263 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
264 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
265 if (rep->num_cell < 3)
266 return;
267
268 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
269 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
270 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
271 if (rep->num_cell < 4)
272 return;
273
274 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
275 rep->cell[3].bcch_freq = data[11] & 0x1f;
276 rep->cell[3].bsic = data[12] >> 2;
277 if (rep->num_cell < 5)
278 return;
279
280 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
281 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
282 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
283 if (rep->num_cell < 6)
284 return;
285
286 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
287 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
288 rep->cell[5].bsic = data[16] & 0x3f;
289}
290
Holger Freytherd51524f2009-06-09 08:27:07 +0000291int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000292static int gsm48_tx_simple(struct gsm_lchan *lchan,
293 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000294static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800295void free_trans(struct gsm_trans *trans);
Harald Welte65e74cc2008-12-29 01:55:35 +0000296
Harald Welte52b1f982008-12-23 20:25:15 +0000297struct gsm_lai {
298 u_int16_t mcc;
299 u_int16_t mnc;
300 u_int16_t lac;
301};
302
Holger Freyther89824fc2008-12-30 16:18:18 +0000303static int authorize_everonye = 0;
304void gsm0408_allow_everyone(int everyone)
305{
306 printf("Allowing everyone?\n");
307 authorize_everonye = everyone;
308}
309
Holger Freythere97f7fb2008-12-31 18:52:11 +0000310static int reject_cause = 0;
311void gsm0408_set_reject_cause(int cause)
312{
313 reject_cause = cause;
314}
315
Harald Welte4bfdfe72009-06-10 23:11:52 +0800316static u_int32_t new_callref = 0x80000001;
317
Holger Freyther73487a22008-12-31 18:53:57 +0000318static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
319 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000320{
321 if (!subscriber)
322 return 0;
323
Holger Freyther73487a22008-12-31 18:53:57 +0000324 /*
325 * Do not send accept yet as more information should arrive. Some
326 * phones will not send us the information and we will have to check
327 * what we want to do with that.
328 */
329 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
330 return 0;
331
Holger Freyther89824fc2008-12-30 16:18:18 +0000332 if (authorize_everonye)
333 return 1;
334
335 return subscriber->authorized;
336}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000337
Holger Freyther73487a22008-12-31 18:53:57 +0000338static void release_loc_updating_req(struct gsm_lchan *lchan)
339{
Harald Welte179f0642008-12-31 23:59:18 +0000340 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000341 return;
342
Harald Welteff117a82009-05-23 05:22:08 +0000343 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200344 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000345 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000346 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000347}
348
349static void allocate_loc_updating_req(struct gsm_lchan *lchan)
350{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000351 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000352 release_loc_updating_req(lchan);
353
Harald Welte2cf161b2009-06-20 22:36:41 +0200354 if (!tall_locop_ctx)
355 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
356 "loc_updating_oper");
357 lchan->loc_operation = talloc(tall_locop_ctx,
358 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000359 memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
360}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000361
Holger Freytherd51524f2009-06-09 08:27:07 +0000362static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
363{
364 u_int32_t tmsi;
365
366 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
367 db_subscriber_alloc_tmsi(lchan->subscr);
368 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
369 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
370 release_loc_updating_req(lchan);
371 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
372 }
373
374 return 0;
375}
376
Holger Freyther7c19f742009-06-06 13:54:35 +0000377static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
378 void *handler_data, void *signal_data)
379{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800380 struct gsm_trans *trans, *temp;
381
Holger Freyther7c19f742009-06-06 13:54:35 +0000382 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
383 return 0;
384
385 /*
386 * Cancel any outstanding location updating request
387 * operation taking place on the lchan.
388 */
389 struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200390 if (!lchan)
391 return 0;
392
Holger Freyther7c19f742009-06-06 13:54:35 +0000393 release_loc_updating_req(lchan);
394
Harald Welte4bfdfe72009-06-10 23:11:52 +0800395 /* Free all transactions that are associated with the released lchan */
396 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
397 if (trans->lchan == lchan)
398 free_trans(trans);
399 }
400
Holger Freyther7c19f742009-06-06 13:54:35 +0000401 return 0;
402}
403
404/*
405 * This will be ran by the linker when loading the DSO. We use it to
406 * do system initialization, e.g. registration of signal handlers.
407 */
408static __attribute__((constructor)) void on_dso_load_0408(void)
409{
410 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
411}
412
Harald Welte52b1f982008-12-23 20:25:15 +0000413static void to_bcd(u_int8_t *bcd, u_int16_t val)
414{
Harald Welte4b634542008-12-27 01:55:51 +0000415 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000416 val = val / 10;
417 bcd[1] = val % 10;
418 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000419 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000420 val = val / 10;
421}
422
Holger Freyther17746612008-12-28 16:32:44 +0000423void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000424 u_int16_t mnc, u_int16_t lac)
425{
426 u_int8_t bcd[3];
427
428 to_bcd(bcd, mcc);
429 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
430 lai48->digits[1] = bcd[2];
431
432 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000433 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
434#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000435 lai48->digits[1] |= bcd[2] << 4;
436 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000437#else
438 lai48->digits[1] |= 0xf << 4;
439 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
440#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000441
Harald Welte4b634542008-12-27 01:55:51 +0000442 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000443}
444
Harald Welte255539c2008-12-28 02:26:27 +0000445#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000446#define MID_TMSI_LEN (TMSI_LEN + 2)
447
Harald Welte255539c2008-12-28 02:26:27 +0000448int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000449{
Harald Welte65e74cc2008-12-29 01:55:35 +0000450 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000451
Harald Welte4b634542008-12-27 01:55:51 +0000452 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000453 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000454 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000455 *tptr = htonl(tmsi);
456
457 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000458}
459
Harald Welte09e38af2009-02-16 22:52:23 +0000460static const char bcd_num_digits[] = {
461 '0', '1', '2', '3', '4', '5', '6', '7',
462 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
463};
464
Harald Welte0c389302009-06-10 12:08:54 +0800465/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
466int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
467 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000468{
469 u_int8_t in_len = bcd_lv[0];
470 int i;
471
Harald Welte0c389302009-06-10 12:08:54 +0800472 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000473 /* lower nibble */
474 output_len--;
475 if (output_len <= 1)
476 break;
477 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
478
479 /* higher nibble */
480 output_len--;
481 if (output_len <= 1)
482 break;
483 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
484 }
485 if (output_len >= 1)
486 *output++ = '\0';
487
Harald Welte0c389302009-06-10 12:08:54 +0800488 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000489}
490
491/* convert a single ASCII character to call-control BCD */
492static int asc_to_bcd(const char asc)
493{
494 int i;
495
496 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
497 if (bcd_num_digits[i] == asc)
498 return i;
499 }
500 return -EINVAL;
501}
502
Harald Welte0c389302009-06-10 12:08:54 +0800503/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000504int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800505 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000506{
507 int in_len = strlen(input);
508 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800509 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000510
511 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800512 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000513 if (in_len % 2)
514 bcd_lv[0]++;
515
Harald Welte0c389302009-06-10 12:08:54 +0800516 if (bcd_lv[0] > max_len)
517 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000518
519 for (i = 0; i < in_len; i++) {
520 int rc = asc_to_bcd(input[i]);
521 if (rc < 0)
522 return rc;
523 if (i % 2 == 0)
524 *bcd_cur = rc;
525 else
526 *bcd_cur++ |= (rc << 4);
527 }
528 /* append padding nibble in case of odd length */
529 if (i % 2)
530 *bcd_cur++ |= 0xf0;
531
532 /* return how many bytes we used */
533 return (bcd_cur - bcd_lv);
534}
535
Harald Welte0c389302009-06-10 12:08:54 +0800536/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800537static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800538 const u_int8_t *lv)
539{
540 u_int8_t in_len = lv[0];
541 int i, s;
542
543 if (in_len < 1)
544 return -EINVAL;
545
Harald Welte4bfdfe72009-06-10 23:11:52 +0800546 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800547
548 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800549 bcap->transfer = lv[1] & 0x07;
550 bcap->mode = (lv[1] & 0x08) >> 3;
551 bcap->coding = (lv[1] & 0x10) >> 4;
552 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800553
554 i = 1;
555 s = 0;
556 while(!(lv[i] & 0x80)) {
557 i++; /* octet 3a etc */
558 if (in_len < i)
559 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800560 bcap->speech_ver[s++] = lv[i] & 0x0f;
561 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800562 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800563 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800564 if (s == 7) /* maximum speech versions + end of list */
565 return 0;
566 }
567
568 return 0;
569}
570
571/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800572static int encode_bearer_cap(struct msgb *msg, int lv_only,
573 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800574{
575 u_int8_t lv[32 + 1];
576 int i, s;
577
Harald Welte4bfdfe72009-06-10 23:11:52 +0800578 lv[1] = bcap->transfer;
579 lv[1] |= bcap->mode << 3;
580 lv[1] |= bcap->coding << 4;
581 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800582
583 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800584 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800585 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800586 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800587 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800588 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800589 }
590 lv[i] |= 0x80; /* last IE of octet 3 etc */
591
592 lv[0] = i;
593 if (lv_only)
594 msgb_lv_put(msg, lv[0], lv+1);
595 else
596 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
597
598 return 0;
599}
600
601/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800602static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800603{
604 u_int8_t in_len = lv[0];
605
606 if (in_len < 1)
607 return -EINVAL;
608
609 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800610 ccap->dtmf = lv[1] & 0x01;
611 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800612
613 return 0;
614}
615
616/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800617static int decode_called(struct gsm_mncc_number *called,
618 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800619{
620 u_int8_t in_len = lv[0];
621
622 if (in_len < 1)
623 return -EINVAL;
624
625 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800626 called->plan = lv[1] & 0x0f;
627 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800628
629 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800630 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800631
632 return 0;
633}
634
635/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800636static int encode_called(struct msgb *msg,
637 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800638{
639 u_int8_t lv[18];
640 int ret;
641
642 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800643 lv[1] = called->plan;
644 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800645
646 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800647 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800648 if (ret < 0)
649 return ret;
650
651 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
652
653 return 0;
654}
655
656/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800657static int encode_callerid(struct msgb *msg, int ie,
658 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800659{
660 u_int8_t lv[13];
661 int h_len = 1;
662 int ret;
663
664 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800665 lv[1] = callerid->plan;
666 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800667
Harald Welte4bfdfe72009-06-10 23:11:52 +0800668 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800669 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800670 lv[2] = callerid->screen;
671 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800672 lv[2] |= 0x80;
673 h_len++;
674 } else
675 lv[1] |= 0x80;
676
677 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800678 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800679 if (ret < 0)
680 return ret;
681
682 msgb_tlv_put(msg, ie, lv[0], lv+1);
683
684 return 0;
685}
686
687/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800688static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800689 const u_int8_t *lv)
690{
691 u_int8_t in_len = lv[0];
692 int i;
693
694 if (in_len < 2)
695 return -EINVAL;
696
Harald Welte4bfdfe72009-06-10 23:11:52 +0800697 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800698
699 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800700 cause->location = lv[1] & 0x0f;
701 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800702
703 i = 1;
704 if (!(lv[i] & 0x80)) {
705 i++; /* octet 3a */
706 if (in_len < i+1)
707 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800708 cause->rec = 1;
709 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800710
711 }
712 i++;
713
714 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800715 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800716 i++;
717
718 if (in_len < i) /* no diag */
719 return 0;
720
721 if (in_len - (i-1) > 32) /* maximum 32 octets */
722 return 0;
723
724 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800725 memcpy(cause->diag, lv + i, in_len - (i-1));
726 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800727
728 return 0;
729}
730
731/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800732static int encode_cause(struct msgb *msg, int lv_only,
733 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800734{
735 u_int8_t lv[32+4];
736 int i;
737
Harald Welte4bfdfe72009-06-10 23:11:52 +0800738 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800739 return -EINVAL;
740
741 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800742 lv[1] = cause->location;
743 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800744
745 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800746 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800747 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800748 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800749 }
750 lv[i] |= 0x80; /* end of octet 3 */
751
752 /* octet 4 */
753 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800754 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800755
756 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800757 if (cause->diag_len) {
758 memcpy(lv + i, cause->diag, cause->diag_len);
759 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800760 }
761
762 lv[0] = i;
763 if (lv_only)
764 msgb_lv_put(msg, lv[0], lv+1);
765 else
766 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
767
768 return 0;
769}
770
771/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800772static int encode_calling(struct msgb *msg,
773 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800774{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800775 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800776}
777
778/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800779static int encode_connected(struct msgb *msg,
780 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800781{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800782 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800783}
784
785/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800786static int encode_redirecting(struct msgb *msg,
787 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800788{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800789 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800790}
791
792/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800793static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800794 const u_int8_t *lv)
795{
796 u_int8_t in_len = lv[0];
797
798 if (in_len < 1)
799 return -EINVAL;
800
Harald Welte4bfdfe72009-06-10 23:11:52 +0800801 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800802 return -EINVAL;
803
Harald Welte4bfdfe72009-06-10 23:11:52 +0800804 memcpy(facility->info, lv+1, in_len);
805 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800806
807 return 0;
808}
809
810/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800811static int encode_facility(struct msgb *msg, int lv_only,
812 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800813{
814 u_int8_t lv[GSM_MAX_FACILITY + 1];
815
Harald Welte4bfdfe72009-06-10 23:11:52 +0800816 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800817 return -EINVAL;
818
Harald Welte4bfdfe72009-06-10 23:11:52 +0800819 memcpy(lv+1, facility->info, facility->len);
820 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800821 if (lv_only)
822 msgb_lv_put(msg, lv[0], lv+1);
823 else
824 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
825
826 return 0;
827}
828
829/* decode 'notify' */
830static int decode_notify(int *notify, const u_int8_t *v)
831{
832 *notify = v[0] & 0x7f;
833
834 return 0;
835}
836
837/* encode 'notify' */
838static int encode_notify(struct msgb *msg, int notify)
839{
840 msgb_v_put(msg, notify | 0x80);
841
842 return 0;
843}
844
845/* encode 'signal' */
846static int encode_signal(struct msgb *msg, int signal)
847{
848 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
849
850 return 0;
851}
852
853/* decode 'keypad' */
854static int decode_keypad(int *keypad, const u_int8_t *lv)
855{
856 u_int8_t in_len = lv[0];
857
858 if (in_len < 1)
859 return -EINVAL;
860
861 *keypad = lv[1] & 0x7f;
862
863 return 0;
864}
865
866/* encode 'keypad' */
867static int encode_keypad(struct msgb *msg, int keypad)
868{
869 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
870
871 return 0;
872}
873
874/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800875static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800876 const u_int8_t *lv)
877{
878 u_int8_t in_len = lv[0];
879
880 if (in_len < 2)
881 return -EINVAL;
882
Harald Welte4bfdfe72009-06-10 23:11:52 +0800883 progress->coding = (lv[1] & 0x60) >> 5;
884 progress->location = lv[1] & 0x0f;
885 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800886
887 return 0;
888}
889
890/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800891static int encode_progress(struct msgb *msg, int lv_only,
892 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800893{
894 u_int8_t lv[3];
895
896 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800897 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
898 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800899 if (lv_only)
900 msgb_lv_put(msg, lv[0], lv+1);
901 else
902 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
903
904 return 0;
905}
906
907/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800908static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800909 const u_int8_t *lv)
910{
911 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800912 char *info = uu->info;
913 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800914 int i;
915
916 if (in_len < 1)
917 return -EINVAL;
918
Harald Welte4bfdfe72009-06-10 23:11:52 +0800919 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800920
921 for (i = 2; i <= in_len; i++) {
922 info_len--;
923 if (info_len <= 1)
924 break;
925 *info++ = lv[i];
926 }
927 if (info_len >= 1)
928 *info++ = '\0';
929
930 return 0;
931}
932
933/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800934static int encode_useruser(struct msgb *msg, int lv_only,
935 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800936{
937 u_int8_t lv[GSM_MAX_USERUSER + 2];
938
Harald Welte4bfdfe72009-06-10 23:11:52 +0800939 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800940 return -EINVAL;
941
Harald Welte4bfdfe72009-06-10 23:11:52 +0800942 lv[0] = 1 + strlen(uu->info);
943 lv[1] = uu->proto;
944 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800945 if (lv_only)
946 msgb_lv_put(msg, lv[0], lv+1);
947 else
948 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
949
950 return 0;
951}
952
953/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800954static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800955 const u_int8_t *lv)
956{
957 u_int8_t in_len = lv[0];
958
Harald Welte4bfdfe72009-06-10 23:11:52 +0800959 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800960 return -EINVAL;
961
Harald Welte4bfdfe72009-06-10 23:11:52 +0800962 memcpy(ssv->info, lv + 1, in_len);
963 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800964
965 return 0;
966}
967
968/* encode 'more data' */
969static int encode_more(struct msgb *msg)
970{
971 u_int8_t *ie;
972
973 ie = msgb_put(msg, 1);
974 ie[0] = GSM48_IE_MORE_DATA;
975
976 return 0;
977}
978
Holger Freyther819dd202009-01-04 03:52:50 +0000979struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000980{
Harald Welte966636f2009-06-26 19:39:35 +0200981 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
982 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000983}
984
Holger Freyther3e2c3232009-01-04 03:55:31 +0000985int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000986{
Harald Welte65e74cc2008-12-29 01:55:35 +0000987 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800988 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000989 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000990
Harald Welte4bfdfe72009-06-10 23:11:52 +0800991 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
992 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
993 "Sending '%s' to MS.\n", msg->trx->bts->nr,
994 msg->trx->nr, msg->lchan->ts->nr,
995 gh->proto_discr & 0xf0,
996 cc_msg_names[gh->msg_type & 0x3f]);
997 else
998 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
999 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1000 msg->trx->nr, msg->lchan->ts->nr,
1001 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001002 }
1003
Harald Welte4b634542008-12-27 01:55:51 +00001004 msg->l3h = msg->data;
1005
Harald Welte8470bf22008-12-25 23:28:35 +00001006 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001007}
1008
Holger Freyther429e7762008-12-30 13:28:30 +00001009/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001010int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001011{
Harald Welte8470bf22008-12-25 23:28:35 +00001012 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001013 struct gsm48_hdr *gh;
1014
Harald Welte8470bf22008-12-25 23:28:35 +00001015 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001016
1017 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1018 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001019 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001020 gh->data[0] = cause;
1021
Harald Weltedb253af2008-12-30 17:56:55 +00001022 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1023
Harald Welte65e74cc2008-12-29 01:55:35 +00001024 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001025}
1026
1027/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001028int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001029{
Harald Welte8470bf22008-12-25 23:28:35 +00001030 struct gsm_bts *bts = lchan->ts->trx->bts;
1031 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001032 struct gsm48_hdr *gh;
1033 struct gsm48_loc_area_id *lai;
1034 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001035 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001036
Harald Welte8470bf22008-12-25 23:28:35 +00001037 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001038
1039 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1040 gh->proto_discr = GSM48_PDISC_MM;
1041 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1042
1043 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001044 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001045 bts->network->network_code, bts->location_area_code);
1046
1047 mid = msgb_put(msg, MID_TMSI_LEN);
1048 generate_mid_from_tmsi(mid, tmsi);
1049
1050 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1051
Harald Weltedb253af2008-12-30 17:56:55 +00001052 ret = gsm48_sendmsg(msg);
1053
Harald Weltedb253af2008-12-30 17:56:55 +00001054 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001055
Holger Freyther07cc8d82008-12-29 06:23:46 +00001056 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001057}
1058
Harald Weltefc977a82008-12-27 10:19:37 +00001059static char bcd2char(u_int8_t bcd)
1060{
1061 if (bcd < 0xa)
1062 return '0' + bcd;
1063 else
1064 return 'A' + (bcd - 0xa);
1065}
1066
Harald Weltebf5e8df2009-02-03 12:59:45 +00001067/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001068static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1069{
1070 int i;
1071 u_int8_t mi_type;
1072 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001073 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001074
1075 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1076
1077 switch (mi_type) {
1078 case GSM_MI_TYPE_NONE:
1079 break;
1080 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001081 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1082 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1083 memcpy(&tmsi, &mi[1], 4);
1084 tmsi = ntohl(tmsi);
1085 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001086 }
1087 break;
1088 case GSM_MI_TYPE_IMSI:
1089 case GSM_MI_TYPE_IMEI:
1090 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001091 *str_cur++ = bcd2char(mi[0] >> 4);
1092
1093 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001094 if (str_cur + 2 >= string + str_len)
1095 return str_cur - string;
1096 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001097 /* skip last nibble in last input byte when GSM_EVEN */
1098 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1099 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001100 }
1101 break;
1102 default:
1103 break;
1104 }
Harald Weltefc977a82008-12-27 10:19:37 +00001105 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001106
Harald Weltefc977a82008-12-27 10:19:37 +00001107 return str_cur - string;
1108}
1109
Harald Weltebf5e8df2009-02-03 12:59:45 +00001110/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001111static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1112{
1113 struct msgb *msg = gsm48_msgb_alloc();
1114 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001115
Harald Welte231ad4f2008-12-27 11:15:38 +00001116 msg->lchan = lchan;
1117
1118 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1119 gh->proto_discr = GSM48_PDISC_MM;
1120 gh->msg_type = GSM48_MT_MM_ID_REQ;
1121 gh->data[0] = id_type;
1122
Harald Welte65e74cc2008-12-29 01:55:35 +00001123 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001124}
1125
1126#define MI_SIZE 32
1127
Harald Weltebf5e8df2009-02-03 12:59:45 +00001128/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001129static int mm_rx_id_resp(struct msgb *msg)
1130{
1131 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001132 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001133 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1134 char mi_string[MI_SIZE];
1135
1136 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001137 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001138 mi_type, mi_string);
1139
Harald Welte75a983f2008-12-27 21:34:06 +00001140 switch (mi_type) {
1141 case GSM_MI_TYPE_IMSI:
1142 if (!lchan->subscr)
1143 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001144 if (lchan->loc_operation)
1145 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001146 break;
1147 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001148 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001149 /* update subscribe <-> IMEI mapping */
1150 if (lchan->subscr)
1151 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001152 if (lchan->loc_operation)
1153 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001154 break;
1155 }
Holger Freyther73487a22008-12-31 18:53:57 +00001156
1157 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001158 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001159}
1160
Harald Welte255539c2008-12-28 02:26:27 +00001161
1162static void loc_upd_rej_cb(void *data)
1163{
1164 struct gsm_lchan *lchan = data;
1165
Holger Freyther73487a22008-12-31 18:53:57 +00001166 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001167 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001168 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001169}
1170
Holger Freytherb7193e42008-12-29 17:44:08 +00001171static void schedule_reject(struct gsm_lchan *lchan)
1172{
Holger Freyther73487a22008-12-31 18:53:57 +00001173 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1174 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001175 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001176}
1177
Harald Welte2a139372009-02-22 21:14:55 +00001178static const char *lupd_name(u_int8_t type)
1179{
1180 switch (type) {
1181 case GSM48_LUPD_NORMAL:
1182 return "NORMAL";
1183 case GSM48_LUPD_PERIODIC:
1184 return "PEROIDOC";
1185 case GSM48_LUPD_IMSI_ATT:
1186 return "IMSI ATTACH";
1187 default:
1188 return "UNKNOWN";
1189 }
1190}
1191
Harald Welte231ad4f2008-12-27 11:15:38 +00001192#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001193/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001194static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001195{
Harald Welte8470bf22008-12-25 23:28:35 +00001196 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001197 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001198 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001199 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001200 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001201 char mi_string[MI_SIZE];
1202 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001203
Harald Welte8470bf22008-12-25 23:28:35 +00001204 lu = (struct gsm48_loc_upd_req *) gh->data;
1205
1206 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001207
Harald Weltefc977a82008-12-27 10:19:37 +00001208 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1209
Holger Freyther79f4ae62009-06-02 03:25:04 +00001210 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001211 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001212
Holger Freythereaf04692009-06-06 13:54:44 +00001213 /*
1214 * Pseudo Spoof detection: Just drop a second/concurrent
1215 * location updating request.
1216 */
1217 if (lchan->loc_operation) {
1218 DEBUGP(DMM, "LUPDREQ: ignoring request due an existing one: %p.\n",
1219 lchan->loc_operation);
1220 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1221 return 0;
1222 }
1223
Holger Freyther73487a22008-12-31 18:53:57 +00001224 allocate_loc_updating_req(lchan);
1225
Harald Welte52b1f982008-12-23 20:25:15 +00001226 switch (mi_type) {
1227 case GSM_MI_TYPE_IMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001228 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001229 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001230 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001231 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001232
Harald Welte52b1f982008-12-23 20:25:15 +00001233 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001234 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001235 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001236 case GSM_MI_TYPE_TMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001237 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001238 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001239 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001240 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001241
Harald Welte52b1f982008-12-23 20:25:15 +00001242 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001243 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001244 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001245 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001246 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001247 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001248 }
1249 break;
1250 case GSM_MI_TYPE_IMEI:
1251 case GSM_MI_TYPE_IMEISV:
1252 /* no sim card... FIXME: what to do ? */
Harald Welte2a139372009-02-22 21:14:55 +00001253 DEBUGP(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001254 break;
1255 default:
Harald Welte2a139372009-02-22 21:14:55 +00001256 DEBUGP(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001257 break;
1258 }
1259
Harald Welte4bfdfe72009-06-10 23:11:52 +08001260 if (!subscr) {
1261 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1262 /* FIXME: request id? close channel? */
1263 return -EINVAL;
1264 }
1265
Harald Welte255539c2008-12-28 02:26:27 +00001266 lchan->subscr = subscr;
1267
Holger Freyther73487a22008-12-31 18:53:57 +00001268 /*
1269 * Schedule the reject timer and check if we can let the
1270 * subscriber into our network immediately or if we need to wait
1271 * for identity responses.
1272 */
1273 schedule_reject(lchan);
Holger Freytherd51524f2009-06-09 08:27:07 +00001274 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001275}
1276
Harald Welte7584aea2009-02-11 11:44:12 +00001277/* 9.1.5 Channel mode modify */
1278int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1279{
1280 struct msgb *msg = gsm48_msgb_alloc();
1281 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1282 struct gsm48_chan_mode_modify *cmm =
1283 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001284 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001285
Harald Welte4a543e82009-02-28 13:17:55 +00001286 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001287
Harald Welte45b407a2009-05-23 15:51:12 +00001288 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001289 msg->lchan = lchan;
1290 gh->proto_discr = GSM48_PDISC_RR;
1291 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1292
1293 /* fill the channel information element, this code
1294 * should probably be shared with rsl_rx_chan_rqd() */
1295 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001296 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001297 cmm->chan_desc.h0.h = 0;
1298 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1299 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1300 cmm->mode = mode;
1301
1302 return gsm48_sendmsg(msg);
1303}
1304
Harald Welte4bfdfe72009-06-10 23:11:52 +08001305#if 0
1306static u_int8_t to_bcd8(u_int8_t val)
1307{
1308 return ((val / 10) << 4) | (val % 10);
1309}
1310#endif
1311
Harald Weltedb253af2008-12-30 17:56:55 +00001312/* Section 9.2.15a */
1313int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1314{
1315 struct msgb *msg = gsm48_msgb_alloc();
1316 struct gsm48_hdr *gh;
1317 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001318 u_int8_t *ptr8;
1319 u_int16_t *ptr16;
1320 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001321 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001322#if 0
1323 time_t cur_t;
1324 struct tm* cur_time;
1325 int tz15min;
1326#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001327
1328 msg->lchan = lchan;
1329
1330 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1331 gh->proto_discr = GSM48_PDISC_MM;
1332 gh->msg_type = GSM48_MT_MM_INFO;
1333
1334 if (net->name_long) {
1335 name_len = strlen(net->name_long);
1336 /* 10.5.3.5a */
1337 ptr8 = msgb_put(msg, 3);
1338 ptr8[0] = GSM48_IE_NAME_LONG;
1339 ptr8[1] = name_len*2 +1;
1340 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1341
1342 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1343 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001344 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001345
1346 /* FIXME: Use Cell Broadcast, not UCS-2, since
1347 * UCS-2 is only supported by later revisions of the spec */
1348 }
1349
1350 if (net->name_short) {
1351 name_len = strlen(net->name_short);
1352 /* 10.5.3.5a */
1353 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1354 ptr8[0] = GSM48_IE_NAME_LONG;
1355 ptr8[1] = name_len*2 + 1;
1356 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1357
Harald Weltee872cb12009-01-01 00:33:37 +00001358 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001359 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001360 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001361 }
1362
1363#if 0
1364 /* Section 10.5.3.9 */
1365 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001366 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001367 ptr8 = msgb_put(msg, 8);
1368 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1369 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1370 ptr8[2] = to_bcd8(cur_time->tm_mon);
1371 ptr8[3] = to_bcd8(cur_time->tm_mday);
1372 ptr8[4] = to_bcd8(cur_time->tm_hour);
1373 ptr8[5] = to_bcd8(cur_time->tm_min);
1374 ptr8[6] = to_bcd8(cur_time->tm_sec);
1375 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1376 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001377 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001378 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001379 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001380#endif
1381
1382 return gsm48_sendmsg(msg);
1383}
1384
Harald Welte4b634542008-12-27 01:55:51 +00001385static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1386{
Harald Welte4b634542008-12-27 01:55:51 +00001387 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001388 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001389}
Harald Welteba4cf162009-01-10 01:49:35 +00001390
1391/* 9.2.6 CM service reject */
1392static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1393 enum gsm48_reject_value value)
1394{
1395 struct msgb *msg = gsm48_msgb_alloc();
1396 struct gsm48_hdr *gh;
1397
1398 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1399
1400 msg->lchan = lchan;
1401 use_lchan(lchan);
1402
1403 gh->proto_discr = GSM48_PDISC_MM;
1404 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1405 gh->data[0] = value;
1406 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1407
1408 return gsm48_sendmsg(msg);
1409}
1410
Harald Welte4ed0e922009-01-10 03:17:30 +00001411
1412/*
1413 * Handle CM Service Requests
1414 * a) Verify that the packet is long enough to contain the information
1415 * we require otherwsie reject with INCORRECT_MESSAGE
1416 * b) Try to parse the TMSI. If we do not have one reject
1417 * c) Check that we know the subscriber with the TMSI otherwise reject
1418 * with a HLR cause
1419 * d) Set the subscriber on the gsm_lchan and accept
1420 */
Harald Welte4b634542008-12-27 01:55:51 +00001421static int gsm48_rx_mm_serv_req(struct msgb *msg)
1422{
Harald Welteba4cf162009-01-10 01:49:35 +00001423 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001424 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001425
Harald Welteba4cf162009-01-10 01:49:35 +00001426 struct gsm_subscriber *subscr;
1427 struct gsm48_hdr *gh = msgb_l3(msg);
1428 struct gsm48_service_request *req =
1429 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001430 /* unfortunately in Phase1 the classmar2 length is variable */
1431 u_int8_t classmark2_len = gh->data[1];
1432 u_int8_t *classmark2 = gh->data+2;
1433 u_int8_t mi_len = *(classmark2 + classmark2_len);
1434 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001435
Harald Weltec9e02182009-05-01 19:07:53 +00001436 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001437 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001438 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001439 return gsm48_tx_mm_serv_rej(msg->lchan,
1440 GSM48_REJECT_INCORRECT_MESSAGE);
1441 }
1442
1443 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001444 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001445 return gsm48_tx_mm_serv_rej(msg->lchan,
1446 GSM48_REJECT_INCORRECT_MESSAGE);
1447 }
1448
Harald Weltec9e02182009-05-01 19:07:53 +00001449 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001450 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001451 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001452 return gsm48_tx_mm_serv_rej(msg->lchan,
1453 GSM48_REJECT_INCORRECT_MESSAGE);
1454 }
1455
Harald Weltec9e02182009-05-01 19:07:53 +00001456 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001457 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001458 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001459
Holger Freythereb443982009-06-04 13:58:42 +00001460 subscr = subscr_get_by_tmsi(mi_string);
1461
Harald Welte2a139372009-02-22 21:14:55 +00001462 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001463 if (!subscr)
1464 return gsm48_tx_mm_serv_rej(msg->lchan,
1465 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1466
1467 if (!msg->lchan->subscr)
1468 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001469 else if (msg->lchan->subscr != subscr) {
1470 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1471 subscr_put(subscr);
1472 }
1473
Harald Weltef7c43522009-06-09 20:24:21 +00001474 subscr->classmark2_len = classmark2_len;
1475 memcpy(subscr->classmark2, classmark2, classmark2_len);
1476
Harald Welte4b634542008-12-27 01:55:51 +00001477 return gsm48_tx_mm_serv_ack(msg->lchan);
1478}
1479
Harald Welte2a139372009-02-22 21:14:55 +00001480static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1481{
1482 struct gsm48_hdr *gh = msgb_l3(msg);
1483 struct gsm48_imsi_detach_ind *idi =
1484 (struct gsm48_imsi_detach_ind *) gh->data;
1485 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1486 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001487 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001488
1489 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1490 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1491 mi_type, mi_string);
1492
1493 switch (mi_type) {
1494 case GSM_MI_TYPE_TMSI:
1495 subscr = subscr_get_by_tmsi(mi_string);
1496 break;
1497 case GSM_MI_TYPE_IMSI:
1498 subscr = subscr_get_by_imsi(mi_string);
1499 break;
1500 case GSM_MI_TYPE_IMEI:
1501 case GSM_MI_TYPE_IMEISV:
1502 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001503 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001504 break;
1505 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001506 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001507 break;
1508 }
1509
Holger Freyther4a49e772009-04-12 05:37:29 +00001510 if (subscr) {
1511 subscr_update(subscr, msg->trx->bts,
1512 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001513 DEBUGP(DMM, "Subscriber: %s\n",
1514 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001515 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001516 } else
Harald Welte2a139372009-02-22 21:14:55 +00001517 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1518
Harald Welte2a139372009-02-22 21:14:55 +00001519 return 0;
1520}
1521
Harald Welted2a7f5a2009-06-05 20:08:20 +00001522static int gsm48_rx_mm_status(struct msgb *msg)
1523{
1524 struct gsm48_hdr *gh = msgb_l3(msg);
1525
1526 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1527
1528 return 0;
1529}
1530
Harald Weltebf5e8df2009-02-03 12:59:45 +00001531/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001532static int gsm0408_rcv_mm(struct msgb *msg)
1533{
1534 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001535 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001536
1537 switch (gh->msg_type & 0xbf) {
1538 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +00001539 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001540 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001541 break;
1542 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001543 rc = mm_rx_id_resp(msg);
1544 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001545 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001546 rc = gsm48_rx_mm_serv_req(msg);
1547 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001548 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001549 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001550 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001551 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001552 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1553 msg->lchan->subscr ?
1554 msg->lchan->subscr->imsi :
1555 "unknown subscriber");
1556 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001557 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001558 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1559 break;
1560 case GSM48_MT_MM_CM_REEST_REQ:
1561 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1562 break;
1563 case GSM48_MT_MM_AUTH_RESP:
1564 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001565 break;
1566 default:
1567 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1568 gh->msg_type);
1569 break;
1570 }
1571
1572 return rc;
1573}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001574
Harald Welte2d35ae62009-02-06 12:02:13 +00001575/* Receive a PAGING RESPONSE message from the MS */
1576static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1577{
1578 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001579 u_int8_t *classmark2_lv = gh->data + 1;
1580 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1581 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001582 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001583 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001584 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001585 int rc = 0;
1586
Harald Welte61548982009-02-22 21:26:29 +00001587 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001588 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1589 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001590 switch (mi_type) {
1591 case GSM_MI_TYPE_TMSI:
1592 subscr = subscr_get_by_tmsi(mi_string);
1593 break;
1594 case GSM_MI_TYPE_IMSI:
1595 subscr = subscr_get_by_imsi(mi_string);
1596 break;
1597 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001598
1599 if (!subscr) {
1600 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001601 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001602 return -EINVAL;
1603 }
1604 DEBUGP(DRR, "<- Channel was requested by %s\n",
1605 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001606
Harald Weltef7c43522009-06-09 20:24:21 +00001607 subscr->classmark2_len = *classmark2_lv;
1608 memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv);
1609
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001610 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001611 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001612 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001613 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1614 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001615 return -EINVAL;
1616 } else {
1617 DEBUGP(DRR, "<- Channel already owned by us\n");
1618 subscr_put(subscr);
1619 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001620 }
1621
Harald Welte595ad7b2009-02-16 22:05:44 +00001622 sig_data.subscr = subscr;
1623 sig_data.bts = msg->lchan->ts->trx->bts;
1624 sig_data.lchan = msg->lchan;
1625
1626 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001627
1628 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001629 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001630
Harald Welte7584aea2009-02-11 11:44:12 +00001631 /* FIXME: somehow signal the completion of the PAGING to
1632 * the entity that requested the paging */
1633
Harald Welte2d35ae62009-02-06 12:02:13 +00001634 return rc;
1635}
1636
Harald Weltef7c43522009-06-09 20:24:21 +00001637static int gsm48_rx_rr_classmark(struct msgb *msg)
1638{
1639 struct gsm48_hdr *gh = msgb_l3(msg);
1640 struct gsm_subscriber *subscr = msg->lchan->subscr;
1641 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1642 u_int8_t cm2_len, cm3_len = 0;
1643 u_int8_t *cm2, *cm3 = NULL;
1644
1645 DEBUGP(DRR, "CLASSMARK CHANGE ");
1646
1647 /* classmark 2 */
1648 cm2_len = gh->data[0];
1649 cm2 = &gh->data[1];
1650 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1651
1652 if (payload_len > cm2_len + 1) {
1653 /* we must have a classmark3 */
1654 if (gh->data[cm2_len+1] != 0x20) {
1655 DEBUGPC(DRR, "ERR CM3 TAG\n");
1656 return -EINVAL;
1657 }
1658 if (cm2_len > 3) {
1659 DEBUGPC(DRR, "CM2 too long!\n");
1660 return -EINVAL;
1661 }
1662
1663 cm3_len = gh->data[cm2_len+2];
1664 cm3 = &gh->data[cm2_len+3];
1665 if (cm3_len > 14) {
1666 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1667 return -EINVAL;
1668 }
1669 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1670 }
1671 if (subscr) {
1672 subscr->classmark2_len = cm2_len;
1673 memcpy(subscr->classmark2, cm2, cm2_len);
1674 if (cm3) {
1675 subscr->classmark3_len = cm3_len;
1676 memcpy(subscr->classmark3, cm3, cm3_len);
1677 }
1678 }
1679
1680 /* FIXME: store the classmark2/3 values with the equipment register */
1681
1682 return 0;
1683}
1684
Harald Weltecf5b3592009-05-01 18:28:42 +00001685static int gsm48_rx_rr_status(struct msgb *msg)
1686{
1687 struct gsm48_hdr *gh = msgb_l3(msg);
1688
1689 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1690 rr_cause_name(gh->data[0]));
1691
1692 return 0;
1693}
1694
Harald Weltef7c43522009-06-09 20:24:21 +00001695static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1696{
1697 struct gsm48_hdr *gh = msgb_l3(msg);
1698 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1699 static struct gsm_meas_rep meas_rep;
1700
1701 DEBUGP(DRR, "MEASUREMENT REPORT ");
1702 parse_meas_rep(&meas_rep, gh->data, payload_len);
1703 if (meas_rep.flags & MEAS_REP_F_DTX)
1704 DEBUGPC(DRR, "DTX ");
1705 if (meas_rep.flags & MEAS_REP_F_BA1)
1706 DEBUGPC(DRR, "BA1 ");
1707 if (!(meas_rep.flags & MEAS_REP_F_VALID))
1708 DEBUGPC(DRR, "NOT VALID ");
1709 else
1710 DEBUGPC(DRR, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
1711 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1712 meas_rep.rxqual_sub);
1713
1714 DEBUGPC(DRR, "NUM_NEIGH=%u\n", meas_rep.num_cell);
1715
1716 /* FIXME: put the results somwhere */
1717
1718 return 0;
1719}
1720
Harald Weltebf5e8df2009-02-03 12:59:45 +00001721/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001722static int gsm0408_rcv_rr(struct msgb *msg)
1723{
1724 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001725 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001726
1727 switch (gh->msg_type) {
1728 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001729 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001730 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001731 case GSM48_MT_RR_GPRS_SUSP_REQ:
1732 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1733 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001734 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001735 rc = gsm48_rr_rx_pag_resp(msg);
1736 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001737 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1738 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001739 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001740 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001741 case GSM48_MT_RR_STATUS:
1742 rc = gsm48_rx_rr_status(msg);
1743 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001744 case GSM48_MT_RR_MEAS_REP:
1745 rc = gsm48_rx_rr_meas_rep(msg);
1746 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001747 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001748 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001749 gh->msg_type);
1750 break;
1751 }
1752
Harald Welte2d35ae62009-02-06 12:02:13 +00001753 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001754}
1755
Holger Freythere64a7a32009-02-06 21:55:37 +00001756/* 7.1.7 and 9.1.7 Channel release*/
1757int gsm48_send_rr_release(struct gsm_lchan *lchan)
1758{
1759 struct msgb *msg = gsm48_msgb_alloc();
1760 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1761 u_int8_t *cause;
1762
1763 msg->lchan = lchan;
1764 gh->proto_discr = GSM48_PDISC_RR;
1765 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1766
1767 cause = msgb_put(msg, 1);
1768 cause[0] = GSM48_RR_CAUSE_NORMAL;
1769
1770 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1771 lchan->nr, lchan->type);
1772
1773 return gsm48_sendmsg(msg);
1774}
1775
Harald Welte4bc90a12008-12-27 16:32:52 +00001776/* Call Control */
1777
Harald Welte7584aea2009-02-11 11:44:12 +00001778/* The entire call control code is written in accordance with Figure 7.10c
1779 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1780 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1781 * it for voice */
1782
Harald Welte4bfdfe72009-06-10 23:11:52 +08001783static void new_cc_state(struct gsm_trans *trans, int state)
1784{
1785 if (state > 31 || state < 0)
1786 return;
1787
1788 DEBUGP(DCC, "new state %s -> %s\n",
1789 cc_state_names[trans->state], cc_state_names[state]);
1790
1791 trans->state = state;
1792}
1793
1794static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001795{
1796 struct msgb *msg = gsm48_msgb_alloc();
1797 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1798 u_int8_t *cause, *call_state;
1799
Harald Welte4bfdfe72009-06-10 23:11:52 +08001800 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1801 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001802 gh->msg_type = GSM48_MT_CC_STATUS;
1803
1804 cause = msgb_put(msg, 3);
1805 cause[0] = 2;
1806 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1807 cause[2] = 0x80 | 30; /* response to status inquiry */
1808
1809 call_state = msgb_put(msg, 1);
1810 call_state[0] = 0xc0 | 0x00;
1811
Harald Welte65e74cc2008-12-29 01:55:35 +00001812 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001813}
1814
Harald Welte6f4b7532008-12-29 00:39:37 +00001815static int gsm48_tx_simple(struct gsm_lchan *lchan,
1816 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001817{
1818 struct msgb *msg = gsm48_msgb_alloc();
1819 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1820
1821 msg->lchan = lchan;
1822
Harald Welte6f4b7532008-12-29 00:39:37 +00001823 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001824 gh->msg_type = msg_type;
1825
Harald Welte65e74cc2008-12-29 01:55:35 +00001826 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001827}
1828
Harald Welte4bfdfe72009-06-10 23:11:52 +08001829static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1830{
1831 if (bsc_timer_pending(&trans->cc_timer)) {
1832 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1833 bsc_del_timer(&trans->cc_timer);
1834 trans->Tcurrent = 0;
1835 }
1836}
1837
1838static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1839 int msg_type, struct gsm_mncc *mncc)
1840{
1841 struct msgb *msg;
1842
1843 if (trans)
1844 if (trans->lchan)
1845 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1846 "Sending '%s' to MNCC.\n",
1847 trans->lchan->ts->trx->bts->nr,
1848 trans->lchan->ts->trx->nr,
1849 trans->lchan->ts->nr, trans->transaction_id,
1850 (trans->subscr)?(trans->subscr->extension):"-",
1851 get_mncc_name(msg_type));
1852 else
1853 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1854 "Sending '%s' to MNCC.\n",
1855 (trans->subscr)?(trans->subscr->extension):"-",
1856 get_mncc_name(msg_type));
1857 else
1858 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1859 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1860
1861 mncc->msg_type = msg_type;
1862
Harald Welte966636f2009-06-26 19:39:35 +02001863 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001864 if (!msg)
1865 return -ENOMEM;
1866 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1867 msgb_enqueue(&net->upqueue, msg);
1868
1869 return 0;
1870}
1871
1872int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1873 u_int32_t callref, int location, int value)
1874{
1875 struct gsm_mncc rel;
1876
Harald Welte92f70c52009-06-12 01:54:08 +08001877 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001878 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001879 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001880 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1881}
1882
1883void free_trans(struct gsm_trans *trans)
1884{
1885 struct gsm_bts *bts;
1886
1887 gsm48_stop_cc_timer(trans);
1888
1889 /* send release to L4, if callref still exists */
1890 if (trans->callref) {
1891 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001892 mncc_release_ind(trans->network, trans, trans->callref,
1893 GSM48_CAUSE_LOC_PRN_S_LU,
1894 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001895 if (trans->state != GSM_CSTATE_NULL)
1896 new_cc_state(trans, GSM_CSTATE_NULL);
1897 }
1898
1899 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1900 /* Stop paging on all bts' */
1901 bts = NULL;
1902 do {
1903 bts = gsm_bts_by_lac(trans->subscr->net,
1904 trans->subscr->lac, bts);
1905 if (!bts)
1906 break;
1907 /* Stop paging */
1908 paging_request_stop(bts, trans->subscr, NULL);
1909 } while (1);
1910 }
1911
1912 if (trans->lchan) {
1913 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1914 put_lchan(trans->lchan);
1915 }
1916
1917 if (trans->subscr)
1918 subscr_put(trans->subscr);
1919
1920 if (trans->state != GSM_CSTATE_NULL)
1921 new_cc_state(trans, GSM_CSTATE_NULL);
1922
1923 llist_del(&trans->entry);
1924
Harald Welte2cf161b2009-06-20 22:36:41 +02001925 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001926}
1927
1928static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1929
Harald Welte09e38af2009-02-16 22:52:23 +00001930/* call-back from paging the B-end of the connection */
1931static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001932 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001933{
Harald Welte7ccf7782009-02-17 01:43:01 +00001934 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001935 struct gsm_subscriber *subscr = param;
1936 struct gsm_trans *transt, *tmp;
1937 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001938
Harald Welte09e38af2009-02-16 22:52:23 +00001939 if (hooknum != GSM_HOOK_RR_PAGING)
1940 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001941
1942 if (!subscr)
1943 return -EINVAL;
1944 net = subscr->net;
1945 if (!net) {
1946 DEBUGP(DCC, "Error Network not set!\n");
1947 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001948 }
Harald Welte7584aea2009-02-11 11:44:12 +00001949
Harald Welte4bfdfe72009-06-10 23:11:52 +08001950 /* check all tranactions (without lchan) for subscriber */
1951 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1952 if (transt->subscr != subscr || transt->lchan)
1953 continue;
1954 switch (event) {
1955 case GSM_PAGING_SUCCEEDED:
1956 if (!lchan) // paranoid
1957 break;
1958 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1959 subscr->extension);
1960 /* Assign lchan */
1961 if (!transt->lchan) {
1962 transt->lchan = lchan;
1963 use_lchan(lchan);
1964 }
1965 /* send SETUP request to called party */
1966 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1967 if (is_ipaccess_bts(lchan->ts->trx->bts))
1968 rsl_ipacc_bind(lchan);
1969 break;
1970 case GSM_PAGING_EXPIRED:
1971 DEBUGP(DCC, "Paging subscr %s expired!\n",
1972 subscr->extension);
1973 /* Temporarily out of order */
1974 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001975 GSM48_CAUSE_LOC_PRN_S_LU,
1976 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001977 transt->callref = 0;
1978 free_trans(transt);
1979 break;
1980 }
1981 }
Harald Welte09e38af2009-02-16 22:52:23 +00001982 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001983}
Harald Welte7584aea2009-02-11 11:44:12 +00001984
Harald Welte49f48b82009-02-17 15:29:33 +00001985/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001986static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001987{
Harald Welte11fa29c2009-02-19 17:24:39 +00001988 struct gsm_bts *bts = lchan->ts->trx->bts;
1989 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001990 struct gsm_bts_trx_ts *ts;
1991
Harald Welte11fa29c2009-02-19 17:24:39 +00001992 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1993 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1994 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1995
1996 if (bts->type != remote_bts->type) {
1997 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1998 return -EINVAL;
1999 }
Harald Welte49f48b82009-02-17 15:29:33 +00002000
Harald Welte11fa29c2009-02-19 17:24:39 +00002001 switch (bts->type) {
2002 case GSM_BTS_TYPE_NANOBTS_900:
2003 case GSM_BTS_TYPE_NANOBTS_1800:
2004 ts = remote_lchan->ts;
2005 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2006 lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2007
2008 ts = lchan->ts;
2009 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2010 remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2011 break;
2012 case GSM_BTS_TYPE_BS11:
2013 trau_mux_map_lchan(lchan, remote_lchan);
2014 break;
2015 default:
2016 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2017 break;
2018 }
Harald Welte49f48b82009-02-17 15:29:33 +00002019
2020 return 0;
2021}
2022
Harald Welte4bfdfe72009-06-10 23:11:52 +08002023static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002024{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002025 struct gsm_trans *trans;
2026 llist_for_each_entry(trans, &net->trans_list, entry) {
2027 if (trans->callref == callref)
2028 return trans;
2029 }
2030 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002031}
2032
Harald Welte4bfdfe72009-06-10 23:11:52 +08002033/* bridge channels of two transactions */
2034static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002035{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002036 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2037 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002038
Harald Welte4bfdfe72009-06-10 23:11:52 +08002039 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002040 return -EIO;
2041
Harald Welte4bfdfe72009-06-10 23:11:52 +08002042 if (!trans1->lchan || !trans2->lchan)
2043 return -EIO;
2044
2045 /* through-connect channel */
2046 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002047}
2048
Harald Welte4bfdfe72009-06-10 23:11:52 +08002049/* enable receive of channels to upqueue */
2050static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2051{
2052 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002053
Harald Welte4bfdfe72009-06-10 23:11:52 +08002054 /* Find callref */
2055 trans = get_trans_ref(net, data->callref);
2056 if (!trans)
2057 return -EIO;
2058 if (!trans->lchan)
2059 return 0;
2060
2061 // todo IPACCESS
2062 if (enable)
2063 return trau_recv_lchan(trans->lchan, data->callref);
2064 return trau_mux_unmap(NULL, data->callref);
2065}
2066
2067/* send a frame to channel */
2068static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2069{
2070 struct gsm_trans *trans;
2071
2072 /* Find callref */
2073 trans = get_trans_ref(net, frame->callref);
2074 if (!trans)
2075 return -EIO;
2076 if (!trans->lchan)
2077 return 0;
2078 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2079 trans->lchan->type != GSM_LCHAN_TCH_H)
2080 return 0;
2081
2082 // todo IPACCESS
2083 return trau_send_lchan(trans->lchan,
2084 (struct decoded_trau_frame *)frame->data);
2085}
2086
2087
2088static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2089{
2090 DEBUGP(DCC, "-> STATUS ENQ\n");
2091 return gsm48_cc_tx_status(trans, msg);
2092}
2093
2094static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2095static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2096
2097static void gsm48_cc_timeout(void *arg)
2098{
2099 struct gsm_trans *trans = arg;
2100 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002101 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2102 int mo_location = GSM48_CAUSE_LOC_USER;
2103 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2104 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002105 struct gsm_mncc mo_rel, l4_rel;
2106
2107 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2108 mo_rel.callref = trans->callref;
2109 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2110 l4_rel.callref = trans->callref;
2111
2112 switch(trans->Tcurrent) {
2113 case 0x303:
2114 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002115 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002116 break;
2117 case 0x310:
2118 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002119 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002120 break;
2121 case 0x313:
2122 disconnect = 1;
2123 /* unknown, did not find it in the specs */
2124 break;
2125 case 0x301:
2126 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002127 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002128 break;
2129 case 0x308:
2130 if (!trans->T308_second) {
2131 /* restart T308 a second time */
2132 gsm48_cc_tx_release(trans, &trans->cc_msg);
2133 trans->T308_second = 1;
2134 break; /* stay in release state */
2135 }
2136 free_trans(trans);
2137 return;
2138// release = 1;
2139// l4_cause = 14;
2140// break;
2141 case 0x306:
2142 release = 1;
2143 mo_cause = trans->cc_msg.cause.value;
2144 mo_location = trans->cc_msg.cause.location;
2145 break;
2146 case 0x323:
2147 disconnect = 1;
2148 break;
2149 default:
2150 release = 1;
2151 }
2152
2153 if (release && trans->callref) {
2154 /* process release towards layer 4 */
2155 mncc_release_ind(trans->network, trans, trans->callref,
2156 l4_location, l4_cause);
2157 trans->callref = 0;
2158 }
2159
2160 if (disconnect && trans->callref) {
2161 /* process disconnect towards layer 4 */
2162 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2163 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2164 }
2165
2166 /* process disconnect towards mobile station */
2167 if (disconnect || release) {
2168 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2169 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2170 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2171 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2172 mo_rel.cause.diag_len = 3;
2173
2174 if (disconnect)
2175 gsm48_cc_tx_disconnect(trans, &mo_rel);
2176 if (release)
2177 gsm48_cc_tx_release(trans, &mo_rel);
2178 }
2179
2180}
2181
2182static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2183 int sec, int micro)
2184{
2185 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2186 trans->cc_timer.cb = gsm48_cc_timeout;
2187 trans->cc_timer.data = trans;
2188 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2189 trans->Tcurrent = current;
2190}
2191
2192static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2193{
2194 struct gsm48_hdr *gh = msgb_l3(msg);
2195 u_int8_t msg_type = gh->msg_type & 0xbf;
2196 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2197 struct tlv_parsed tp;
2198 struct gsm_mncc setup;
2199
2200 memset(&setup, 0, sizeof(struct gsm_mncc));
2201 setup.callref = trans->callref;
2202 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2203 /* emergency setup is identified by msg_type */
2204 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2205 setup.emergency = 1;
2206
2207 /* use subscriber as calling party number */
2208 if (trans->subscr) {
2209 setup.fields |= MNCC_F_CALLING;
2210 strncpy(setup.calling.number, trans->subscr->extension,
2211 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002212 strncpy(setup.imsi, trans->subscr->imsi,
2213 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002214 }
2215 /* bearer capability */
2216 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2217 setup.fields |= MNCC_F_BEARER_CAP;
2218 decode_bearer_cap(&setup.bearer_cap,
2219 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2220 }
2221 /* facility */
2222 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2223 setup.fields |= MNCC_F_FACILITY;
2224 decode_facility(&setup.facility,
2225 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2226 }
2227 /* called party bcd number */
2228 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2229 setup.fields |= MNCC_F_CALLED;
2230 decode_called(&setup.called,
2231 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2232 }
2233 /* user-user */
2234 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2235 setup.fields |= MNCC_F_USERUSER;
2236 decode_useruser(&setup.useruser,
2237 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2238 }
2239 /* ss-version */
2240 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2241 setup.fields |= MNCC_F_SSVERSION;
2242 decode_ssversion(&setup.ssversion,
2243 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2244 }
2245 /* CLIR suppression */
2246 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2247 setup.clir.sup = 1;
2248 /* CLIR invocation */
2249 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2250 setup.clir.inv = 1;
2251 /* cc cap */
2252 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2253 setup.fields |= MNCC_F_CCCAP;
2254 decode_cccap(&setup.cccap,
2255 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2256 }
2257
2258 if (is_ipaccess_bts(msg->trx->bts))
2259 rsl_ipacc_bind(msg->lchan);
2260
2261 new_cc_state(trans, GSM_CSTATE_INITIATED);
2262
2263 /* indicate setup to MNCC */
2264 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2265
2266 return 0;
2267}
2268
2269static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002270{
2271 struct msgb *msg = gsm48_msgb_alloc();
2272 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002273 struct gsm_mncc *setup = arg;
2274 struct gsm_trans *transt;
2275 u_int16_t trans_id_mask = 0;
2276 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002277
Harald Welte7ccf7782009-02-17 01:43:01 +00002278 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002279
Harald Welte4bfdfe72009-06-10 23:11:52 +08002280 /* transaction id must not be assigned */
2281 if (trans->transaction_id != 0xff) { /* unasssigned */
2282 DEBUGP(DCC, "TX Setup with assigned transaction. "
2283 "This is not allowed!\n");
2284 /* Temporarily out of order */
2285 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002286 GSM48_CAUSE_LOC_PRN_S_LU,
2287 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002288 trans->callref = 0;
2289 free_trans(trans);
2290 return rc;
2291 }
2292
2293 /* Get free transaction_id */
2294 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2295 /* Transaction of our lchan? */
2296 if (transt->lchan == trans->lchan &&
2297 transt->transaction_id != 0xff)
2298 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2299 }
2300 /* Assign free transaction ID */
2301 if ((trans_id_mask & 0x007f) == 0x7f) {
2302 /* no free transaction ID */
2303 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002304 GSM48_CAUSE_LOC_PRN_S_LU,
2305 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002306 trans->callref = 0;
2307 free_trans(trans);
2308 return rc;
2309 }
2310 for (i = 0; i < 7; i++) {
2311 if ((trans_id_mask & (1 << i)) == 0) {
2312 trans->transaction_id = i << 4; /* flag = 0 */
2313 break;
2314 }
2315 }
Harald Welte49f48b82009-02-17 15:29:33 +00002316
Harald Welte4bfdfe72009-06-10 23:11:52 +08002317 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2318 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002319 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002320
Harald Welte4bfdfe72009-06-10 23:11:52 +08002321 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002322
Harald Welte4bfdfe72009-06-10 23:11:52 +08002323 /* bearer capability */
2324 if (setup->fields & MNCC_F_BEARER_CAP)
2325 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2326 /* facility */
2327 if (setup->fields & MNCC_F_FACILITY)
2328 encode_facility(msg, 0, &setup->facility);
2329 /* progress */
2330 if (setup->fields & MNCC_F_PROGRESS)
2331 encode_progress(msg, 0, &setup->progress);
2332 /* calling party BCD number */
2333 if (setup->fields & MNCC_F_CALLING)
2334 encode_calling(msg, &setup->calling);
2335 /* called party BCD number */
2336 if (setup->fields & MNCC_F_CALLED)
2337 encode_called(msg, &setup->called);
2338 /* user-user */
2339 if (setup->fields & MNCC_F_USERUSER)
2340 encode_useruser(msg, 0, &setup->useruser);
2341 /* redirecting party BCD number */
2342 if (setup->fields & MNCC_F_REDIRECTING)
2343 encode_redirecting(msg, &setup->redirecting);
2344 /* signal */
2345 if (setup->fields & MNCC_F_SIGNAL)
2346 encode_signal(msg, setup->signal);
2347
2348 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002349
2350 return gsm48_sendmsg(msg);
2351}
2352
Harald Welte4bfdfe72009-06-10 23:11:52 +08002353static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2354{
2355 struct gsm48_hdr *gh = msgb_l3(msg);
2356 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2357 struct tlv_parsed tp;
2358 struct gsm_mncc call_conf;
2359
2360 gsm48_stop_cc_timer(trans);
2361 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2362
2363 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2364 call_conf.callref = trans->callref;
2365 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2366#if 0
2367 /* repeat */
2368 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2369 call_conf.repeat = 1;
2370 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2371 call_conf.repeat = 2;
2372#endif
2373 /* bearer capability */
2374 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2375 call_conf.fields |= MNCC_F_BEARER_CAP;
2376 decode_bearer_cap(&call_conf.bearer_cap,
2377 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2378 }
2379 /* cause */
2380 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2381 call_conf.fields |= MNCC_F_CAUSE;
2382 decode_cause(&call_conf.cause,
2383 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2384 }
2385 /* cc cap */
2386 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2387 call_conf.fields |= MNCC_F_CCCAP;
2388 decode_cccap(&call_conf.cccap,
2389 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2390 }
2391
2392 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2393
2394 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2395}
2396
2397static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2398{
2399 struct gsm_mncc *proceeding = arg;
2400 struct msgb *msg = gsm48_msgb_alloc();
2401 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2402
2403 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2404 msg->lchan = trans->lchan;
2405 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2406
2407 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2408
2409 /* bearer capability */
2410 if (proceeding->fields & MNCC_F_BEARER_CAP)
2411 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2412 /* facility */
2413 if (proceeding->fields & MNCC_F_FACILITY)
2414 encode_facility(msg, 0, &proceeding->facility);
2415 /* progress */
2416 if (proceeding->fields & MNCC_F_PROGRESS)
2417 encode_progress(msg, 0, &proceeding->progress);
2418
2419 return gsm48_sendmsg(msg);
2420}
2421
2422static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2423{
2424 struct gsm48_hdr *gh = msgb_l3(msg);
2425 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2426 struct tlv_parsed tp;
2427 struct gsm_mncc alerting;
2428
2429 gsm48_stop_cc_timer(trans);
2430 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2431
2432 memset(&alerting, 0, sizeof(struct gsm_mncc));
2433 alerting.callref = trans->callref;
2434 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2435 /* facility */
2436 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2437 alerting.fields |= MNCC_F_FACILITY;
2438 decode_facility(&alerting.facility,
2439 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2440 }
2441
2442 /* progress */
2443 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2444 alerting.fields |= MNCC_F_PROGRESS;
2445 decode_progress(&alerting.progress,
2446 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2447 }
2448 /* ss-version */
2449 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2450 alerting.fields |= MNCC_F_SSVERSION;
2451 decode_ssversion(&alerting.ssversion,
2452 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2453 }
2454
2455 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2456
2457 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2458}
2459
2460static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2461{
2462 struct gsm_mncc *alerting = arg;
2463 struct msgb *msg = gsm48_msgb_alloc();
2464 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2465
2466 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2467 msg->lchan = trans->lchan;
2468 gh->msg_type = GSM48_MT_CC_ALERTING;
2469
2470 /* facility */
2471 if (alerting->fields & MNCC_F_FACILITY)
2472 encode_facility(msg, 0, &alerting->facility);
2473 /* progress */
2474 if (alerting->fields & MNCC_F_PROGRESS)
2475 encode_progress(msg, 0, &alerting->progress);
2476 /* user-user */
2477 if (alerting->fields & MNCC_F_USERUSER)
2478 encode_useruser(msg, 0, &alerting->useruser);
2479
2480 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2481
2482 return gsm48_sendmsg(msg);
2483}
2484
2485static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2486{
2487 struct gsm_mncc *progress = arg;
2488 struct msgb *msg = gsm48_msgb_alloc();
2489 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2490
2491 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2492 msg->lchan = trans->lchan;
2493 gh->msg_type = GSM48_MT_CC_PROGRESS;
2494
2495 /* progress */
2496 encode_progress(msg, 1, &progress->progress);
2497 /* user-user */
2498 if (progress->fields & MNCC_F_USERUSER)
2499 encode_useruser(msg, 0, &progress->useruser);
2500
2501 return gsm48_sendmsg(msg);
2502}
2503
2504static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2505{
2506 struct gsm_mncc *connect = arg;
2507 struct msgb *msg = gsm48_msgb_alloc();
2508 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2509
2510 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2511 msg->lchan = trans->lchan;
2512 gh->msg_type = GSM48_MT_CC_CONNECT;
2513
2514 gsm48_stop_cc_timer(trans);
2515 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2516
2517 /* facility */
2518 if (connect->fields & MNCC_F_FACILITY)
2519 encode_facility(msg, 0, &connect->facility);
2520 /* progress */
2521 if (connect->fields & MNCC_F_PROGRESS)
2522 encode_progress(msg, 0, &connect->progress);
2523 /* connected number */
2524 if (connect->fields & MNCC_F_CONNECTED)
2525 encode_connected(msg, &connect->connected);
2526 /* user-user */
2527 if (connect->fields & MNCC_F_USERUSER)
2528 encode_useruser(msg, 0, &connect->useruser);
2529
2530 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2531
2532 return gsm48_sendmsg(msg);
2533}
2534
2535static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2536{
2537 struct gsm48_hdr *gh = msgb_l3(msg);
2538 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2539 struct tlv_parsed tp;
2540 struct gsm_mncc connect;
2541
2542 gsm48_stop_cc_timer(trans);
2543
2544 memset(&connect, 0, sizeof(struct gsm_mncc));
2545 connect.callref = trans->callref;
2546 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2547 /* use subscriber as connected party number */
2548 if (trans->subscr) {
2549 connect.fields |= MNCC_F_CONNECTED;
2550 strncpy(connect.connected.number, trans->subscr->extension,
2551 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002552 strncpy(connect.imsi, trans->subscr->imsi,
2553 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002554 }
2555 /* facility */
2556 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2557 connect.fields |= MNCC_F_FACILITY;
2558 decode_facility(&connect.facility,
2559 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2560 }
2561 /* user-user */
2562 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2563 connect.fields |= MNCC_F_USERUSER;
2564 decode_useruser(&connect.useruser,
2565 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2566 }
2567 /* ss-version */
2568 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2569 connect.fields |= MNCC_F_SSVERSION;
2570 decode_ssversion(&connect.ssversion,
2571 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2572 }
2573
2574 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2575
2576 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2577}
2578
2579
2580static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2581{
2582 struct gsm_mncc connect_ack;
2583
2584 gsm48_stop_cc_timer(trans);
2585
2586 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2587
2588 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2589 connect_ack.callref = trans->callref;
2590 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2591 &connect_ack);
2592}
2593
2594static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2595{
2596 struct msgb *msg = gsm48_msgb_alloc();
2597 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2598
2599 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2600 msg->lchan = trans->lchan;
2601 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2602
2603 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2604
2605 return gsm48_sendmsg(msg);
2606}
2607
2608static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2609{
2610 struct gsm48_hdr *gh = msgb_l3(msg);
2611 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2612 struct tlv_parsed tp;
2613 struct gsm_mncc disc;
2614
2615 gsm48_stop_cc_timer(trans);
2616
2617 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2618
2619 memset(&disc, 0, sizeof(struct gsm_mncc));
2620 disc.callref = trans->callref;
2621 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2622 /* cause */
2623 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2624 disc.fields |= MNCC_F_CAUSE;
2625 decode_cause(&disc.cause,
2626 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2627 }
2628 /* facility */
2629 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2630 disc.fields |= MNCC_F_FACILITY;
2631 decode_facility(&disc.facility,
2632 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2633 }
2634 /* user-user */
2635 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2636 disc.fields |= MNCC_F_USERUSER;
2637 decode_useruser(&disc.useruser,
2638 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2639 }
2640 /* ss-version */
2641 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2642 disc.fields |= MNCC_F_SSVERSION;
2643 decode_ssversion(&disc.ssversion,
2644 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2645 }
2646
2647 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2648
2649}
2650
Harald Weltec66b71c2009-06-11 14:23:20 +08002651static struct gsm_mncc_cause default_cause = {
2652 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2653 .coding = 0,
2654 .rec = 0,
2655 .rec_val = 0,
2656 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2657 .diag_len = 0,
2658 .diag = { 0 },
2659};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002660
2661static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2662{
2663 struct gsm_mncc *disc = arg;
2664 struct msgb *msg = gsm48_msgb_alloc();
2665 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2666
2667 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2668 msg->lchan = trans->lchan;
2669 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2670
2671 gsm48_stop_cc_timer(trans);
2672 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2673
2674 /* cause */
2675 if (disc->fields & MNCC_F_CAUSE)
2676 encode_cause(msg, 1, &disc->cause);
2677 else
2678 encode_cause(msg, 1, &default_cause);
2679
2680 /* facility */
2681 if (disc->fields & MNCC_F_FACILITY)
2682 encode_facility(msg, 0, &disc->facility);
2683 /* progress */
2684 if (disc->fields & MNCC_F_PROGRESS)
2685 encode_progress(msg, 0, &disc->progress);
2686 /* user-user */
2687 if (disc->fields & MNCC_F_USERUSER)
2688 encode_useruser(msg, 0, &disc->useruser);
2689
2690 /* store disconnect cause for T306 expiry */
2691 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2692
2693 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2694
2695 return gsm48_sendmsg(msg);
2696}
2697
2698static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2699{
2700 struct gsm48_hdr *gh = msgb_l3(msg);
2701 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2702 struct tlv_parsed tp;
2703 struct gsm_mncc rel;
2704 int rc;
2705
2706 gsm48_stop_cc_timer(trans);
2707
2708 memset(&rel, 0, sizeof(struct gsm_mncc));
2709 rel.callref = trans->callref;
2710 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2711 /* cause */
2712 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2713 rel.fields |= MNCC_F_CAUSE;
2714 decode_cause(&rel.cause,
2715 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2716 }
2717 /* facility */
2718 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2719 rel.fields |= MNCC_F_FACILITY;
2720 decode_facility(&rel.facility,
2721 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2722 }
2723 /* user-user */
2724 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2725 rel.fields |= MNCC_F_USERUSER;
2726 decode_useruser(&rel.useruser,
2727 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2728 }
2729 /* ss-version */
2730 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2731 rel.fields |= MNCC_F_SSVERSION;
2732 decode_ssversion(&rel.ssversion,
2733 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2734 }
2735
2736 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2737 /* release collision 5.4.5 */
2738 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2739 } else {
2740 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2741 GSM48_MT_CC_RELEASE_COMPL);
2742 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2743 }
2744
2745 new_cc_state(trans, GSM_CSTATE_NULL);
2746
2747 trans->callref = 0;
2748 free_trans(trans);
2749
2750 return rc;
2751}
2752
2753static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2754{
2755 struct gsm_mncc *rel = arg;
2756 struct msgb *msg = gsm48_msgb_alloc();
2757 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2758
2759 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2760 msg->lchan = trans->lchan;
2761 gh->msg_type = GSM48_MT_CC_RELEASE;
2762
2763 trans->callref = 0;
2764
2765 gsm48_stop_cc_timer(trans);
2766 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2767
2768 /* cause */
2769 if (rel->fields & MNCC_F_CAUSE)
2770 encode_cause(msg, 0, &rel->cause);
2771 /* facility */
2772 if (rel->fields & MNCC_F_FACILITY)
2773 encode_facility(msg, 0, &rel->facility);
2774 /* user-user */
2775 if (rel->fields & MNCC_F_USERUSER)
2776 encode_useruser(msg, 0, &rel->useruser);
2777
2778 trans->T308_second = 0;
2779 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2780
2781 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2782 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2783
2784 return gsm48_sendmsg(msg);
2785}
2786
2787static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2788{
2789 struct gsm48_hdr *gh = msgb_l3(msg);
2790 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2791 struct tlv_parsed tp;
2792 struct gsm_mncc rel;
2793 int rc = 0;
2794
2795 gsm48_stop_cc_timer(trans);
2796
2797 memset(&rel, 0, sizeof(struct gsm_mncc));
2798 rel.callref = trans->callref;
2799 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2800 /* cause */
2801 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2802 rel.fields |= MNCC_F_CAUSE;
2803 decode_cause(&rel.cause,
2804 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2805 }
2806 /* facility */
2807 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2808 rel.fields |= MNCC_F_FACILITY;
2809 decode_facility(&rel.facility,
2810 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2811 }
2812 /* user-user */
2813 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2814 rel.fields |= MNCC_F_USERUSER;
2815 decode_useruser(&rel.useruser,
2816 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2817 }
2818 /* ss-version */
2819 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2820 rel.fields |= MNCC_F_SSVERSION;
2821 decode_ssversion(&rel.ssversion,
2822 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2823 }
2824
2825 if (trans->callref) {
2826 switch (trans->state) {
2827 case GSM_CSTATE_CALL_PRESENT:
2828 rc = mncc_recvmsg(trans->network, trans,
2829 MNCC_REJ_IND, &rel);
2830 break;
2831 case GSM_CSTATE_RELEASE_REQ:
2832 rc = mncc_recvmsg(trans->network, trans,
2833 MNCC_REL_CNF, &rel);
2834 break;
2835 default:
2836 rc = mncc_recvmsg(trans->network, trans,
2837 MNCC_REL_IND, &rel);
2838 }
2839 }
2840
2841 trans->callref = 0;
2842 free_trans(trans);
2843
2844 return rc;
2845}
2846
2847static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2848{
2849 struct gsm_mncc *rel = arg;
2850 struct msgb *msg = gsm48_msgb_alloc();
2851 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2852
2853 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2854 msg->lchan = trans->lchan;
2855 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2856
2857 trans->callref = 0;
2858
2859 gsm48_stop_cc_timer(trans);
2860
2861 /* cause */
2862 if (rel->fields & MNCC_F_CAUSE)
2863 encode_cause(msg, 0, &rel->cause);
2864 /* facility */
2865 if (rel->fields & MNCC_F_FACILITY)
2866 encode_facility(msg, 0, &rel->facility);
2867 /* user-user */
2868 if (rel->fields & MNCC_F_USERUSER)
2869 encode_useruser(msg, 0, &rel->useruser);
2870
2871 free_trans(trans);
2872
2873 return gsm48_sendmsg(msg);
2874}
2875
2876static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2877{
2878 struct gsm48_hdr *gh = msgb_l3(msg);
2879 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2880 struct tlv_parsed tp;
2881 struct gsm_mncc fac;
2882
2883 memset(&fac, 0, sizeof(struct gsm_mncc));
2884 fac.callref = trans->callref;
2885 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2886 /* facility */
2887 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2888 fac.fields |= MNCC_F_FACILITY;
2889 decode_facility(&fac.facility,
2890 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2891 }
2892 /* ss-version */
2893 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2894 fac.fields |= MNCC_F_SSVERSION;
2895 decode_ssversion(&fac.ssversion,
2896 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2897 }
2898
2899 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2900}
2901
2902static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2903{
2904 struct gsm_mncc *fac = arg;
2905 struct msgb *msg = gsm48_msgb_alloc();
2906 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2907
2908 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2909 msg->lchan = trans->lchan;
2910 gh->msg_type = GSM48_MT_CC_FACILITY;
2911
2912 /* facility */
2913 encode_facility(msg, 1, &fac->facility);
2914
2915 return gsm48_sendmsg(msg);
2916}
2917
2918static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2919{
2920 struct gsm_mncc hold;
2921
2922 memset(&hold, 0, sizeof(struct gsm_mncc));
2923 hold.callref = trans->callref;
2924 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2925}
2926
2927static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2928{
2929 struct msgb *msg = gsm48_msgb_alloc();
2930 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2931
2932 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2933 msg->lchan = trans->lchan;
2934 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2935
2936 return gsm48_sendmsg(msg);
2937}
2938
2939static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2940{
2941 struct gsm_mncc *hold_rej = arg;
2942 struct msgb *msg = gsm48_msgb_alloc();
2943 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2944
2945 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2946 msg->lchan = trans->lchan;
2947 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2948
2949 /* cause */
2950 if (hold_rej->fields & MNCC_F_CAUSE)
2951 encode_cause(msg, 1, &hold_rej->cause);
2952 else
2953 encode_cause(msg, 1, &default_cause);
2954
2955 return gsm48_sendmsg(msg);
2956}
2957
2958static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2959{
2960 struct gsm_mncc retrieve;
2961
2962 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2963 retrieve.callref = trans->callref;
2964 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2965}
2966
2967static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2968{
2969 struct msgb *msg = gsm48_msgb_alloc();
2970 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2971
2972 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2973 msg->lchan = trans->lchan;
2974 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2975
2976 return gsm48_sendmsg(msg);
2977}
2978
2979static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2980{
2981 struct gsm_mncc *retrieve_rej = arg;
2982 struct msgb *msg = gsm48_msgb_alloc();
2983 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2984
2985 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2986 msg->lchan = trans->lchan;
2987 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2988
2989 /* cause */
2990 if (retrieve_rej->fields & MNCC_F_CAUSE)
2991 encode_cause(msg, 1, &retrieve_rej->cause);
2992 else
2993 encode_cause(msg, 1, &default_cause);
2994
2995 return gsm48_sendmsg(msg);
2996}
2997
2998static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2999{
3000 struct gsm48_hdr *gh = msgb_l3(msg);
3001 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3002 struct tlv_parsed tp;
3003 struct gsm_mncc dtmf;
3004
3005 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3006 dtmf.callref = trans->callref;
3007 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3008 /* keypad facility */
3009 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3010 dtmf.fields |= MNCC_F_KEYPAD;
3011 decode_keypad(&dtmf.keypad,
3012 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3013 }
3014
3015 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3016}
3017
3018static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3019{
3020 struct gsm_mncc *dtmf = arg;
3021 struct msgb *msg = gsm48_msgb_alloc();
3022 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3023
3024 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3025 msg->lchan = trans->lchan;
3026 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3027
3028 /* keypad */
3029 if (dtmf->fields & MNCC_F_KEYPAD)
3030 encode_keypad(msg, dtmf->keypad);
3031
3032 return gsm48_sendmsg(msg);
3033}
3034
3035static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3036{
3037 struct gsm_mncc *dtmf = arg;
3038 struct msgb *msg = gsm48_msgb_alloc();
3039 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3040
3041 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3042 msg->lchan = trans->lchan;
3043 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3044
3045 /* cause */
3046 if (dtmf->fields & MNCC_F_CAUSE)
3047 encode_cause(msg, 1, &dtmf->cause);
3048 else
3049 encode_cause(msg, 1, &default_cause);
3050
3051 return gsm48_sendmsg(msg);
3052}
3053
3054static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3055{
3056 struct msgb *msg = gsm48_msgb_alloc();
3057 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3058
3059 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3060 msg->lchan = trans->lchan;
3061 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3062
3063 return gsm48_sendmsg(msg);
3064}
3065
3066static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3067{
3068 struct gsm_mncc dtmf;
3069
3070 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3071 dtmf.callref = trans->callref;
3072
3073 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3074}
3075
3076static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3077{
3078 struct gsm48_hdr *gh = msgb_l3(msg);
3079 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3080 struct tlv_parsed tp;
3081 struct gsm_mncc modify;
3082
3083 memset(&modify, 0, sizeof(struct gsm_mncc));
3084 modify.callref = trans->callref;
3085 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3086 /* bearer capability */
3087 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3088 modify.fields |= MNCC_F_BEARER_CAP;
3089 decode_bearer_cap(&modify.bearer_cap,
3090 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3091 }
3092
3093 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3094
3095 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3096}
3097
3098static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3099{
3100 struct gsm_mncc *modify = arg;
3101 struct msgb *msg = gsm48_msgb_alloc();
3102 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3103
3104 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3105 msg->lchan = trans->lchan;
3106 gh->msg_type = GSM48_MT_CC_MODIFY;
3107
3108 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3109
3110 /* bearer capability */
3111 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3112
3113 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3114
3115 return gsm48_sendmsg(msg);
3116}
3117
3118static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3119{
3120 struct gsm48_hdr *gh = msgb_l3(msg);
3121 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3122 struct tlv_parsed tp;
3123 struct gsm_mncc modify;
3124
3125 gsm48_stop_cc_timer(trans);
3126
3127 memset(&modify, 0, sizeof(struct gsm_mncc));
3128 modify.callref = trans->callref;
3129 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3130 /* bearer capability */
3131 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3132 modify.fields |= MNCC_F_BEARER_CAP;
3133 decode_bearer_cap(&modify.bearer_cap,
3134 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3135 }
3136
3137 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3138
3139 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3140}
3141
3142static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3143{
3144 struct gsm_mncc *modify = arg;
3145 struct msgb *msg = gsm48_msgb_alloc();
3146 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3147
3148 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3149 msg->lchan = trans->lchan;
3150 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3151
3152 /* bearer capability */
3153 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3154
3155 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3156
3157 return gsm48_sendmsg(msg);
3158}
3159
3160static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3161{
3162 struct gsm48_hdr *gh = msgb_l3(msg);
3163 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3164 struct tlv_parsed tp;
3165 struct gsm_mncc modify;
3166
3167 gsm48_stop_cc_timer(trans);
3168
3169 memset(&modify, 0, sizeof(struct gsm_mncc));
3170 modify.callref = trans->callref;
3171 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3172 /* bearer capability */
3173 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3174 modify.fields |= GSM48_IE_BEARER_CAP;
3175 decode_bearer_cap(&modify.bearer_cap,
3176 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3177 }
3178 /* cause */
3179 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3180 modify.fields |= MNCC_F_CAUSE;
3181 decode_cause(&modify.cause,
3182 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3183 }
3184
3185 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3186
3187 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3188}
3189
3190static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3191{
3192 struct gsm_mncc *modify = arg;
3193 struct msgb *msg = gsm48_msgb_alloc();
3194 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3195
3196 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3197 msg->lchan = trans->lchan;
3198 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3199
3200 /* bearer capability */
3201 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3202 /* cause */
3203 encode_cause(msg, 1, &modify->cause);
3204
3205 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3206
3207 return gsm48_sendmsg(msg);
3208}
3209
3210static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3211{
3212 struct gsm_mncc *notify = arg;
3213 struct msgb *msg = gsm48_msgb_alloc();
3214 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3215
3216 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3217 msg->lchan = trans->lchan;
3218 gh->msg_type = GSM48_MT_CC_NOTIFY;
3219
3220 /* notify */
3221 encode_notify(msg, notify->notify);
3222
3223 return gsm48_sendmsg(msg);
3224}
3225
3226static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3227{
3228 struct gsm48_hdr *gh = msgb_l3(msg);
3229 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3230// struct tlv_parsed tp;
3231 struct gsm_mncc notify;
3232
3233 memset(&notify, 0, sizeof(struct gsm_mncc));
3234 notify.callref = trans->callref;
3235// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3236 if (payload_len >= 1)
3237 decode_notify(&notify.notify, gh->data);
3238
3239 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3240}
3241
3242static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3243{
3244 struct gsm_mncc *user = arg;
3245 struct msgb *msg = gsm48_msgb_alloc();
3246 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3247
3248 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3249 msg->lchan = trans->lchan;
3250 gh->msg_type = GSM48_MT_CC_USER_INFO;
3251
3252 /* user-user */
3253 if (user->fields & MNCC_F_USERUSER)
3254 encode_useruser(msg, 1, &user->useruser);
3255 /* more data */
3256 if (user->more)
3257 encode_more(msg);
3258
3259 return gsm48_sendmsg(msg);
3260}
3261
3262static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3263{
3264 struct gsm48_hdr *gh = msgb_l3(msg);
3265 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3266 struct tlv_parsed tp;
3267 struct gsm_mncc user;
3268
3269 memset(&user, 0, sizeof(struct gsm_mncc));
3270 user.callref = trans->callref;
3271 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3272 /* user-user */
3273 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3274 user.fields |= MNCC_F_USERUSER;
3275 decode_useruser(&user.useruser,
3276 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3277 }
3278 /* more data */
3279 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3280 user.more = 1;
3281
3282 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3283}
3284
3285static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3286{
3287 struct gsm_mncc *mode = arg;
3288
3289 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3290}
3291
3292static struct downstate {
3293 u_int32_t states;
3294 int type;
3295 int (*rout) (struct gsm_trans *trans, void *arg);
3296} downstatelist[] = {
3297 /* mobile originating call establishment */
3298 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3299 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3300 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3301 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3302 {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 */
3303 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3304 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3305 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3306 /* mobile terminating call establishment */
3307 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3308 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3309 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3310 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3311 /* signalling during call */
3312 {SBIT(GSM_CSTATE_ACTIVE),
3313 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3314 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3315 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3316 {ALL_STATES,
3317 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3318 {ALL_STATES,
3319 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3320 {ALL_STATES,
3321 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3322 {SBIT(GSM_CSTATE_ACTIVE),
3323 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3324 {SBIT(GSM_CSTATE_ACTIVE),
3325 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3326 {SBIT(GSM_CSTATE_ACTIVE),
3327 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3328 {SBIT(GSM_CSTATE_ACTIVE),
3329 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3330 {SBIT(GSM_CSTATE_ACTIVE),
3331 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3332 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3333 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3334 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3335 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3336 {SBIT(GSM_CSTATE_ACTIVE),
3337 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3338 /* clearing */
3339 {SBIT(GSM_CSTATE_INITIATED),
3340 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3341 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3342 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3343 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3344 MNCC_REL_REQ, gsm48_cc_tx_release},
3345 /* special */
3346 {ALL_STATES,
3347 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3348};
3349
3350#define DOWNSLLEN \
3351 (sizeof(downstatelist) / sizeof(struct downstate))
3352
3353
3354int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3355{
3356 int i, j, k, l, rc = 0;
3357 struct gsm_trans *trans = NULL, *transt;
3358 struct gsm_subscriber *subscr;
3359 struct gsm_lchan *lchan = NULL, *lchant;
3360 struct gsm_bts *bts = NULL;
3361 struct gsm_bts_trx *trx;
3362 struct gsm_bts_trx_ts *ts;
3363 struct gsm_mncc *data = arg, rel;
3364
3365 /* handle special messages */
3366 switch(msg_type) {
3367 case MNCC_BRIDGE:
3368 return tch_bridge(net, arg);
3369 case MNCC_FRAME_DROP:
3370 return tch_recv(net, arg, 0);
3371 case MNCC_FRAME_RECV:
3372 return tch_recv(net, arg, 1);
3373 case GSM_TRAU_FRAME:
3374 return tch_frame(net, arg);
3375 }
3376
3377 memset(&rel, 0, sizeof(struct gsm_mncc));
3378 rel.callref = data->callref;
3379
3380 /* Find callref */
3381 trans = get_trans_ref(net, data->callref);
3382
3383 /* Callref unknown */
3384 if (!trans) {
Andreas Eversbergc079be42009-06-15 23:22:09 +02003385 if (msg_type != MNCC_SETUP_REQ ||
3386 (!data->called.number[0] && !data->imsi[0])) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003387 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3388 "Received '%s' from MNCC with "
3389 "unknown callref %d\n", data->called.number,
3390 get_mncc_name(msg_type), data->callref);
3391 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003392 return mncc_release_ind(net, NULL, data->callref,
3393 GSM48_CAUSE_LOC_PRN_S_LU,
3394 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003395 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003396 if (!data->called.number[0] && !data->imsi[0]) {
3397 DEBUGP(DCC, "(bts - trx - ts - ti) "
3398 "Received '%s' from MNCC with "
3399 "no number or IMSI\n", get_mncc_name(msg_type));
3400 /* Invalid number */
3401 return mncc_release_ind(net, NULL, data->callref,
3402 GSM48_CAUSE_LOC_PRN_S_LU,
3403 GSM48_CC_CAUSE_INV_NR_FORMAT);
3404 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003405 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003406 if (data->called.number[0])
3407 subscr = subscr_get_by_extension(data->called.number);
3408 else
3409 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003410 /* If subscriber is not found */
3411 if (!subscr) {
3412 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3413 "Received '%s' from MNCC with "
3414 "unknown subscriber %s\n", data->called.number,
3415 get_mncc_name(msg_type), data->called.number);
3416 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003417 return mncc_release_ind(net, NULL, data->callref,
3418 GSM48_CAUSE_LOC_PRN_S_LU,
3419 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003420 }
3421 /* If subscriber is not "attached" */
3422 if (!subscr->lac) {
3423 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3424 "Received '%s' from MNCC with "
3425 "detached subscriber %s\n", data->called.number,
3426 get_mncc_name(msg_type), data->called.number);
3427 subscr_put(subscr);
3428 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003429 return mncc_release_ind(net, NULL, data->callref,
3430 GSM48_CAUSE_LOC_PRN_S_LU,
3431 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003432 }
3433 /* Create transaction */
Harald Weltec05677b2009-06-26 20:17:06 +02003434 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003435 DEBUGP(DCC, "No memory for trans.\n");
3436 subscr_put(subscr);
3437 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003438 mncc_release_ind(net, NULL, data->callref,
3439 GSM48_CAUSE_LOC_PRN_S_LU,
3440 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003441 return -ENOMEM;
3442 }
3443 trans->callref = data->callref;
3444 trans->network = net;
3445 trans->transaction_id = 0xff; /* unassigned */
3446 llist_add_tail(&trans->entry, &net->trans_list);
3447 /* Assign subscriber to transaction */
3448 trans->subscr = subscr;
3449 /* Find lchan */
3450 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003451 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003452 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003453 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003454 for (k = 0; k < TRX_NR_TS; k++) {
3455 ts = &trx->ts[k];
3456 for (l = 0; l < TS_MAX_LCHAN; l++) {
3457 lchant = &ts->lchan[l];
3458 if (lchant->subscr == subscr) {
3459 lchan = lchant;
3460 break;
3461 }
3462 }
3463 }
3464 }
3465 }
3466
3467 /* If subscriber has no lchan */
3468 if (!lchan) {
3469 /* find transaction with this subscriber already paging */
3470 llist_for_each_entry(transt, &net->trans_list, entry) {
3471 /* Transaction of our lchan? */
3472 if (transt == trans ||
3473 transt->subscr != subscr)
3474 continue;
3475 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3476 "Received '%s' from MNCC with "
3477 "unallocated channel, paging already "
3478 "started.\n", bts->nr,
3479 data->called.number,
3480 get_mncc_name(msg_type));
3481 return 0;
3482 }
3483 /* store setup informations until paging was successfull */
3484 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3485 /* start paging subscriber on all BTS with her location */
3486 subscr->net = net;
3487 bts = NULL;
3488 do {
3489 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3490 if (!bts)
3491 break;
3492 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3493 "Received '%s' from MNCC with "
3494 "unallocated channel, paging.\n",
3495 bts->nr, data->called.number,
3496 get_mncc_name(msg_type));
3497 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003498 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003499 setup_trig_pag_evt, subscr);
3500 } while (1);
3501 return 0;
3502 }
3503 /* Assign lchan */
3504 trans->lchan = lchan;
3505 use_lchan(lchan);
3506 }
3507 lchan = trans->lchan;
3508
3509 /* if paging did not respond yet */
3510 if (!lchan) {
3511 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3512 "Received '%s' from MNCC in paging state\n",
3513 (trans->subscr)?(trans->subscr->extension):"-",
3514 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003515 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3516 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003517 if (msg_type == MNCC_REL_REQ)
3518 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3519 else
3520 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3521 trans->callref = 0;
3522 free_trans(trans);
3523 return rc;
3524 }
3525
3526 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3527 "Received '%s' from MNCC in state %d (%s)\n",
3528 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3529 trans->transaction_id,
3530 (lchan->subscr)?(lchan->subscr->extension):"-",
3531 get_mncc_name(msg_type), trans->state,
3532 cc_state_names[trans->state]);
3533
3534 /* Find function for current state and message */
3535 for (i = 0; i < DOWNSLLEN; i++)
3536 if ((msg_type == downstatelist[i].type)
3537 && ((1 << trans->state) & downstatelist[i].states))
3538 break;
3539 if (i == DOWNSLLEN) {
3540 DEBUGP(DCC, "Message unhandled at this state.\n");
3541 return 0;
3542 }
3543
3544 rc = downstatelist[i].rout(trans, arg);
3545
3546 return rc;
3547}
3548
3549
3550static struct datastate {
3551 u_int32_t states;
3552 int type;
3553 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3554} datastatelist[] = {
3555 /* mobile originating call establishment */
3556 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3557 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3558 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3559 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3560 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3561 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3562 /* mobile terminating call establishment */
3563 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3564 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3565 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3566 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3567 {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 */
3568 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3569 /* signalling during call */
3570 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3571 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3572 {SBIT(GSM_CSTATE_ACTIVE),
3573 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3574 {ALL_STATES,
3575 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3576 {ALL_STATES,
3577 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3578 {ALL_STATES,
3579 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3580 {SBIT(GSM_CSTATE_ACTIVE),
3581 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3582 {SBIT(GSM_CSTATE_ACTIVE),
3583 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3584 {SBIT(GSM_CSTATE_ACTIVE),
3585 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3586 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3587 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3588 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3589 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3590 {SBIT(GSM_CSTATE_ACTIVE),
3591 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3592 /* clearing */
3593 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3594 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3595 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3596 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3597 {ALL_STATES, /* 5.4.3.4 */
3598 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3599};
3600
3601#define DATASLLEN \
3602 (sizeof(datastatelist) / sizeof(struct datastate))
3603
Harald Welte4bc90a12008-12-27 16:32:52 +00003604static int gsm0408_rcv_cc(struct msgb *msg)
3605{
3606 struct gsm48_hdr *gh = msgb_l3(msg);
3607 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003608 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3609 struct gsm_lchan *lchan = msg->lchan;
3610 struct gsm_trans *trans = NULL, *transt;
3611 struct gsm_network *net = lchan->ts->trx->bts->network;
3612 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003613
Harald Welte4bfdfe72009-06-10 23:11:52 +08003614 if (msg_type & 0x80) {
3615 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3616 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003617 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003618
3619 /* Find transaction */
3620 llist_for_each_entry(transt, &net->trans_list, entry) {
3621 /* Transaction of our lchan? */
3622 if (transt->lchan == lchan
3623 && transt->transaction_id == transaction_id) {
3624 trans = transt;
3625 }
3626 }
3627
3628 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3629 "Received '%s' from MS in state %d (%s)\n",
3630 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3631 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3632 cc_msg_names[msg_type], trans?(trans->state):0,
3633 cc_state_names[trans?(trans->state):0]);
3634
3635 /* Create transaction */
3636 if (!trans) {
3637 DEBUGP(DCC, "Unknown transaction ID %02x, "
3638 "creating new trans.\n", transaction_id);
3639 /* Create transaction */
Harald Welte9b11e872009-06-26 19:42:28 +02003640 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003641 DEBUGP(DCC, "No memory for trans.\n");
3642 rc = gsm48_tx_simple(msg->lchan,
3643 GSM48_PDISC_CC | transaction_id,
3644 GSM48_MT_CC_RELEASE_COMPL);
3645 return -ENOMEM;
3646 }
3647 llist_add_tail(&trans->entry, &net->trans_list);
3648 /* Assign transaction */
3649 trans->callref = new_callref++;
3650 trans->network = net;
3651 trans->transaction_id = transaction_id;
3652 trans->lchan = lchan;
3653 use_lchan(lchan);
3654 if (lchan->subscr) {
3655 trans->subscr = lchan->subscr;
3656 subscr_get(trans->subscr);
3657 }
3658 }
3659
3660 /* find function for current state and message */
3661 for (i = 0; i < DATASLLEN; i++)
3662 if ((msg_type == datastatelist[i].type)
3663 && ((1 << trans->state) & datastatelist[i].states))
3664 break;
3665 if (i == DATASLLEN) {
3666 DEBUGP(DCC, "Message unhandled at this state.\n");
3667 return 0;
3668 }
3669
3670 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003671
3672 return rc;
3673}
3674
Harald Welte52b1f982008-12-23 20:25:15 +00003675/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3676int gsm0408_rcvmsg(struct msgb *msg)
3677{
3678 struct gsm48_hdr *gh = msgb_l3(msg);
3679 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003680 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003681
3682 switch (pdisc) {
3683 case GSM48_PDISC_CC:
3684 rc = gsm0408_rcv_cc(msg);
3685 break;
3686 case GSM48_PDISC_MM:
3687 rc = gsm0408_rcv_mm(msg);
3688 break;
3689 case GSM48_PDISC_RR:
3690 rc = gsm0408_rcv_rr(msg);
3691 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003692 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003693 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003694 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003695 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003696 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003697 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3698 pdisc);
3699 break;
3700 default:
3701 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3702 pdisc);
3703 break;
3704 }
3705
3706 return rc;
3707}
Harald Welte8470bf22008-12-25 23:28:35 +00003708
Harald Welte8470bf22008-12-25 23:28:35 +00003709/* Section 9.1.8 / Table 9.9 */
3710struct chreq {
3711 u_int8_t val;
3712 u_int8_t mask;
3713 enum chreq_type type;
3714};
3715
3716/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3717static const struct chreq chreq_type_neci1[] = {
3718 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3719 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3720 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3721 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3722 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3723 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3724 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3725 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3726 { 0x10, 0xf0, CHREQ_T_SDCCH },
3727 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3728 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3729 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3730};
3731
3732/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3733static const struct chreq chreq_type_neci0[] = {
3734 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3735 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3736 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3737 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3738 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3739 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3740 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3741 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3742};
3743
3744static const enum gsm_chan_t ctype_by_chreq[] = {
3745 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3746 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3747 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3748 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3749 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3750 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3751 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3752 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3753 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3754 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3755 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3756 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3757};
3758
Harald Weltee14a57c2008-12-29 04:08:28 +00003759static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3760 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3761 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3762 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3763 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3764 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3765 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3766 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3767 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3768 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3769 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3770 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3771 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3772};
3773
Harald Welte8470bf22008-12-25 23:28:35 +00003774enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3775{
3776 int i;
3777 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3778
3779 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3780 const struct chreq *chr = &chreq_type_neci0[i];
3781 if ((ra & chr->mask) == chr->val)
3782 return ctype_by_chreq[chr->type];
3783 }
3784 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3785 return GSM_LCHAN_SDCCH;
3786}
Harald Weltee14a57c2008-12-29 04:08:28 +00003787
3788enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3789{
3790 int i;
3791 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3792
3793 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3794 const struct chreq *chr = &chreq_type_neci0[i];
3795 if ((ra & chr->mask) == chr->val)
3796 return reason_by_chreq[chr->type];
3797 }
3798 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3799 return GSM_CHREQ_REASON_OTHER;
3800}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003801
3802/* dequeue messages to layer 4 */
3803int bsc_upqueue(struct gsm_network *net)
3804{
3805 struct gsm_mncc *mncc;
3806 struct msgb *msg;
3807 int work = 0;
3808
3809 if (net)
3810 while ((msg = msgb_dequeue(&net->upqueue))) {
3811 mncc = (struct gsm_mncc *)msg->data;
3812 if (net->mncc_recv)
3813 net->mncc_recv(net, mncc->msg_type, mncc);
3814 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003815 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003816 }
3817
3818 return work;
3819}