blob: df4d3c66861c8c08d82c484f7a0776eb67cb1a00 [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");
Harald Welte470ec292009-06-26 20:25:23 +0200357 lchan->loc_operation = talloc_zero(tall_locop_ctx,
358 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000359}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000360
Holger Freytherd51524f2009-06-09 08:27:07 +0000361static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
362{
363 u_int32_t tmsi;
364
365 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
366 db_subscriber_alloc_tmsi(lchan->subscr);
367 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
368 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
369 release_loc_updating_req(lchan);
370 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
371 }
372
373 return 0;
374}
375
Holger Freyther7c19f742009-06-06 13:54:35 +0000376static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
377 void *handler_data, void *signal_data)
378{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800379 struct gsm_trans *trans, *temp;
380
Holger Freyther7c19f742009-06-06 13:54:35 +0000381 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
382 return 0;
383
384 /*
385 * Cancel any outstanding location updating request
386 * operation taking place on the lchan.
387 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200388 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200389 if (!lchan)
390 return 0;
391
Holger Freyther7c19f742009-06-06 13:54:35 +0000392 release_loc_updating_req(lchan);
393
Harald Welte4bfdfe72009-06-10 23:11:52 +0800394 /* Free all transactions that are associated with the released lchan */
395 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
396 if (trans->lchan == lchan)
397 free_trans(trans);
398 }
399
Holger Freyther7c19f742009-06-06 13:54:35 +0000400 return 0;
401}
402
403/*
404 * This will be ran by the linker when loading the DSO. We use it to
405 * do system initialization, e.g. registration of signal handlers.
406 */
407static __attribute__((constructor)) void on_dso_load_0408(void)
408{
409 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
410}
411
Harald Welte52b1f982008-12-23 20:25:15 +0000412static void to_bcd(u_int8_t *bcd, u_int16_t val)
413{
Harald Welte4b634542008-12-27 01:55:51 +0000414 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000415 val = val / 10;
416 bcd[1] = val % 10;
417 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000418 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000419 val = val / 10;
420}
421
Holger Freyther17746612008-12-28 16:32:44 +0000422void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000423 u_int16_t mnc, u_int16_t lac)
424{
425 u_int8_t bcd[3];
426
427 to_bcd(bcd, mcc);
428 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
429 lai48->digits[1] = bcd[2];
430
431 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000432 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
433#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000434 lai48->digits[1] |= bcd[2] << 4;
435 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000436#else
437 lai48->digits[1] |= 0xf << 4;
438 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
439#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000440
Harald Welte4b634542008-12-27 01:55:51 +0000441 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000442}
443
Harald Welte255539c2008-12-28 02:26:27 +0000444#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000445#define MID_TMSI_LEN (TMSI_LEN + 2)
446
Harald Welte255539c2008-12-28 02:26:27 +0000447int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000448{
Harald Welte65e74cc2008-12-29 01:55:35 +0000449 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000450
Harald Welte4b634542008-12-27 01:55:51 +0000451 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000452 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000453 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000454 *tptr = htonl(tmsi);
455
456 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000457}
458
Harald Welte09e38af2009-02-16 22:52:23 +0000459static const char bcd_num_digits[] = {
460 '0', '1', '2', '3', '4', '5', '6', '7',
461 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
462};
463
Harald Welte0c389302009-06-10 12:08:54 +0800464/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
465int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
466 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000467{
468 u_int8_t in_len = bcd_lv[0];
469 int i;
470
Harald Welte0c389302009-06-10 12:08:54 +0800471 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000472 /* lower nibble */
473 output_len--;
474 if (output_len <= 1)
475 break;
476 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
477
478 /* higher nibble */
479 output_len--;
480 if (output_len <= 1)
481 break;
482 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
483 }
484 if (output_len >= 1)
485 *output++ = '\0';
486
Harald Welte0c389302009-06-10 12:08:54 +0800487 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000488}
489
490/* convert a single ASCII character to call-control BCD */
491static int asc_to_bcd(const char asc)
492{
493 int i;
494
495 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
496 if (bcd_num_digits[i] == asc)
497 return i;
498 }
499 return -EINVAL;
500}
501
Harald Welte0c389302009-06-10 12:08:54 +0800502/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000503int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800504 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000505{
506 int in_len = strlen(input);
507 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800508 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000509
510 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800511 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000512 if (in_len % 2)
513 bcd_lv[0]++;
514
Harald Welte0c389302009-06-10 12:08:54 +0800515 if (bcd_lv[0] > max_len)
516 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000517
518 for (i = 0; i < in_len; i++) {
519 int rc = asc_to_bcd(input[i]);
520 if (rc < 0)
521 return rc;
522 if (i % 2 == 0)
523 *bcd_cur = rc;
524 else
525 *bcd_cur++ |= (rc << 4);
526 }
527 /* append padding nibble in case of odd length */
528 if (i % 2)
529 *bcd_cur++ |= 0xf0;
530
531 /* return how many bytes we used */
532 return (bcd_cur - bcd_lv);
533}
534
Harald Welte0c389302009-06-10 12:08:54 +0800535/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800536static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800537 const u_int8_t *lv)
538{
539 u_int8_t in_len = lv[0];
540 int i, s;
541
542 if (in_len < 1)
543 return -EINVAL;
544
Harald Welte4bfdfe72009-06-10 23:11:52 +0800545 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800546
547 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800548 bcap->transfer = lv[1] & 0x07;
549 bcap->mode = (lv[1] & 0x08) >> 3;
550 bcap->coding = (lv[1] & 0x10) >> 4;
551 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800552
553 i = 1;
554 s = 0;
555 while(!(lv[i] & 0x80)) {
556 i++; /* octet 3a etc */
557 if (in_len < i)
558 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800559 bcap->speech_ver[s++] = lv[i] & 0x0f;
560 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800561 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800562 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800563 if (s == 7) /* maximum speech versions + end of list */
564 return 0;
565 }
566
567 return 0;
568}
569
570/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800571static int encode_bearer_cap(struct msgb *msg, int lv_only,
572 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800573{
574 u_int8_t lv[32 + 1];
575 int i, s;
576
Harald Welte4bfdfe72009-06-10 23:11:52 +0800577 lv[1] = bcap->transfer;
578 lv[1] |= bcap->mode << 3;
579 lv[1] |= bcap->coding << 4;
580 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800581
582 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800583 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800584 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800586 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800588 }
589 lv[i] |= 0x80; /* last IE of octet 3 etc */
590
591 lv[0] = i;
592 if (lv_only)
593 msgb_lv_put(msg, lv[0], lv+1);
594 else
595 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
596
597 return 0;
598}
599
600/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800601static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800602{
603 u_int8_t in_len = lv[0];
604
605 if (in_len < 1)
606 return -EINVAL;
607
608 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800609 ccap->dtmf = lv[1] & 0x01;
610 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800611
612 return 0;
613}
614
615/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800616static int decode_called(struct gsm_mncc_number *called,
617 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800618{
619 u_int8_t in_len = lv[0];
620
621 if (in_len < 1)
622 return -EINVAL;
623
624 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800625 called->plan = lv[1] & 0x0f;
626 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800627
628 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800629 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800630
631 return 0;
632}
633
634/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800635static int encode_called(struct msgb *msg,
636 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800637{
638 u_int8_t lv[18];
639 int ret;
640
641 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800642 lv[1] = called->plan;
643 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800644
645 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800646 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800647 if (ret < 0)
648 return ret;
649
650 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
651
652 return 0;
653}
654
655/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800656static int encode_callerid(struct msgb *msg, int ie,
657 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800658{
659 u_int8_t lv[13];
660 int h_len = 1;
661 int ret;
662
663 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800664 lv[1] = callerid->plan;
665 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800666
Harald Welte4bfdfe72009-06-10 23:11:52 +0800667 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800668 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800669 lv[2] = callerid->screen;
670 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800671 lv[2] |= 0x80;
672 h_len++;
673 } else
674 lv[1] |= 0x80;
675
676 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800677 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800678 if (ret < 0)
679 return ret;
680
681 msgb_tlv_put(msg, ie, lv[0], lv+1);
682
683 return 0;
684}
685
686/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800687static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800688 const u_int8_t *lv)
689{
690 u_int8_t in_len = lv[0];
691 int i;
692
693 if (in_len < 2)
694 return -EINVAL;
695
Harald Welte4bfdfe72009-06-10 23:11:52 +0800696 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800697
698 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800699 cause->location = lv[1] & 0x0f;
700 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800701
702 i = 1;
703 if (!(lv[i] & 0x80)) {
704 i++; /* octet 3a */
705 if (in_len < i+1)
706 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800707 cause->rec = 1;
708 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800709
710 }
711 i++;
712
713 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800714 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800715 i++;
716
717 if (in_len < i) /* no diag */
718 return 0;
719
720 if (in_len - (i-1) > 32) /* maximum 32 octets */
721 return 0;
722
723 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800724 memcpy(cause->diag, lv + i, in_len - (i-1));
725 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800726
727 return 0;
728}
729
730/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800731static int encode_cause(struct msgb *msg, int lv_only,
732 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800733{
734 u_int8_t lv[32+4];
735 int i;
736
Harald Welte4bfdfe72009-06-10 23:11:52 +0800737 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800738 return -EINVAL;
739
740 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800741 lv[1] = cause->location;
742 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800743
744 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800746 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800748 }
749 lv[i] |= 0x80; /* end of octet 3 */
750
751 /* octet 4 */
752 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800753 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800754
755 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800756 if (cause->diag_len) {
757 memcpy(lv + i, cause->diag, cause->diag_len);
758 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800759 }
760
761 lv[0] = i;
762 if (lv_only)
763 msgb_lv_put(msg, lv[0], lv+1);
764 else
765 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
766
767 return 0;
768}
769
770/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800771static int encode_calling(struct msgb *msg,
772 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800773{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800774 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800775}
776
777/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800778static int encode_connected(struct msgb *msg,
779 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800780{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800781 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800782}
783
784/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800785static int encode_redirecting(struct msgb *msg,
786 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800787{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800788 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800789}
790
791/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800792static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800793 const u_int8_t *lv)
794{
795 u_int8_t in_len = lv[0];
796
797 if (in_len < 1)
798 return -EINVAL;
799
Harald Welte4bfdfe72009-06-10 23:11:52 +0800800 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800801 return -EINVAL;
802
Harald Welte4bfdfe72009-06-10 23:11:52 +0800803 memcpy(facility->info, lv+1, in_len);
804 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800805
806 return 0;
807}
808
809/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800810static int encode_facility(struct msgb *msg, int lv_only,
811 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800812{
813 u_int8_t lv[GSM_MAX_FACILITY + 1];
814
Harald Welte4bfdfe72009-06-10 23:11:52 +0800815 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800816 return -EINVAL;
817
Harald Welte4bfdfe72009-06-10 23:11:52 +0800818 memcpy(lv+1, facility->info, facility->len);
819 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800820 if (lv_only)
821 msgb_lv_put(msg, lv[0], lv+1);
822 else
823 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
824
825 return 0;
826}
827
828/* decode 'notify' */
829static int decode_notify(int *notify, const u_int8_t *v)
830{
831 *notify = v[0] & 0x7f;
832
833 return 0;
834}
835
836/* encode 'notify' */
837static int encode_notify(struct msgb *msg, int notify)
838{
839 msgb_v_put(msg, notify | 0x80);
840
841 return 0;
842}
843
844/* encode 'signal' */
845static int encode_signal(struct msgb *msg, int signal)
846{
847 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
848
849 return 0;
850}
851
852/* decode 'keypad' */
853static int decode_keypad(int *keypad, const u_int8_t *lv)
854{
855 u_int8_t in_len = lv[0];
856
857 if (in_len < 1)
858 return -EINVAL;
859
860 *keypad = lv[1] & 0x7f;
861
862 return 0;
863}
864
865/* encode 'keypad' */
866static int encode_keypad(struct msgb *msg, int keypad)
867{
868 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
869
870 return 0;
871}
872
873/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800874static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800875 const u_int8_t *lv)
876{
877 u_int8_t in_len = lv[0];
878
879 if (in_len < 2)
880 return -EINVAL;
881
Harald Welte4bfdfe72009-06-10 23:11:52 +0800882 progress->coding = (lv[1] & 0x60) >> 5;
883 progress->location = lv[1] & 0x0f;
884 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800885
886 return 0;
887}
888
889/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800890static int encode_progress(struct msgb *msg, int lv_only,
891 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800892{
893 u_int8_t lv[3];
894
895 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800896 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
897 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800898 if (lv_only)
899 msgb_lv_put(msg, lv[0], lv+1);
900 else
901 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
902
903 return 0;
904}
905
906/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800907static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800908 const u_int8_t *lv)
909{
910 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800911 char *info = uu->info;
912 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800913 int i;
914
915 if (in_len < 1)
916 return -EINVAL;
917
Harald Welte4bfdfe72009-06-10 23:11:52 +0800918 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800919
920 for (i = 2; i <= in_len; i++) {
921 info_len--;
922 if (info_len <= 1)
923 break;
924 *info++ = lv[i];
925 }
926 if (info_len >= 1)
927 *info++ = '\0';
928
929 return 0;
930}
931
932/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800933static int encode_useruser(struct msgb *msg, int lv_only,
934 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800935{
936 u_int8_t lv[GSM_MAX_USERUSER + 2];
937
Harald Welte4bfdfe72009-06-10 23:11:52 +0800938 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800939 return -EINVAL;
940
Harald Welte4bfdfe72009-06-10 23:11:52 +0800941 lv[0] = 1 + strlen(uu->info);
942 lv[1] = uu->proto;
943 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800944 if (lv_only)
945 msgb_lv_put(msg, lv[0], lv+1);
946 else
947 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
948
949 return 0;
950}
951
952/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800953static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800954 const u_int8_t *lv)
955{
956 u_int8_t in_len = lv[0];
957
Harald Welte4bfdfe72009-06-10 23:11:52 +0800958 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800959 return -EINVAL;
960
Harald Welte4bfdfe72009-06-10 23:11:52 +0800961 memcpy(ssv->info, lv + 1, in_len);
962 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800963
964 return 0;
965}
966
967/* encode 'more data' */
968static int encode_more(struct msgb *msg)
969{
970 u_int8_t *ie;
971
972 ie = msgb_put(msg, 1);
973 ie[0] = GSM48_IE_MORE_DATA;
974
975 return 0;
976}
977
Holger Freyther819dd202009-01-04 03:52:50 +0000978struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000979{
Harald Welte966636f2009-06-26 19:39:35 +0200980 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
981 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000982}
983
Holger Freyther3e2c3232009-01-04 03:55:31 +0000984int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000985{
Harald Welte65e74cc2008-12-29 01:55:35 +0000986 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800987 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000988 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000989
Harald Welte4bfdfe72009-06-10 23:11:52 +0800990 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
991 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
992 "Sending '%s' to MS.\n", msg->trx->bts->nr,
993 msg->trx->nr, msg->lchan->ts->nr,
994 gh->proto_discr & 0xf0,
995 cc_msg_names[gh->msg_type & 0x3f]);
996 else
997 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
998 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
999 msg->trx->nr, msg->lchan->ts->nr,
1000 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001001 }
1002
Harald Welte4b634542008-12-27 01:55:51 +00001003 msg->l3h = msg->data;
1004
Harald Welte8470bf22008-12-25 23:28:35 +00001005 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001006}
1007
Holger Freyther429e7762008-12-30 13:28:30 +00001008/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001009int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001010{
Harald Welte8470bf22008-12-25 23:28:35 +00001011 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001012 struct gsm48_hdr *gh;
1013
Harald Welte8470bf22008-12-25 23:28:35 +00001014 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001015
1016 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1017 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001018 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001019 gh->data[0] = cause;
1020
Harald Weltedb253af2008-12-30 17:56:55 +00001021 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1022
Harald Welte65e74cc2008-12-29 01:55:35 +00001023 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001024}
1025
1026/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001027int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001028{
Harald Welte8470bf22008-12-25 23:28:35 +00001029 struct gsm_bts *bts = lchan->ts->trx->bts;
1030 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001031 struct gsm48_hdr *gh;
1032 struct gsm48_loc_area_id *lai;
1033 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001034 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001035
Harald Welte8470bf22008-12-25 23:28:35 +00001036 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001037
1038 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1039 gh->proto_discr = GSM48_PDISC_MM;
1040 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1041
1042 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001043 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001044 bts->network->network_code, bts->location_area_code);
1045
1046 mid = msgb_put(msg, MID_TMSI_LEN);
1047 generate_mid_from_tmsi(mid, tmsi);
1048
1049 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1050
Harald Weltedb253af2008-12-30 17:56:55 +00001051 ret = gsm48_sendmsg(msg);
1052
Harald Weltedb253af2008-12-30 17:56:55 +00001053 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001054
Holger Freyther07cc8d82008-12-29 06:23:46 +00001055 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001056}
1057
Harald Weltefc977a82008-12-27 10:19:37 +00001058static char bcd2char(u_int8_t bcd)
1059{
1060 if (bcd < 0xa)
1061 return '0' + bcd;
1062 else
1063 return 'A' + (bcd - 0xa);
1064}
1065
Harald Weltebf5e8df2009-02-03 12:59:45 +00001066/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001067static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1068{
1069 int i;
1070 u_int8_t mi_type;
1071 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001072 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001073
1074 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1075
1076 switch (mi_type) {
1077 case GSM_MI_TYPE_NONE:
1078 break;
1079 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001080 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1081 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1082 memcpy(&tmsi, &mi[1], 4);
1083 tmsi = ntohl(tmsi);
1084 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001085 }
1086 break;
1087 case GSM_MI_TYPE_IMSI:
1088 case GSM_MI_TYPE_IMEI:
1089 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001090 *str_cur++ = bcd2char(mi[0] >> 4);
1091
1092 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001093 if (str_cur + 2 >= string + str_len)
1094 return str_cur - string;
1095 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001096 /* skip last nibble in last input byte when GSM_EVEN */
1097 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1098 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001099 }
1100 break;
1101 default:
1102 break;
1103 }
Harald Weltefc977a82008-12-27 10:19:37 +00001104 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001105
Harald Weltefc977a82008-12-27 10:19:37 +00001106 return str_cur - string;
1107}
1108
Harald Weltebf5e8df2009-02-03 12:59:45 +00001109/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001110static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1111{
1112 struct msgb *msg = gsm48_msgb_alloc();
1113 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001114
Harald Welte231ad4f2008-12-27 11:15:38 +00001115 msg->lchan = lchan;
1116
1117 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1118 gh->proto_discr = GSM48_PDISC_MM;
1119 gh->msg_type = GSM48_MT_MM_ID_REQ;
1120 gh->data[0] = id_type;
1121
Harald Welte65e74cc2008-12-29 01:55:35 +00001122 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001123}
1124
1125#define MI_SIZE 32
1126
Harald Weltebf5e8df2009-02-03 12:59:45 +00001127/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001128static int mm_rx_id_resp(struct msgb *msg)
1129{
1130 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001131 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001132 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1133 char mi_string[MI_SIZE];
1134
1135 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001136 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001137 mi_type, mi_string);
1138
Harald Welte75a983f2008-12-27 21:34:06 +00001139 switch (mi_type) {
1140 case GSM_MI_TYPE_IMSI:
1141 if (!lchan->subscr)
1142 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001143 if (lchan->loc_operation)
1144 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001145 break;
1146 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001147 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001148 /* update subscribe <-> IMEI mapping */
1149 if (lchan->subscr)
1150 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001151 if (lchan->loc_operation)
1152 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001153 break;
1154 }
Holger Freyther73487a22008-12-31 18:53:57 +00001155
1156 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001157 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001158}
1159
Harald Welte255539c2008-12-28 02:26:27 +00001160
1161static void loc_upd_rej_cb(void *data)
1162{
1163 struct gsm_lchan *lchan = data;
1164
Holger Freyther73487a22008-12-31 18:53:57 +00001165 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001166 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001167 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001168}
1169
Holger Freytherb7193e42008-12-29 17:44:08 +00001170static void schedule_reject(struct gsm_lchan *lchan)
1171{
Holger Freyther73487a22008-12-31 18:53:57 +00001172 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1173 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001174 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001175}
1176
Harald Welte2a139372009-02-22 21:14:55 +00001177static const char *lupd_name(u_int8_t type)
1178{
1179 switch (type) {
1180 case GSM48_LUPD_NORMAL:
1181 return "NORMAL";
1182 case GSM48_LUPD_PERIODIC:
1183 return "PEROIDOC";
1184 case GSM48_LUPD_IMSI_ATT:
1185 return "IMSI ATTACH";
1186 default:
1187 return "UNKNOWN";
1188 }
1189}
1190
Harald Welte231ad4f2008-12-27 11:15:38 +00001191#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001192/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001193static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001194{
Harald Welte8470bf22008-12-25 23:28:35 +00001195 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001196 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001197 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001198 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001199 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001200 char mi_string[MI_SIZE];
1201 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001202
Harald Welte8470bf22008-12-25 23:28:35 +00001203 lu = (struct gsm48_loc_upd_req *) gh->data;
1204
1205 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001206
Harald Weltefc977a82008-12-27 10:19:37 +00001207 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1208
Harald Weltea0368542009-06-27 02:58:43 +02001209 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001210 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001211
Holger Freythereaf04692009-06-06 13:54:44 +00001212 /*
1213 * Pseudo Spoof detection: Just drop a second/concurrent
1214 * location updating request.
1215 */
1216 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001217 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001218 lchan->loc_operation);
1219 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1220 return 0;
1221 }
1222
Holger Freyther73487a22008-12-31 18:53:57 +00001223 allocate_loc_updating_req(lchan);
1224
Harald Welte52b1f982008-12-23 20:25:15 +00001225 switch (mi_type) {
1226 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001227 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001228 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001229 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001230 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001231
Harald Welte52b1f982008-12-23 20:25:15 +00001232 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001233 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001234 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001235 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001236 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001237 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001238 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001239 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001240
Harald Welte52b1f982008-12-23 20:25:15 +00001241 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001242 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001243 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001244 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001245 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001246 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001247 }
1248 break;
1249 case GSM_MI_TYPE_IMEI:
1250 case GSM_MI_TYPE_IMEISV:
1251 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001252 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001253 break;
1254 default:
Harald Weltea0368542009-06-27 02:58:43 +02001255 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001256 break;
1257 }
1258
Harald Welte24516ea2009-07-04 10:18:00 +02001259 /* schedule the reject timer */
1260 schedule_reject(lchan);
1261
Harald Welte4bfdfe72009-06-10 23:11:52 +08001262 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001263 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001264 /* FIXME: request id? close channel? */
1265 return -EINVAL;
1266 }
1267
Harald Welte255539c2008-12-28 02:26:27 +00001268 lchan->subscr = subscr;
1269
Harald Welte24516ea2009-07-04 10:18:00 +02001270 /* check if we can let the subscriber into our network immediately
1271 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001272 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001273}
1274
Harald Welte7584aea2009-02-11 11:44:12 +00001275/* 9.1.5 Channel mode modify */
1276int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1277{
1278 struct msgb *msg = gsm48_msgb_alloc();
1279 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1280 struct gsm48_chan_mode_modify *cmm =
1281 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001282 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001283
Harald Welte4a543e82009-02-28 13:17:55 +00001284 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001285
Harald Welte45b407a2009-05-23 15:51:12 +00001286 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001287 msg->lchan = lchan;
1288 gh->proto_discr = GSM48_PDISC_RR;
1289 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1290
1291 /* fill the channel information element, this code
1292 * should probably be shared with rsl_rx_chan_rqd() */
1293 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001294 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001295 cmm->chan_desc.h0.h = 0;
1296 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1297 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1298 cmm->mode = mode;
1299
1300 return gsm48_sendmsg(msg);
1301}
1302
Harald Welte4bfdfe72009-06-10 23:11:52 +08001303#if 0
1304static u_int8_t to_bcd8(u_int8_t val)
1305{
1306 return ((val / 10) << 4) | (val % 10);
1307}
1308#endif
1309
Harald Weltedb253af2008-12-30 17:56:55 +00001310/* Section 9.2.15a */
1311int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1312{
1313 struct msgb *msg = gsm48_msgb_alloc();
1314 struct gsm48_hdr *gh;
1315 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001316 u_int8_t *ptr8;
1317 u_int16_t *ptr16;
1318 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001319 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001320#if 0
1321 time_t cur_t;
1322 struct tm* cur_time;
1323 int tz15min;
1324#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001325
1326 msg->lchan = lchan;
1327
1328 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1329 gh->proto_discr = GSM48_PDISC_MM;
1330 gh->msg_type = GSM48_MT_MM_INFO;
1331
1332 if (net->name_long) {
1333 name_len = strlen(net->name_long);
1334 /* 10.5.3.5a */
1335 ptr8 = msgb_put(msg, 3);
1336 ptr8[0] = GSM48_IE_NAME_LONG;
1337 ptr8[1] = name_len*2 +1;
1338 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1339
1340 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1341 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001342 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001343
1344 /* FIXME: Use Cell Broadcast, not UCS-2, since
1345 * UCS-2 is only supported by later revisions of the spec */
1346 }
1347
1348 if (net->name_short) {
1349 name_len = strlen(net->name_short);
1350 /* 10.5.3.5a */
1351 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001352 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001353 ptr8[1] = name_len*2 + 1;
1354 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1355
Harald Weltee872cb12009-01-01 00:33:37 +00001356 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001357 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001358 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001359 }
1360
1361#if 0
1362 /* Section 10.5.3.9 */
1363 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001364 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001365 ptr8 = msgb_put(msg, 8);
1366 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1367 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1368 ptr8[2] = to_bcd8(cur_time->tm_mon);
1369 ptr8[3] = to_bcd8(cur_time->tm_mday);
1370 ptr8[4] = to_bcd8(cur_time->tm_hour);
1371 ptr8[5] = to_bcd8(cur_time->tm_min);
1372 ptr8[6] = to_bcd8(cur_time->tm_sec);
1373 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1374 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001375 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001376 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001377 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001378#endif
1379
1380 return gsm48_sendmsg(msg);
1381}
1382
Harald Welte4b634542008-12-27 01:55:51 +00001383static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1384{
Harald Welte4b634542008-12-27 01:55:51 +00001385 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001386 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001387}
Harald Welteba4cf162009-01-10 01:49:35 +00001388
1389/* 9.2.6 CM service reject */
1390static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1391 enum gsm48_reject_value value)
1392{
1393 struct msgb *msg = gsm48_msgb_alloc();
1394 struct gsm48_hdr *gh;
1395
1396 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1397
1398 msg->lchan = lchan;
1399 use_lchan(lchan);
1400
1401 gh->proto_discr = GSM48_PDISC_MM;
1402 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1403 gh->data[0] = value;
1404 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1405
1406 return gsm48_sendmsg(msg);
1407}
1408
Harald Welte4ed0e922009-01-10 03:17:30 +00001409
1410/*
1411 * Handle CM Service Requests
1412 * a) Verify that the packet is long enough to contain the information
1413 * we require otherwsie reject with INCORRECT_MESSAGE
1414 * b) Try to parse the TMSI. If we do not have one reject
1415 * c) Check that we know the subscriber with the TMSI otherwise reject
1416 * with a HLR cause
1417 * d) Set the subscriber on the gsm_lchan and accept
1418 */
Harald Welte4b634542008-12-27 01:55:51 +00001419static int gsm48_rx_mm_serv_req(struct msgb *msg)
1420{
Harald Welteba4cf162009-01-10 01:49:35 +00001421 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001422 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001423
Harald Welteba4cf162009-01-10 01:49:35 +00001424 struct gsm_subscriber *subscr;
1425 struct gsm48_hdr *gh = msgb_l3(msg);
1426 struct gsm48_service_request *req =
1427 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001428 /* unfortunately in Phase1 the classmar2 length is variable */
1429 u_int8_t classmark2_len = gh->data[1];
1430 u_int8_t *classmark2 = gh->data+2;
1431 u_int8_t mi_len = *(classmark2 + classmark2_len);
1432 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001433
Harald Weltec9e02182009-05-01 19:07:53 +00001434 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001435 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001436 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001437 return gsm48_tx_mm_serv_rej(msg->lchan,
1438 GSM48_REJECT_INCORRECT_MESSAGE);
1439 }
1440
1441 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001442 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001443 return gsm48_tx_mm_serv_rej(msg->lchan,
1444 GSM48_REJECT_INCORRECT_MESSAGE);
1445 }
1446
Harald Weltec9e02182009-05-01 19:07:53 +00001447 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001448 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001449 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001450 return gsm48_tx_mm_serv_rej(msg->lchan,
1451 GSM48_REJECT_INCORRECT_MESSAGE);
1452 }
1453
Harald Weltec9e02182009-05-01 19:07:53 +00001454 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001455 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001456 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001457
Holger Freythereb443982009-06-04 13:58:42 +00001458 subscr = subscr_get_by_tmsi(mi_string);
1459
Harald Welte2a139372009-02-22 21:14:55 +00001460 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001461 if (!subscr)
1462 return gsm48_tx_mm_serv_rej(msg->lchan,
1463 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1464
1465 if (!msg->lchan->subscr)
1466 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001467 else if (msg->lchan->subscr != subscr) {
1468 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1469 subscr_put(subscr);
1470 }
1471
Harald Weltec2e302d2009-07-05 14:08:13 +02001472 subscr->equipment.classmark2_len = classmark2_len;
1473 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1474 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001475
Harald Welte4b634542008-12-27 01:55:51 +00001476 return gsm48_tx_mm_serv_ack(msg->lchan);
1477}
1478
Harald Welte2a139372009-02-22 21:14:55 +00001479static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1480{
1481 struct gsm48_hdr *gh = msgb_l3(msg);
1482 struct gsm48_imsi_detach_ind *idi =
1483 (struct gsm48_imsi_detach_ind *) gh->data;
1484 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1485 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001486 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001487
1488 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1489 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1490 mi_type, mi_string);
1491
1492 switch (mi_type) {
1493 case GSM_MI_TYPE_TMSI:
1494 subscr = subscr_get_by_tmsi(mi_string);
1495 break;
1496 case GSM_MI_TYPE_IMSI:
1497 subscr = subscr_get_by_imsi(mi_string);
1498 break;
1499 case GSM_MI_TYPE_IMEI:
1500 case GSM_MI_TYPE_IMEISV:
1501 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001502 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001503 break;
1504 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001505 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001506 break;
1507 }
1508
Holger Freyther4a49e772009-04-12 05:37:29 +00001509 if (subscr) {
1510 subscr_update(subscr, msg->trx->bts,
1511 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001512 DEBUGP(DMM, "Subscriber: %s\n",
1513 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001514 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001515 } else
Harald Welte2a139372009-02-22 21:14:55 +00001516 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1517
Harald Welte2a139372009-02-22 21:14:55 +00001518 return 0;
1519}
1520
Harald Welted2a7f5a2009-06-05 20:08:20 +00001521static int gsm48_rx_mm_status(struct msgb *msg)
1522{
1523 struct gsm48_hdr *gh = msgb_l3(msg);
1524
1525 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1526
1527 return 0;
1528}
1529
Harald Weltebf5e8df2009-02-03 12:59:45 +00001530/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001531static int gsm0408_rcv_mm(struct msgb *msg)
1532{
1533 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001534 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001535
1536 switch (gh->msg_type & 0xbf) {
1537 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001538 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001539 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001540 break;
1541 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001542 rc = mm_rx_id_resp(msg);
1543 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001544 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001545 rc = gsm48_rx_mm_serv_req(msg);
1546 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001547 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001548 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001549 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001550 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001551 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1552 msg->lchan->subscr ?
1553 msg->lchan->subscr->imsi :
1554 "unknown subscriber");
1555 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001556 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001557 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1558 break;
1559 case GSM48_MT_MM_CM_REEST_REQ:
1560 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1561 break;
1562 case GSM48_MT_MM_AUTH_RESP:
1563 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001564 break;
1565 default:
1566 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1567 gh->msg_type);
1568 break;
1569 }
1570
1571 return rc;
1572}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001573
Harald Welte2d35ae62009-02-06 12:02:13 +00001574/* Receive a PAGING RESPONSE message from the MS */
1575static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1576{
1577 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001578 u_int8_t *classmark2_lv = gh->data + 1;
1579 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1580 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001581 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001582 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001583 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001584 int rc = 0;
1585
Harald Welte61548982009-02-22 21:26:29 +00001586 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001587 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1588 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001589 switch (mi_type) {
1590 case GSM_MI_TYPE_TMSI:
1591 subscr = subscr_get_by_tmsi(mi_string);
1592 break;
1593 case GSM_MI_TYPE_IMSI:
1594 subscr = subscr_get_by_imsi(mi_string);
1595 break;
1596 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001597
1598 if (!subscr) {
1599 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001600 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001601 return -EINVAL;
1602 }
1603 DEBUGP(DRR, "<- Channel was requested by %s\n",
1604 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001605
Harald Weltec2e302d2009-07-05 14:08:13 +02001606 subscr->equipment.classmark2_len = *classmark2_lv;
1607 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1608 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001609
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) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001672 subscr->equipment.classmark2_len = cm2_len;
1673 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001674 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001675 subscr->equipment.classmark3_len = cm3_len;
1676 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001677 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001678 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001679 }
1680
Harald Weltef7c43522009-06-09 20:24:21 +00001681 return 0;
1682}
1683
Harald Weltecf5b3592009-05-01 18:28:42 +00001684static int gsm48_rx_rr_status(struct msgb *msg)
1685{
1686 struct gsm48_hdr *gh = msgb_l3(msg);
1687
1688 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1689 rr_cause_name(gh->data[0]));
1690
1691 return 0;
1692}
1693
Harald Weltef7c43522009-06-09 20:24:21 +00001694static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1695{
1696 struct gsm48_hdr *gh = msgb_l3(msg);
1697 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1698 static struct gsm_meas_rep meas_rep;
1699
Harald Welte10d0e672009-06-27 02:53:10 +02001700 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001701 parse_meas_rep(&meas_rep, gh->data, payload_len);
1702 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001703 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001704 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001705 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001706 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001707 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001708 else
Harald Welte10d0e672009-06-27 02:53:10 +02001709 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001710 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1711 meas_rep.rxqual_sub);
1712
Harald Welte10d0e672009-06-27 02:53:10 +02001713 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001714
1715 /* FIXME: put the results somwhere */
1716
1717 return 0;
1718}
1719
Harald Weltebf5e8df2009-02-03 12:59:45 +00001720/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001721static int gsm0408_rcv_rr(struct msgb *msg)
1722{
1723 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001724 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001725
1726 switch (gh->msg_type) {
1727 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001728 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001729 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001730 case GSM48_MT_RR_GPRS_SUSP_REQ:
1731 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1732 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001733 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001734 rc = gsm48_rr_rx_pag_resp(msg);
1735 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001736 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1737 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001738 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001739 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001740 case GSM48_MT_RR_STATUS:
1741 rc = gsm48_rx_rr_status(msg);
1742 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001743 case GSM48_MT_RR_MEAS_REP:
1744 rc = gsm48_rx_rr_meas_rep(msg);
1745 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001746 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001747 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001748 gh->msg_type);
1749 break;
1750 }
1751
Harald Welte2d35ae62009-02-06 12:02:13 +00001752 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001753}
1754
Holger Freythere64a7a32009-02-06 21:55:37 +00001755/* 7.1.7 and 9.1.7 Channel release*/
1756int gsm48_send_rr_release(struct gsm_lchan *lchan)
1757{
1758 struct msgb *msg = gsm48_msgb_alloc();
1759 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1760 u_int8_t *cause;
1761
1762 msg->lchan = lchan;
1763 gh->proto_discr = GSM48_PDISC_RR;
1764 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1765
1766 cause = msgb_put(msg, 1);
1767 cause[0] = GSM48_RR_CAUSE_NORMAL;
1768
1769 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1770 lchan->nr, lchan->type);
1771
Harald Welteae0f2362009-07-19 18:36:49 +02001772 /* Send actual release request to MS */
1773 gsm48_sendmsg(msg);
1774
1775 /* Deactivate the SACCH on the BTS side */
1776 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001777}
1778
Harald Welte4bc90a12008-12-27 16:32:52 +00001779/* Call Control */
1780
Harald Welte7584aea2009-02-11 11:44:12 +00001781/* The entire call control code is written in accordance with Figure 7.10c
1782 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1783 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1784 * it for voice */
1785
Harald Welte4bfdfe72009-06-10 23:11:52 +08001786static void new_cc_state(struct gsm_trans *trans, int state)
1787{
1788 if (state > 31 || state < 0)
1789 return;
1790
1791 DEBUGP(DCC, "new state %s -> %s\n",
1792 cc_state_names[trans->state], cc_state_names[state]);
1793
1794 trans->state = state;
1795}
1796
1797static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001798{
1799 struct msgb *msg = gsm48_msgb_alloc();
1800 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1801 u_int8_t *cause, *call_state;
1802
Harald Welte4bfdfe72009-06-10 23:11:52 +08001803 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1804 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001805 gh->msg_type = GSM48_MT_CC_STATUS;
1806
1807 cause = msgb_put(msg, 3);
1808 cause[0] = 2;
1809 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1810 cause[2] = 0x80 | 30; /* response to status inquiry */
1811
1812 call_state = msgb_put(msg, 1);
1813 call_state[0] = 0xc0 | 0x00;
1814
Harald Welte65e74cc2008-12-29 01:55:35 +00001815 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001816}
1817
Harald Welte6f4b7532008-12-29 00:39:37 +00001818static int gsm48_tx_simple(struct gsm_lchan *lchan,
1819 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001820{
1821 struct msgb *msg = gsm48_msgb_alloc();
1822 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1823
1824 msg->lchan = lchan;
1825
Harald Welte6f4b7532008-12-29 00:39:37 +00001826 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001827 gh->msg_type = msg_type;
1828
Harald Welte65e74cc2008-12-29 01:55:35 +00001829 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001830}
1831
Harald Welte4bfdfe72009-06-10 23:11:52 +08001832static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1833{
1834 if (bsc_timer_pending(&trans->cc_timer)) {
1835 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1836 bsc_del_timer(&trans->cc_timer);
1837 trans->Tcurrent = 0;
1838 }
1839}
1840
1841static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1842 int msg_type, struct gsm_mncc *mncc)
1843{
1844 struct msgb *msg;
1845
1846 if (trans)
1847 if (trans->lchan)
1848 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1849 "Sending '%s' to MNCC.\n",
1850 trans->lchan->ts->trx->bts->nr,
1851 trans->lchan->ts->trx->nr,
1852 trans->lchan->ts->nr, trans->transaction_id,
1853 (trans->subscr)?(trans->subscr->extension):"-",
1854 get_mncc_name(msg_type));
1855 else
1856 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1857 "Sending '%s' to MNCC.\n",
1858 (trans->subscr)?(trans->subscr->extension):"-",
1859 get_mncc_name(msg_type));
1860 else
1861 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1862 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1863
1864 mncc->msg_type = msg_type;
1865
Harald Welte966636f2009-06-26 19:39:35 +02001866 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001867 if (!msg)
1868 return -ENOMEM;
1869 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1870 msgb_enqueue(&net->upqueue, msg);
1871
1872 return 0;
1873}
1874
1875int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1876 u_int32_t callref, int location, int value)
1877{
1878 struct gsm_mncc rel;
1879
Harald Welte92f70c52009-06-12 01:54:08 +08001880 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001881 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001882 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001883 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1884}
1885
1886void free_trans(struct gsm_trans *trans)
1887{
1888 struct gsm_bts *bts;
1889
1890 gsm48_stop_cc_timer(trans);
1891
1892 /* send release to L4, if callref still exists */
1893 if (trans->callref) {
1894 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001895 mncc_release_ind(trans->network, trans, trans->callref,
1896 GSM48_CAUSE_LOC_PRN_S_LU,
1897 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001898 if (trans->state != GSM_CSTATE_NULL)
1899 new_cc_state(trans, GSM_CSTATE_NULL);
1900 }
1901
1902 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1903 /* Stop paging on all bts' */
1904 bts = NULL;
1905 do {
1906 bts = gsm_bts_by_lac(trans->subscr->net,
1907 trans->subscr->lac, bts);
1908 if (!bts)
1909 break;
1910 /* Stop paging */
1911 paging_request_stop(bts, trans->subscr, NULL);
1912 } while (1);
1913 }
1914
1915 if (trans->lchan) {
1916 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1917 put_lchan(trans->lchan);
1918 }
1919
1920 if (trans->subscr)
1921 subscr_put(trans->subscr);
1922
1923 if (trans->state != GSM_CSTATE_NULL)
1924 new_cc_state(trans, GSM_CSTATE_NULL);
1925
1926 llist_del(&trans->entry);
1927
Harald Welte2cf161b2009-06-20 22:36:41 +02001928 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001929}
1930
1931static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1932
Harald Welte09e38af2009-02-16 22:52:23 +00001933/* call-back from paging the B-end of the connection */
1934static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001935 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001936{
Harald Welte7ccf7782009-02-17 01:43:01 +00001937 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001938 struct gsm_subscriber *subscr = param;
1939 struct gsm_trans *transt, *tmp;
1940 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001941
Harald Welte09e38af2009-02-16 22:52:23 +00001942 if (hooknum != GSM_HOOK_RR_PAGING)
1943 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001944
1945 if (!subscr)
1946 return -EINVAL;
1947 net = subscr->net;
1948 if (!net) {
1949 DEBUGP(DCC, "Error Network not set!\n");
1950 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001951 }
Harald Welte7584aea2009-02-11 11:44:12 +00001952
Harald Welte4bfdfe72009-06-10 23:11:52 +08001953 /* check all tranactions (without lchan) for subscriber */
1954 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1955 if (transt->subscr != subscr || transt->lchan)
1956 continue;
1957 switch (event) {
1958 case GSM_PAGING_SUCCEEDED:
1959 if (!lchan) // paranoid
1960 break;
1961 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1962 subscr->extension);
1963 /* Assign lchan */
1964 if (!transt->lchan) {
1965 transt->lchan = lchan;
1966 use_lchan(lchan);
1967 }
1968 /* send SETUP request to called party */
1969 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1970 if (is_ipaccess_bts(lchan->ts->trx->bts))
1971 rsl_ipacc_bind(lchan);
1972 break;
1973 case GSM_PAGING_EXPIRED:
1974 DEBUGP(DCC, "Paging subscr %s expired!\n",
1975 subscr->extension);
1976 /* Temporarily out of order */
1977 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001978 GSM48_CAUSE_LOC_PRN_S_LU,
1979 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001980 transt->callref = 0;
1981 free_trans(transt);
1982 break;
1983 }
1984 }
Harald Welte09e38af2009-02-16 22:52:23 +00001985 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001986}
Harald Welte7584aea2009-02-11 11:44:12 +00001987
Harald Welte49f48b82009-02-17 15:29:33 +00001988/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001989static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001990{
Harald Welte11fa29c2009-02-19 17:24:39 +00001991 struct gsm_bts *bts = lchan->ts->trx->bts;
1992 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001993 struct gsm_bts_trx_ts *ts;
1994
Harald Welte11fa29c2009-02-19 17:24:39 +00001995 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1996 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1997 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1998
1999 if (bts->type != remote_bts->type) {
2000 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2001 return -EINVAL;
2002 }
Harald Welte49f48b82009-02-17 15:29:33 +00002003
Harald Welte11fa29c2009-02-19 17:24:39 +00002004 switch (bts->type) {
2005 case GSM_BTS_TYPE_NANOBTS_900:
2006 case GSM_BTS_TYPE_NANOBTS_1800:
2007 ts = remote_lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002008 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2009 ts->abis_ip.bound_port,
2010 lchan->ts->abis_ip.conn_id,
2011 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002012
2013 ts = lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002014 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2015 ts->abis_ip.bound_port,
2016 remote_lchan->ts->abis_ip.conn_id,
2017 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002018 break;
2019 case GSM_BTS_TYPE_BS11:
2020 trau_mux_map_lchan(lchan, remote_lchan);
2021 break;
2022 default:
2023 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2024 break;
2025 }
Harald Welte49f48b82009-02-17 15:29:33 +00002026
2027 return 0;
2028}
2029
Harald Welte4bfdfe72009-06-10 23:11:52 +08002030static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002031{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002032 struct gsm_trans *trans;
2033 llist_for_each_entry(trans, &net->trans_list, entry) {
2034 if (trans->callref == callref)
2035 return trans;
2036 }
2037 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002038}
2039
Harald Welte4bfdfe72009-06-10 23:11:52 +08002040/* bridge channels of two transactions */
2041static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002042{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002043 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2044 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002045
Harald Welte4bfdfe72009-06-10 23:11:52 +08002046 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002047 return -EIO;
2048
Harald Welte4bfdfe72009-06-10 23:11:52 +08002049 if (!trans1->lchan || !trans2->lchan)
2050 return -EIO;
2051
2052 /* through-connect channel */
2053 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002054}
2055
Harald Welte4bfdfe72009-06-10 23:11:52 +08002056/* enable receive of channels to upqueue */
2057static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2058{
2059 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002060
Harald Welte4bfdfe72009-06-10 23:11:52 +08002061 /* Find callref */
2062 trans = get_trans_ref(net, data->callref);
2063 if (!trans)
2064 return -EIO;
2065 if (!trans->lchan)
2066 return 0;
2067
2068 // todo IPACCESS
2069 if (enable)
2070 return trau_recv_lchan(trans->lchan, data->callref);
2071 return trau_mux_unmap(NULL, data->callref);
2072}
2073
2074/* send a frame to channel */
2075static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2076{
2077 struct gsm_trans *trans;
2078
2079 /* Find callref */
2080 trans = get_trans_ref(net, frame->callref);
2081 if (!trans)
2082 return -EIO;
2083 if (!trans->lchan)
2084 return 0;
2085 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2086 trans->lchan->type != GSM_LCHAN_TCH_H)
2087 return 0;
2088
2089 // todo IPACCESS
2090 return trau_send_lchan(trans->lchan,
2091 (struct decoded_trau_frame *)frame->data);
2092}
2093
2094
2095static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2096{
2097 DEBUGP(DCC, "-> STATUS ENQ\n");
2098 return gsm48_cc_tx_status(trans, msg);
2099}
2100
2101static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2102static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2103
2104static void gsm48_cc_timeout(void *arg)
2105{
2106 struct gsm_trans *trans = arg;
2107 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002108 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2109 int mo_location = GSM48_CAUSE_LOC_USER;
2110 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2111 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002112 struct gsm_mncc mo_rel, l4_rel;
2113
2114 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2115 mo_rel.callref = trans->callref;
2116 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2117 l4_rel.callref = trans->callref;
2118
2119 switch(trans->Tcurrent) {
2120 case 0x303:
2121 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002122 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002123 break;
2124 case 0x310:
2125 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002126 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002127 break;
2128 case 0x313:
2129 disconnect = 1;
2130 /* unknown, did not find it in the specs */
2131 break;
2132 case 0x301:
2133 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002134 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002135 break;
2136 case 0x308:
2137 if (!trans->T308_second) {
2138 /* restart T308 a second time */
2139 gsm48_cc_tx_release(trans, &trans->cc_msg);
2140 trans->T308_second = 1;
2141 break; /* stay in release state */
2142 }
2143 free_trans(trans);
2144 return;
2145// release = 1;
2146// l4_cause = 14;
2147// break;
2148 case 0x306:
2149 release = 1;
2150 mo_cause = trans->cc_msg.cause.value;
2151 mo_location = trans->cc_msg.cause.location;
2152 break;
2153 case 0x323:
2154 disconnect = 1;
2155 break;
2156 default:
2157 release = 1;
2158 }
2159
2160 if (release && trans->callref) {
2161 /* process release towards layer 4 */
2162 mncc_release_ind(trans->network, trans, trans->callref,
2163 l4_location, l4_cause);
2164 trans->callref = 0;
2165 }
2166
2167 if (disconnect && trans->callref) {
2168 /* process disconnect towards layer 4 */
2169 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2170 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2171 }
2172
2173 /* process disconnect towards mobile station */
2174 if (disconnect || release) {
2175 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2176 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2177 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2178 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2179 mo_rel.cause.diag_len = 3;
2180
2181 if (disconnect)
2182 gsm48_cc_tx_disconnect(trans, &mo_rel);
2183 if (release)
2184 gsm48_cc_tx_release(trans, &mo_rel);
2185 }
2186
2187}
2188
2189static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2190 int sec, int micro)
2191{
2192 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2193 trans->cc_timer.cb = gsm48_cc_timeout;
2194 trans->cc_timer.data = trans;
2195 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2196 trans->Tcurrent = current;
2197}
2198
2199static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2200{
2201 struct gsm48_hdr *gh = msgb_l3(msg);
2202 u_int8_t msg_type = gh->msg_type & 0xbf;
2203 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2204 struct tlv_parsed tp;
2205 struct gsm_mncc setup;
2206
2207 memset(&setup, 0, sizeof(struct gsm_mncc));
2208 setup.callref = trans->callref;
2209 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2210 /* emergency setup is identified by msg_type */
2211 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2212 setup.emergency = 1;
2213
2214 /* use subscriber as calling party number */
2215 if (trans->subscr) {
2216 setup.fields |= MNCC_F_CALLING;
2217 strncpy(setup.calling.number, trans->subscr->extension,
2218 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002219 strncpy(setup.imsi, trans->subscr->imsi,
2220 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002221 }
2222 /* bearer capability */
2223 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2224 setup.fields |= MNCC_F_BEARER_CAP;
2225 decode_bearer_cap(&setup.bearer_cap,
2226 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2227 }
2228 /* facility */
2229 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2230 setup.fields |= MNCC_F_FACILITY;
2231 decode_facility(&setup.facility,
2232 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2233 }
2234 /* called party bcd number */
2235 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2236 setup.fields |= MNCC_F_CALLED;
2237 decode_called(&setup.called,
2238 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2239 }
2240 /* user-user */
2241 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2242 setup.fields |= MNCC_F_USERUSER;
2243 decode_useruser(&setup.useruser,
2244 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2245 }
2246 /* ss-version */
2247 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2248 setup.fields |= MNCC_F_SSVERSION;
2249 decode_ssversion(&setup.ssversion,
2250 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2251 }
2252 /* CLIR suppression */
2253 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2254 setup.clir.sup = 1;
2255 /* CLIR invocation */
2256 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2257 setup.clir.inv = 1;
2258 /* cc cap */
2259 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2260 setup.fields |= MNCC_F_CCCAP;
2261 decode_cccap(&setup.cccap,
2262 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2263 }
2264
2265 if (is_ipaccess_bts(msg->trx->bts))
2266 rsl_ipacc_bind(msg->lchan);
2267
2268 new_cc_state(trans, GSM_CSTATE_INITIATED);
2269
2270 /* indicate setup to MNCC */
2271 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2272
2273 return 0;
2274}
2275
2276static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002277{
2278 struct msgb *msg = gsm48_msgb_alloc();
2279 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002280 struct gsm_mncc *setup = arg;
2281 struct gsm_trans *transt;
2282 u_int16_t trans_id_mask = 0;
2283 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002284
Harald Welte7ccf7782009-02-17 01:43:01 +00002285 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002286
Harald Welte4bfdfe72009-06-10 23:11:52 +08002287 /* transaction id must not be assigned */
2288 if (trans->transaction_id != 0xff) { /* unasssigned */
2289 DEBUGP(DCC, "TX Setup with assigned transaction. "
2290 "This is not allowed!\n");
2291 /* Temporarily out of order */
2292 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002293 GSM48_CAUSE_LOC_PRN_S_LU,
2294 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002295 trans->callref = 0;
2296 free_trans(trans);
2297 return rc;
2298 }
2299
2300 /* Get free transaction_id */
2301 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2302 /* Transaction of our lchan? */
2303 if (transt->lchan == trans->lchan &&
2304 transt->transaction_id != 0xff)
2305 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2306 }
2307 /* Assign free transaction ID */
2308 if ((trans_id_mask & 0x007f) == 0x7f) {
2309 /* no free transaction ID */
2310 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002311 GSM48_CAUSE_LOC_PRN_S_LU,
2312 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002313 trans->callref = 0;
2314 free_trans(trans);
2315 return rc;
2316 }
2317 for (i = 0; i < 7; i++) {
2318 if ((trans_id_mask & (1 << i)) == 0) {
2319 trans->transaction_id = i << 4; /* flag = 0 */
2320 break;
2321 }
2322 }
Harald Welte49f48b82009-02-17 15:29:33 +00002323
Harald Welte4bfdfe72009-06-10 23:11:52 +08002324 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2325 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002326 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002327
Harald Welte4bfdfe72009-06-10 23:11:52 +08002328 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002329
Harald Welte4bfdfe72009-06-10 23:11:52 +08002330 /* bearer capability */
2331 if (setup->fields & MNCC_F_BEARER_CAP)
2332 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2333 /* facility */
2334 if (setup->fields & MNCC_F_FACILITY)
2335 encode_facility(msg, 0, &setup->facility);
2336 /* progress */
2337 if (setup->fields & MNCC_F_PROGRESS)
2338 encode_progress(msg, 0, &setup->progress);
2339 /* calling party BCD number */
2340 if (setup->fields & MNCC_F_CALLING)
2341 encode_calling(msg, &setup->calling);
2342 /* called party BCD number */
2343 if (setup->fields & MNCC_F_CALLED)
2344 encode_called(msg, &setup->called);
2345 /* user-user */
2346 if (setup->fields & MNCC_F_USERUSER)
2347 encode_useruser(msg, 0, &setup->useruser);
2348 /* redirecting party BCD number */
2349 if (setup->fields & MNCC_F_REDIRECTING)
2350 encode_redirecting(msg, &setup->redirecting);
2351 /* signal */
2352 if (setup->fields & MNCC_F_SIGNAL)
2353 encode_signal(msg, setup->signal);
2354
2355 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002356
2357 return gsm48_sendmsg(msg);
2358}
2359
Harald Welte4bfdfe72009-06-10 23:11:52 +08002360static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2361{
2362 struct gsm48_hdr *gh = msgb_l3(msg);
2363 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2364 struct tlv_parsed tp;
2365 struct gsm_mncc call_conf;
2366
2367 gsm48_stop_cc_timer(trans);
2368 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2369
2370 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2371 call_conf.callref = trans->callref;
2372 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2373#if 0
2374 /* repeat */
2375 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2376 call_conf.repeat = 1;
2377 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2378 call_conf.repeat = 2;
2379#endif
2380 /* bearer capability */
2381 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2382 call_conf.fields |= MNCC_F_BEARER_CAP;
2383 decode_bearer_cap(&call_conf.bearer_cap,
2384 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2385 }
2386 /* cause */
2387 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2388 call_conf.fields |= MNCC_F_CAUSE;
2389 decode_cause(&call_conf.cause,
2390 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2391 }
2392 /* cc cap */
2393 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2394 call_conf.fields |= MNCC_F_CCCAP;
2395 decode_cccap(&call_conf.cccap,
2396 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2397 }
2398
2399 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2400
2401 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2402}
2403
2404static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2405{
2406 struct gsm_mncc *proceeding = arg;
2407 struct msgb *msg = gsm48_msgb_alloc();
2408 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2409
2410 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2411 msg->lchan = trans->lchan;
2412 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2413
2414 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2415
2416 /* bearer capability */
2417 if (proceeding->fields & MNCC_F_BEARER_CAP)
2418 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2419 /* facility */
2420 if (proceeding->fields & MNCC_F_FACILITY)
2421 encode_facility(msg, 0, &proceeding->facility);
2422 /* progress */
2423 if (proceeding->fields & MNCC_F_PROGRESS)
2424 encode_progress(msg, 0, &proceeding->progress);
2425
2426 return gsm48_sendmsg(msg);
2427}
2428
2429static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2430{
2431 struct gsm48_hdr *gh = msgb_l3(msg);
2432 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2433 struct tlv_parsed tp;
2434 struct gsm_mncc alerting;
2435
2436 gsm48_stop_cc_timer(trans);
2437 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2438
2439 memset(&alerting, 0, sizeof(struct gsm_mncc));
2440 alerting.callref = trans->callref;
2441 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2442 /* facility */
2443 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2444 alerting.fields |= MNCC_F_FACILITY;
2445 decode_facility(&alerting.facility,
2446 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2447 }
2448
2449 /* progress */
2450 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2451 alerting.fields |= MNCC_F_PROGRESS;
2452 decode_progress(&alerting.progress,
2453 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2454 }
2455 /* ss-version */
2456 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2457 alerting.fields |= MNCC_F_SSVERSION;
2458 decode_ssversion(&alerting.ssversion,
2459 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2460 }
2461
2462 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2463
2464 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2465}
2466
2467static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2468{
2469 struct gsm_mncc *alerting = arg;
2470 struct msgb *msg = gsm48_msgb_alloc();
2471 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2472
2473 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2474 msg->lchan = trans->lchan;
2475 gh->msg_type = GSM48_MT_CC_ALERTING;
2476
2477 /* facility */
2478 if (alerting->fields & MNCC_F_FACILITY)
2479 encode_facility(msg, 0, &alerting->facility);
2480 /* progress */
2481 if (alerting->fields & MNCC_F_PROGRESS)
2482 encode_progress(msg, 0, &alerting->progress);
2483 /* user-user */
2484 if (alerting->fields & MNCC_F_USERUSER)
2485 encode_useruser(msg, 0, &alerting->useruser);
2486
2487 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2488
2489 return gsm48_sendmsg(msg);
2490}
2491
2492static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2493{
2494 struct gsm_mncc *progress = arg;
2495 struct msgb *msg = gsm48_msgb_alloc();
2496 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2497
2498 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2499 msg->lchan = trans->lchan;
2500 gh->msg_type = GSM48_MT_CC_PROGRESS;
2501
2502 /* progress */
2503 encode_progress(msg, 1, &progress->progress);
2504 /* user-user */
2505 if (progress->fields & MNCC_F_USERUSER)
2506 encode_useruser(msg, 0, &progress->useruser);
2507
2508 return gsm48_sendmsg(msg);
2509}
2510
2511static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2512{
2513 struct gsm_mncc *connect = arg;
2514 struct msgb *msg = gsm48_msgb_alloc();
2515 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2516
2517 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2518 msg->lchan = trans->lchan;
2519 gh->msg_type = GSM48_MT_CC_CONNECT;
2520
2521 gsm48_stop_cc_timer(trans);
2522 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2523
2524 /* facility */
2525 if (connect->fields & MNCC_F_FACILITY)
2526 encode_facility(msg, 0, &connect->facility);
2527 /* progress */
2528 if (connect->fields & MNCC_F_PROGRESS)
2529 encode_progress(msg, 0, &connect->progress);
2530 /* connected number */
2531 if (connect->fields & MNCC_F_CONNECTED)
2532 encode_connected(msg, &connect->connected);
2533 /* user-user */
2534 if (connect->fields & MNCC_F_USERUSER)
2535 encode_useruser(msg, 0, &connect->useruser);
2536
2537 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2538
2539 return gsm48_sendmsg(msg);
2540}
2541
2542static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2543{
2544 struct gsm48_hdr *gh = msgb_l3(msg);
2545 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2546 struct tlv_parsed tp;
2547 struct gsm_mncc connect;
2548
2549 gsm48_stop_cc_timer(trans);
2550
2551 memset(&connect, 0, sizeof(struct gsm_mncc));
2552 connect.callref = trans->callref;
2553 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2554 /* use subscriber as connected party number */
2555 if (trans->subscr) {
2556 connect.fields |= MNCC_F_CONNECTED;
2557 strncpy(connect.connected.number, trans->subscr->extension,
2558 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002559 strncpy(connect.imsi, trans->subscr->imsi,
2560 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002561 }
2562 /* facility */
2563 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2564 connect.fields |= MNCC_F_FACILITY;
2565 decode_facility(&connect.facility,
2566 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2567 }
2568 /* user-user */
2569 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2570 connect.fields |= MNCC_F_USERUSER;
2571 decode_useruser(&connect.useruser,
2572 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2573 }
2574 /* ss-version */
2575 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2576 connect.fields |= MNCC_F_SSVERSION;
2577 decode_ssversion(&connect.ssversion,
2578 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2579 }
2580
2581 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2582
2583 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2584}
2585
2586
2587static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2588{
2589 struct gsm_mncc connect_ack;
2590
2591 gsm48_stop_cc_timer(trans);
2592
2593 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2594
2595 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2596 connect_ack.callref = trans->callref;
2597 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2598 &connect_ack);
2599}
2600
2601static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2602{
2603 struct msgb *msg = gsm48_msgb_alloc();
2604 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2605
2606 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2607 msg->lchan = trans->lchan;
2608 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2609
2610 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2611
2612 return gsm48_sendmsg(msg);
2613}
2614
2615static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2616{
2617 struct gsm48_hdr *gh = msgb_l3(msg);
2618 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2619 struct tlv_parsed tp;
2620 struct gsm_mncc disc;
2621
2622 gsm48_stop_cc_timer(trans);
2623
2624 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2625
2626 memset(&disc, 0, sizeof(struct gsm_mncc));
2627 disc.callref = trans->callref;
2628 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2629 /* cause */
2630 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2631 disc.fields |= MNCC_F_CAUSE;
2632 decode_cause(&disc.cause,
2633 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2634 }
2635 /* facility */
2636 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2637 disc.fields |= MNCC_F_FACILITY;
2638 decode_facility(&disc.facility,
2639 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2640 }
2641 /* user-user */
2642 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2643 disc.fields |= MNCC_F_USERUSER;
2644 decode_useruser(&disc.useruser,
2645 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2646 }
2647 /* ss-version */
2648 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2649 disc.fields |= MNCC_F_SSVERSION;
2650 decode_ssversion(&disc.ssversion,
2651 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2652 }
2653
2654 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2655
2656}
2657
Harald Weltec66b71c2009-06-11 14:23:20 +08002658static struct gsm_mncc_cause default_cause = {
2659 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2660 .coding = 0,
2661 .rec = 0,
2662 .rec_val = 0,
2663 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2664 .diag_len = 0,
2665 .diag = { 0 },
2666};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002667
2668static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2669{
2670 struct gsm_mncc *disc = arg;
2671 struct msgb *msg = gsm48_msgb_alloc();
2672 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2673
2674 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2675 msg->lchan = trans->lchan;
2676 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2677
2678 gsm48_stop_cc_timer(trans);
2679 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2680
2681 /* cause */
2682 if (disc->fields & MNCC_F_CAUSE)
2683 encode_cause(msg, 1, &disc->cause);
2684 else
2685 encode_cause(msg, 1, &default_cause);
2686
2687 /* facility */
2688 if (disc->fields & MNCC_F_FACILITY)
2689 encode_facility(msg, 0, &disc->facility);
2690 /* progress */
2691 if (disc->fields & MNCC_F_PROGRESS)
2692 encode_progress(msg, 0, &disc->progress);
2693 /* user-user */
2694 if (disc->fields & MNCC_F_USERUSER)
2695 encode_useruser(msg, 0, &disc->useruser);
2696
2697 /* store disconnect cause for T306 expiry */
2698 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2699
2700 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2701
2702 return gsm48_sendmsg(msg);
2703}
2704
2705static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2706{
2707 struct gsm48_hdr *gh = msgb_l3(msg);
2708 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2709 struct tlv_parsed tp;
2710 struct gsm_mncc rel;
2711 int rc;
2712
2713 gsm48_stop_cc_timer(trans);
2714
2715 memset(&rel, 0, sizeof(struct gsm_mncc));
2716 rel.callref = trans->callref;
2717 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2718 /* cause */
2719 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2720 rel.fields |= MNCC_F_CAUSE;
2721 decode_cause(&rel.cause,
2722 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2723 }
2724 /* facility */
2725 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2726 rel.fields |= MNCC_F_FACILITY;
2727 decode_facility(&rel.facility,
2728 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2729 }
2730 /* user-user */
2731 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2732 rel.fields |= MNCC_F_USERUSER;
2733 decode_useruser(&rel.useruser,
2734 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2735 }
2736 /* ss-version */
2737 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2738 rel.fields |= MNCC_F_SSVERSION;
2739 decode_ssversion(&rel.ssversion,
2740 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2741 }
2742
2743 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2744 /* release collision 5.4.5 */
2745 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2746 } else {
2747 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2748 GSM48_MT_CC_RELEASE_COMPL);
2749 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2750 }
2751
2752 new_cc_state(trans, GSM_CSTATE_NULL);
2753
2754 trans->callref = 0;
2755 free_trans(trans);
2756
2757 return rc;
2758}
2759
2760static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2761{
2762 struct gsm_mncc *rel = arg;
2763 struct msgb *msg = gsm48_msgb_alloc();
2764 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2765
2766 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2767 msg->lchan = trans->lchan;
2768 gh->msg_type = GSM48_MT_CC_RELEASE;
2769
2770 trans->callref = 0;
2771
2772 gsm48_stop_cc_timer(trans);
2773 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2774
2775 /* cause */
2776 if (rel->fields & MNCC_F_CAUSE)
2777 encode_cause(msg, 0, &rel->cause);
2778 /* facility */
2779 if (rel->fields & MNCC_F_FACILITY)
2780 encode_facility(msg, 0, &rel->facility);
2781 /* user-user */
2782 if (rel->fields & MNCC_F_USERUSER)
2783 encode_useruser(msg, 0, &rel->useruser);
2784
2785 trans->T308_second = 0;
2786 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2787
2788 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2789 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2790
2791 return gsm48_sendmsg(msg);
2792}
2793
2794static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2795{
2796 struct gsm48_hdr *gh = msgb_l3(msg);
2797 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2798 struct tlv_parsed tp;
2799 struct gsm_mncc rel;
2800 int rc = 0;
2801
2802 gsm48_stop_cc_timer(trans);
2803
2804 memset(&rel, 0, sizeof(struct gsm_mncc));
2805 rel.callref = trans->callref;
2806 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2807 /* cause */
2808 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2809 rel.fields |= MNCC_F_CAUSE;
2810 decode_cause(&rel.cause,
2811 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2812 }
2813 /* facility */
2814 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2815 rel.fields |= MNCC_F_FACILITY;
2816 decode_facility(&rel.facility,
2817 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2818 }
2819 /* user-user */
2820 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2821 rel.fields |= MNCC_F_USERUSER;
2822 decode_useruser(&rel.useruser,
2823 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2824 }
2825 /* ss-version */
2826 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2827 rel.fields |= MNCC_F_SSVERSION;
2828 decode_ssversion(&rel.ssversion,
2829 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2830 }
2831
2832 if (trans->callref) {
2833 switch (trans->state) {
2834 case GSM_CSTATE_CALL_PRESENT:
2835 rc = mncc_recvmsg(trans->network, trans,
2836 MNCC_REJ_IND, &rel);
2837 break;
2838 case GSM_CSTATE_RELEASE_REQ:
2839 rc = mncc_recvmsg(trans->network, trans,
2840 MNCC_REL_CNF, &rel);
2841 break;
2842 default:
2843 rc = mncc_recvmsg(trans->network, trans,
2844 MNCC_REL_IND, &rel);
2845 }
2846 }
2847
2848 trans->callref = 0;
2849 free_trans(trans);
2850
2851 return rc;
2852}
2853
2854static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2855{
2856 struct gsm_mncc *rel = arg;
2857 struct msgb *msg = gsm48_msgb_alloc();
2858 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2859
2860 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2861 msg->lchan = trans->lchan;
2862 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2863
2864 trans->callref = 0;
2865
2866 gsm48_stop_cc_timer(trans);
2867
2868 /* cause */
2869 if (rel->fields & MNCC_F_CAUSE)
2870 encode_cause(msg, 0, &rel->cause);
2871 /* facility */
2872 if (rel->fields & MNCC_F_FACILITY)
2873 encode_facility(msg, 0, &rel->facility);
2874 /* user-user */
2875 if (rel->fields & MNCC_F_USERUSER)
2876 encode_useruser(msg, 0, &rel->useruser);
2877
2878 free_trans(trans);
2879
2880 return gsm48_sendmsg(msg);
2881}
2882
2883static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2884{
2885 struct gsm48_hdr *gh = msgb_l3(msg);
2886 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2887 struct tlv_parsed tp;
2888 struct gsm_mncc fac;
2889
2890 memset(&fac, 0, sizeof(struct gsm_mncc));
2891 fac.callref = trans->callref;
2892 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2893 /* facility */
2894 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2895 fac.fields |= MNCC_F_FACILITY;
2896 decode_facility(&fac.facility,
2897 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2898 }
2899 /* ss-version */
2900 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2901 fac.fields |= MNCC_F_SSVERSION;
2902 decode_ssversion(&fac.ssversion,
2903 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2904 }
2905
2906 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2907}
2908
2909static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2910{
2911 struct gsm_mncc *fac = arg;
2912 struct msgb *msg = gsm48_msgb_alloc();
2913 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2914
2915 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2916 msg->lchan = trans->lchan;
2917 gh->msg_type = GSM48_MT_CC_FACILITY;
2918
2919 /* facility */
2920 encode_facility(msg, 1, &fac->facility);
2921
2922 return gsm48_sendmsg(msg);
2923}
2924
2925static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2926{
2927 struct gsm_mncc hold;
2928
2929 memset(&hold, 0, sizeof(struct gsm_mncc));
2930 hold.callref = trans->callref;
2931 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2932}
2933
2934static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2935{
2936 struct msgb *msg = gsm48_msgb_alloc();
2937 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2938
2939 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2940 msg->lchan = trans->lchan;
2941 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2942
2943 return gsm48_sendmsg(msg);
2944}
2945
2946static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2947{
2948 struct gsm_mncc *hold_rej = arg;
2949 struct msgb *msg = gsm48_msgb_alloc();
2950 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2951
2952 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2953 msg->lchan = trans->lchan;
2954 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2955
2956 /* cause */
2957 if (hold_rej->fields & MNCC_F_CAUSE)
2958 encode_cause(msg, 1, &hold_rej->cause);
2959 else
2960 encode_cause(msg, 1, &default_cause);
2961
2962 return gsm48_sendmsg(msg);
2963}
2964
2965static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2966{
2967 struct gsm_mncc retrieve;
2968
2969 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2970 retrieve.callref = trans->callref;
2971 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2972}
2973
2974static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2975{
2976 struct msgb *msg = gsm48_msgb_alloc();
2977 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2978
2979 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2980 msg->lchan = trans->lchan;
2981 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2982
2983 return gsm48_sendmsg(msg);
2984}
2985
2986static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2987{
2988 struct gsm_mncc *retrieve_rej = arg;
2989 struct msgb *msg = gsm48_msgb_alloc();
2990 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2991
2992 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2993 msg->lchan = trans->lchan;
2994 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2995
2996 /* cause */
2997 if (retrieve_rej->fields & MNCC_F_CAUSE)
2998 encode_cause(msg, 1, &retrieve_rej->cause);
2999 else
3000 encode_cause(msg, 1, &default_cause);
3001
3002 return gsm48_sendmsg(msg);
3003}
3004
3005static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3006{
3007 struct gsm48_hdr *gh = msgb_l3(msg);
3008 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3009 struct tlv_parsed tp;
3010 struct gsm_mncc dtmf;
3011
3012 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3013 dtmf.callref = trans->callref;
3014 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3015 /* keypad facility */
3016 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3017 dtmf.fields |= MNCC_F_KEYPAD;
3018 decode_keypad(&dtmf.keypad,
3019 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3020 }
3021
3022 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3023}
3024
3025static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3026{
3027 struct gsm_mncc *dtmf = arg;
3028 struct msgb *msg = gsm48_msgb_alloc();
3029 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3030
3031 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3032 msg->lchan = trans->lchan;
3033 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3034
3035 /* keypad */
3036 if (dtmf->fields & MNCC_F_KEYPAD)
3037 encode_keypad(msg, dtmf->keypad);
3038
3039 return gsm48_sendmsg(msg);
3040}
3041
3042static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3043{
3044 struct gsm_mncc *dtmf = arg;
3045 struct msgb *msg = gsm48_msgb_alloc();
3046 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3047
3048 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3049 msg->lchan = trans->lchan;
3050 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3051
3052 /* cause */
3053 if (dtmf->fields & MNCC_F_CAUSE)
3054 encode_cause(msg, 1, &dtmf->cause);
3055 else
3056 encode_cause(msg, 1, &default_cause);
3057
3058 return gsm48_sendmsg(msg);
3059}
3060
3061static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3062{
3063 struct msgb *msg = gsm48_msgb_alloc();
3064 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3065
3066 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3067 msg->lchan = trans->lchan;
3068 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3069
3070 return gsm48_sendmsg(msg);
3071}
3072
3073static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3074{
3075 struct gsm_mncc dtmf;
3076
3077 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3078 dtmf.callref = trans->callref;
3079
3080 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3081}
3082
3083static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3084{
3085 struct gsm48_hdr *gh = msgb_l3(msg);
3086 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3087 struct tlv_parsed tp;
3088 struct gsm_mncc modify;
3089
3090 memset(&modify, 0, sizeof(struct gsm_mncc));
3091 modify.callref = trans->callref;
3092 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3093 /* bearer capability */
3094 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3095 modify.fields |= MNCC_F_BEARER_CAP;
3096 decode_bearer_cap(&modify.bearer_cap,
3097 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3098 }
3099
3100 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3101
3102 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3103}
3104
3105static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3106{
3107 struct gsm_mncc *modify = arg;
3108 struct msgb *msg = gsm48_msgb_alloc();
3109 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3110
3111 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3112 msg->lchan = trans->lchan;
3113 gh->msg_type = GSM48_MT_CC_MODIFY;
3114
3115 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3116
3117 /* bearer capability */
3118 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3119
3120 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3121
3122 return gsm48_sendmsg(msg);
3123}
3124
3125static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3126{
3127 struct gsm48_hdr *gh = msgb_l3(msg);
3128 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3129 struct tlv_parsed tp;
3130 struct gsm_mncc modify;
3131
3132 gsm48_stop_cc_timer(trans);
3133
3134 memset(&modify, 0, sizeof(struct gsm_mncc));
3135 modify.callref = trans->callref;
3136 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3137 /* bearer capability */
3138 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3139 modify.fields |= MNCC_F_BEARER_CAP;
3140 decode_bearer_cap(&modify.bearer_cap,
3141 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3142 }
3143
3144 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3145
3146 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3147}
3148
3149static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3150{
3151 struct gsm_mncc *modify = arg;
3152 struct msgb *msg = gsm48_msgb_alloc();
3153 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3154
3155 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3156 msg->lchan = trans->lchan;
3157 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3158
3159 /* bearer capability */
3160 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3161
3162 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3163
3164 return gsm48_sendmsg(msg);
3165}
3166
3167static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3168{
3169 struct gsm48_hdr *gh = msgb_l3(msg);
3170 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3171 struct tlv_parsed tp;
3172 struct gsm_mncc modify;
3173
3174 gsm48_stop_cc_timer(trans);
3175
3176 memset(&modify, 0, sizeof(struct gsm_mncc));
3177 modify.callref = trans->callref;
3178 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3179 /* bearer capability */
3180 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3181 modify.fields |= GSM48_IE_BEARER_CAP;
3182 decode_bearer_cap(&modify.bearer_cap,
3183 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3184 }
3185 /* cause */
3186 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3187 modify.fields |= MNCC_F_CAUSE;
3188 decode_cause(&modify.cause,
3189 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3190 }
3191
3192 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3193
3194 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3195}
3196
3197static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3198{
3199 struct gsm_mncc *modify = arg;
3200 struct msgb *msg = gsm48_msgb_alloc();
3201 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3202
3203 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3204 msg->lchan = trans->lchan;
3205 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3206
3207 /* bearer capability */
3208 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3209 /* cause */
3210 encode_cause(msg, 1, &modify->cause);
3211
3212 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3213
3214 return gsm48_sendmsg(msg);
3215}
3216
3217static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3218{
3219 struct gsm_mncc *notify = arg;
3220 struct msgb *msg = gsm48_msgb_alloc();
3221 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3222
3223 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3224 msg->lchan = trans->lchan;
3225 gh->msg_type = GSM48_MT_CC_NOTIFY;
3226
3227 /* notify */
3228 encode_notify(msg, notify->notify);
3229
3230 return gsm48_sendmsg(msg);
3231}
3232
3233static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3234{
3235 struct gsm48_hdr *gh = msgb_l3(msg);
3236 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3237// struct tlv_parsed tp;
3238 struct gsm_mncc notify;
3239
3240 memset(&notify, 0, sizeof(struct gsm_mncc));
3241 notify.callref = trans->callref;
3242// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3243 if (payload_len >= 1)
3244 decode_notify(&notify.notify, gh->data);
3245
3246 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3247}
3248
3249static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3250{
3251 struct gsm_mncc *user = arg;
3252 struct msgb *msg = gsm48_msgb_alloc();
3253 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3254
3255 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3256 msg->lchan = trans->lchan;
3257 gh->msg_type = GSM48_MT_CC_USER_INFO;
3258
3259 /* user-user */
3260 if (user->fields & MNCC_F_USERUSER)
3261 encode_useruser(msg, 1, &user->useruser);
3262 /* more data */
3263 if (user->more)
3264 encode_more(msg);
3265
3266 return gsm48_sendmsg(msg);
3267}
3268
3269static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3270{
3271 struct gsm48_hdr *gh = msgb_l3(msg);
3272 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3273 struct tlv_parsed tp;
3274 struct gsm_mncc user;
3275
3276 memset(&user, 0, sizeof(struct gsm_mncc));
3277 user.callref = trans->callref;
3278 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3279 /* user-user */
3280 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3281 user.fields |= MNCC_F_USERUSER;
3282 decode_useruser(&user.useruser,
3283 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3284 }
3285 /* more data */
3286 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3287 user.more = 1;
3288
3289 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3290}
3291
3292static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3293{
3294 struct gsm_mncc *mode = arg;
3295
3296 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3297}
3298
3299static struct downstate {
3300 u_int32_t states;
3301 int type;
3302 int (*rout) (struct gsm_trans *trans, void *arg);
3303} downstatelist[] = {
3304 /* mobile originating call establishment */
3305 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3306 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3307 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3308 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3309 {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 */
3310 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3311 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3312 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3313 /* mobile terminating call establishment */
3314 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3315 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3316 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3317 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3318 /* signalling during call */
3319 {SBIT(GSM_CSTATE_ACTIVE),
3320 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3321 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3322 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3323 {ALL_STATES,
3324 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3325 {ALL_STATES,
3326 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3327 {ALL_STATES,
3328 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3329 {SBIT(GSM_CSTATE_ACTIVE),
3330 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3331 {SBIT(GSM_CSTATE_ACTIVE),
3332 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3333 {SBIT(GSM_CSTATE_ACTIVE),
3334 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3335 {SBIT(GSM_CSTATE_ACTIVE),
3336 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3337 {SBIT(GSM_CSTATE_ACTIVE),
3338 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3339 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3340 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3341 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3342 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3343 {SBIT(GSM_CSTATE_ACTIVE),
3344 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3345 /* clearing */
3346 {SBIT(GSM_CSTATE_INITIATED),
3347 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3348 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3349 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3350 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3351 MNCC_REL_REQ, gsm48_cc_tx_release},
3352 /* special */
3353 {ALL_STATES,
3354 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3355};
3356
3357#define DOWNSLLEN \
3358 (sizeof(downstatelist) / sizeof(struct downstate))
3359
3360
3361int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3362{
3363 int i, j, k, l, rc = 0;
3364 struct gsm_trans *trans = NULL, *transt;
3365 struct gsm_subscriber *subscr;
3366 struct gsm_lchan *lchan = NULL, *lchant;
3367 struct gsm_bts *bts = NULL;
3368 struct gsm_bts_trx *trx;
3369 struct gsm_bts_trx_ts *ts;
3370 struct gsm_mncc *data = arg, rel;
3371
3372 /* handle special messages */
3373 switch(msg_type) {
3374 case MNCC_BRIDGE:
3375 return tch_bridge(net, arg);
3376 case MNCC_FRAME_DROP:
3377 return tch_recv(net, arg, 0);
3378 case MNCC_FRAME_RECV:
3379 return tch_recv(net, arg, 1);
3380 case GSM_TRAU_FRAME:
3381 return tch_frame(net, arg);
3382 }
3383
3384 memset(&rel, 0, sizeof(struct gsm_mncc));
3385 rel.callref = data->callref;
3386
3387 /* Find callref */
3388 trans = get_trans_ref(net, data->callref);
3389
3390 /* Callref unknown */
3391 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003392 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003393 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3394 "Received '%s' from MNCC with "
3395 "unknown callref %d\n", data->called.number,
3396 get_mncc_name(msg_type), data->callref);
3397 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003398 return mncc_release_ind(net, NULL, data->callref,
3399 GSM48_CAUSE_LOC_PRN_S_LU,
3400 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003401 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003402 if (!data->called.number[0] && !data->imsi[0]) {
3403 DEBUGP(DCC, "(bts - trx - ts - ti) "
3404 "Received '%s' from MNCC with "
3405 "no number or IMSI\n", get_mncc_name(msg_type));
3406 /* Invalid number */
3407 return mncc_release_ind(net, NULL, data->callref,
3408 GSM48_CAUSE_LOC_PRN_S_LU,
3409 GSM48_CC_CAUSE_INV_NR_FORMAT);
3410 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003411 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003412 if (data->called.number[0])
3413 subscr = subscr_get_by_extension(data->called.number);
3414 else
3415 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003416 /* If subscriber is not found */
3417 if (!subscr) {
3418 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3419 "Received '%s' from MNCC with "
3420 "unknown subscriber %s\n", data->called.number,
3421 get_mncc_name(msg_type), data->called.number);
3422 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003423 return mncc_release_ind(net, NULL, data->callref,
3424 GSM48_CAUSE_LOC_PRN_S_LU,
3425 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003426 }
3427 /* If subscriber is not "attached" */
3428 if (!subscr->lac) {
3429 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3430 "Received '%s' from MNCC with "
3431 "detached subscriber %s\n", data->called.number,
3432 get_mncc_name(msg_type), data->called.number);
3433 subscr_put(subscr);
3434 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003435 return mncc_release_ind(net, NULL, data->callref,
3436 GSM48_CAUSE_LOC_PRN_S_LU,
3437 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003438 }
3439 /* Create transaction */
Harald Weltec05677b2009-06-26 20:17:06 +02003440 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003441 DEBUGP(DCC, "No memory for trans.\n");
3442 subscr_put(subscr);
3443 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003444 mncc_release_ind(net, NULL, data->callref,
3445 GSM48_CAUSE_LOC_PRN_S_LU,
3446 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003447 return -ENOMEM;
3448 }
3449 trans->callref = data->callref;
3450 trans->network = net;
3451 trans->transaction_id = 0xff; /* unassigned */
3452 llist_add_tail(&trans->entry, &net->trans_list);
3453 /* Assign subscriber to transaction */
3454 trans->subscr = subscr;
3455 /* Find lchan */
3456 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003457 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003458 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003459 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003460 for (k = 0; k < TRX_NR_TS; k++) {
3461 ts = &trx->ts[k];
3462 for (l = 0; l < TS_MAX_LCHAN; l++) {
3463 lchant = &ts->lchan[l];
3464 if (lchant->subscr == subscr) {
3465 lchan = lchant;
3466 break;
3467 }
3468 }
3469 }
3470 }
3471 }
3472
3473 /* If subscriber has no lchan */
3474 if (!lchan) {
3475 /* find transaction with this subscriber already paging */
3476 llist_for_each_entry(transt, &net->trans_list, entry) {
3477 /* Transaction of our lchan? */
3478 if (transt == trans ||
3479 transt->subscr != subscr)
3480 continue;
3481 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3482 "Received '%s' from MNCC with "
3483 "unallocated channel, paging already "
3484 "started.\n", bts->nr,
3485 data->called.number,
3486 get_mncc_name(msg_type));
3487 return 0;
3488 }
3489 /* store setup informations until paging was successfull */
3490 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3491 /* start paging subscriber on all BTS with her location */
3492 subscr->net = net;
3493 bts = NULL;
3494 do {
3495 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3496 if (!bts)
3497 break;
3498 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3499 "Received '%s' from MNCC with "
3500 "unallocated channel, paging.\n",
3501 bts->nr, data->called.number,
3502 get_mncc_name(msg_type));
3503 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003504 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003505 setup_trig_pag_evt, subscr);
3506 } while (1);
3507 return 0;
3508 }
3509 /* Assign lchan */
3510 trans->lchan = lchan;
3511 use_lchan(lchan);
3512 }
3513 lchan = trans->lchan;
3514
3515 /* if paging did not respond yet */
3516 if (!lchan) {
3517 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3518 "Received '%s' from MNCC in paging state\n",
3519 (trans->subscr)?(trans->subscr->extension):"-",
3520 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003521 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3522 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003523 if (msg_type == MNCC_REL_REQ)
3524 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3525 else
3526 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3527 trans->callref = 0;
3528 free_trans(trans);
3529 return rc;
3530 }
3531
3532 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3533 "Received '%s' from MNCC in state %d (%s)\n",
3534 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3535 trans->transaction_id,
3536 (lchan->subscr)?(lchan->subscr->extension):"-",
3537 get_mncc_name(msg_type), trans->state,
3538 cc_state_names[trans->state]);
3539
3540 /* Find function for current state and message */
3541 for (i = 0; i < DOWNSLLEN; i++)
3542 if ((msg_type == downstatelist[i].type)
3543 && ((1 << trans->state) & downstatelist[i].states))
3544 break;
3545 if (i == DOWNSLLEN) {
3546 DEBUGP(DCC, "Message unhandled at this state.\n");
3547 return 0;
3548 }
3549
3550 rc = downstatelist[i].rout(trans, arg);
3551
3552 return rc;
3553}
3554
3555
3556static struct datastate {
3557 u_int32_t states;
3558 int type;
3559 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3560} datastatelist[] = {
3561 /* mobile originating call establishment */
3562 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3563 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3564 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3565 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3566 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3567 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3568 /* mobile terminating call establishment */
3569 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3570 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3571 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3572 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3573 {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 */
3574 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3575 /* signalling during call */
3576 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3577 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3578 {SBIT(GSM_CSTATE_ACTIVE),
3579 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3580 {ALL_STATES,
3581 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3582 {ALL_STATES,
3583 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3584 {ALL_STATES,
3585 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3586 {SBIT(GSM_CSTATE_ACTIVE),
3587 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3588 {SBIT(GSM_CSTATE_ACTIVE),
3589 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3590 {SBIT(GSM_CSTATE_ACTIVE),
3591 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3592 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3593 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3594 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3595 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3596 {SBIT(GSM_CSTATE_ACTIVE),
3597 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3598 /* clearing */
3599 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3600 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3601 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3602 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3603 {ALL_STATES, /* 5.4.3.4 */
3604 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3605};
3606
3607#define DATASLLEN \
3608 (sizeof(datastatelist) / sizeof(struct datastate))
3609
Harald Welte4bc90a12008-12-27 16:32:52 +00003610static int gsm0408_rcv_cc(struct msgb *msg)
3611{
3612 struct gsm48_hdr *gh = msgb_l3(msg);
3613 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003614 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3615 struct gsm_lchan *lchan = msg->lchan;
3616 struct gsm_trans *trans = NULL, *transt;
3617 struct gsm_network *net = lchan->ts->trx->bts->network;
3618 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003619
Harald Welte4bfdfe72009-06-10 23:11:52 +08003620 if (msg_type & 0x80) {
3621 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3622 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003623 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003624
3625 /* Find transaction */
3626 llist_for_each_entry(transt, &net->trans_list, entry) {
3627 /* Transaction of our lchan? */
3628 if (transt->lchan == lchan
3629 && transt->transaction_id == transaction_id) {
3630 trans = transt;
3631 }
3632 }
3633
3634 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3635 "Received '%s' from MS in state %d (%s)\n",
3636 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3637 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3638 cc_msg_names[msg_type], trans?(trans->state):0,
3639 cc_state_names[trans?(trans->state):0]);
3640
3641 /* Create transaction */
3642 if (!trans) {
3643 DEBUGP(DCC, "Unknown transaction ID %02x, "
3644 "creating new trans.\n", transaction_id);
3645 /* Create transaction */
Harald Welte9b11e872009-06-26 19:42:28 +02003646 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003647 DEBUGP(DCC, "No memory for trans.\n");
3648 rc = gsm48_tx_simple(msg->lchan,
3649 GSM48_PDISC_CC | transaction_id,
3650 GSM48_MT_CC_RELEASE_COMPL);
3651 return -ENOMEM;
3652 }
3653 llist_add_tail(&trans->entry, &net->trans_list);
3654 /* Assign transaction */
3655 trans->callref = new_callref++;
3656 trans->network = net;
3657 trans->transaction_id = transaction_id;
3658 trans->lchan = lchan;
3659 use_lchan(lchan);
3660 if (lchan->subscr) {
3661 trans->subscr = lchan->subscr;
3662 subscr_get(trans->subscr);
3663 }
3664 }
3665
3666 /* find function for current state and message */
3667 for (i = 0; i < DATASLLEN; i++)
3668 if ((msg_type == datastatelist[i].type)
3669 && ((1 << trans->state) & datastatelist[i].states))
3670 break;
3671 if (i == DATASLLEN) {
3672 DEBUGP(DCC, "Message unhandled at this state.\n");
3673 return 0;
3674 }
3675
3676 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003677
3678 return rc;
3679}
3680
Harald Welte52b1f982008-12-23 20:25:15 +00003681/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3682int gsm0408_rcvmsg(struct msgb *msg)
3683{
3684 struct gsm48_hdr *gh = msgb_l3(msg);
3685 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003686 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003687
3688 switch (pdisc) {
3689 case GSM48_PDISC_CC:
3690 rc = gsm0408_rcv_cc(msg);
3691 break;
3692 case GSM48_PDISC_MM:
3693 rc = gsm0408_rcv_mm(msg);
3694 break;
3695 case GSM48_PDISC_RR:
3696 rc = gsm0408_rcv_rr(msg);
3697 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003698 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003699 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003700 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003701 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003702 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003703 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3704 pdisc);
3705 break;
3706 default:
3707 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3708 pdisc);
3709 break;
3710 }
3711
3712 return rc;
3713}
Harald Welte8470bf22008-12-25 23:28:35 +00003714
Harald Welte8470bf22008-12-25 23:28:35 +00003715/* Section 9.1.8 / Table 9.9 */
3716struct chreq {
3717 u_int8_t val;
3718 u_int8_t mask;
3719 enum chreq_type type;
3720};
3721
3722/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3723static const struct chreq chreq_type_neci1[] = {
3724 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3725 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3726 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3727 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3728 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3729 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3730 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3731 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3732 { 0x10, 0xf0, CHREQ_T_SDCCH },
3733 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3734 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3735 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3736};
3737
3738/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3739static const struct chreq chreq_type_neci0[] = {
3740 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3741 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3742 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3743 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3744 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3745 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3746 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3747 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3748};
3749
3750static const enum gsm_chan_t ctype_by_chreq[] = {
3751 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3752 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3753 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3754 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3755 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3756 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3757 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3758 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3759 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3760 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3761 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3762 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3763};
3764
Harald Weltee14a57c2008-12-29 04:08:28 +00003765static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3766 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3767 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3768 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3769 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3770 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3771 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3772 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3773 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3774 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3775 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3776 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3777 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3778};
3779
Harald Welte8470bf22008-12-25 23:28:35 +00003780enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3781{
3782 int i;
3783 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3784
3785 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3786 const struct chreq *chr = &chreq_type_neci0[i];
3787 if ((ra & chr->mask) == chr->val)
3788 return ctype_by_chreq[chr->type];
3789 }
3790 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3791 return GSM_LCHAN_SDCCH;
3792}
Harald Weltee14a57c2008-12-29 04:08:28 +00003793
3794enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3795{
3796 int i;
3797 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3798
3799 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3800 const struct chreq *chr = &chreq_type_neci0[i];
3801 if ((ra & chr->mask) == chr->val)
3802 return reason_by_chreq[chr->type];
3803 }
3804 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3805 return GSM_CHREQ_REASON_OTHER;
3806}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003807
3808/* dequeue messages to layer 4 */
3809int bsc_upqueue(struct gsm_network *net)
3810{
3811 struct gsm_mncc *mncc;
3812 struct msgb *msg;
3813 int work = 0;
3814
3815 if (net)
3816 while ((msg = msgb_dequeue(&net->upqueue))) {
3817 mncc = (struct gsm_mncc *)msg->data;
3818 if (net->mncc_recv)
3819 net->mncc_recv(net, mncc->msg_type, mncc);
3820 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003821 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003822 }
3823
3824 return work;
3825}