blob: 7d54827e980b6269c6da7a52498af43cb4edb383 [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;
Harald Welte5a691b52009-07-05 04:05:44 +0200243 if ((data[1] & 0x40) == 0x00)
Harald Weltef7c43522009-06-09 20:24:21 +0000244 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 Welte9176bd42009-07-23 18:46:00 +02001132 struct gsm_bts *bts = lchan->ts->trx->bts;
1133 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001134 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1135 char mi_string[MI_SIZE];
1136
1137 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001138 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001139 mi_type, mi_string);
1140
Harald Welte75a983f2008-12-27 21:34:06 +00001141 switch (mi_type) {
1142 case GSM_MI_TYPE_IMSI:
1143 if (!lchan->subscr)
Harald Welte9176bd42009-07-23 18:46:00 +02001144 lchan->subscr = db_create_subscriber(net, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001145 if (lchan->loc_operation)
1146 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001147 break;
1148 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001149 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001150 /* update subscribe <-> IMEI mapping */
1151 if (lchan->subscr)
1152 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001153 if (lchan->loc_operation)
1154 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001155 break;
1156 }
Holger Freyther73487a22008-12-31 18:53:57 +00001157
1158 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001159 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001160}
1161
Harald Welte255539c2008-12-28 02:26:27 +00001162
1163static void loc_upd_rej_cb(void *data)
1164{
1165 struct gsm_lchan *lchan = data;
1166
Holger Freyther73487a22008-12-31 18:53:57 +00001167 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001168 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001169 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001170}
1171
Holger Freytherb7193e42008-12-29 17:44:08 +00001172static void schedule_reject(struct gsm_lchan *lchan)
1173{
Holger Freyther73487a22008-12-31 18:53:57 +00001174 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1175 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001176 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001177}
1178
Harald Welte2a139372009-02-22 21:14:55 +00001179static const char *lupd_name(u_int8_t type)
1180{
1181 switch (type) {
1182 case GSM48_LUPD_NORMAL:
1183 return "NORMAL";
1184 case GSM48_LUPD_PERIODIC:
1185 return "PEROIDOC";
1186 case GSM48_LUPD_IMSI_ATT:
1187 return "IMSI ATTACH";
1188 default:
1189 return "UNKNOWN";
1190 }
1191}
1192
Harald Welte231ad4f2008-12-27 11:15:38 +00001193#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001194/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001195static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001196{
Harald Welte8470bf22008-12-25 23:28:35 +00001197 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001198 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001199 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001200 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001201 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001202 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001203 char mi_string[MI_SIZE];
1204 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001205
Harald Welte8470bf22008-12-25 23:28:35 +00001206 lu = (struct gsm48_loc_upd_req *) gh->data;
1207
1208 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001209
Harald Weltefc977a82008-12-27 10:19:37 +00001210 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1211
Harald Weltea0368542009-06-27 02:58:43 +02001212 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001213 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001214
Holger Freythereaf04692009-06-06 13:54:44 +00001215 /*
1216 * Pseudo Spoof detection: Just drop a second/concurrent
1217 * location updating request.
1218 */
1219 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001220 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001221 lchan->loc_operation);
1222 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1223 return 0;
1224 }
1225
Holger Freyther73487a22008-12-31 18:53:57 +00001226 allocate_loc_updating_req(lchan);
1227
Harald Welte52b1f982008-12-23 20:25:15 +00001228 switch (mi_type) {
1229 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001230 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001231 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001232 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001233 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001234
Harald Welte52b1f982008-12-23 20:25:15 +00001235 /* look up subscriber based on IMSI */
Harald Welte9176bd42009-07-23 18:46:00 +02001236 subscr = db_create_subscriber(bts->network, mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001237 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001238 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001239 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001240 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001241 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001242 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001243
Harald Welte52b1f982008-12-23 20:25:15 +00001244 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte9176bd42009-07-23 18:46:00 +02001245 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001246 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001247 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001248 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001249 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001250 }
1251 break;
1252 case GSM_MI_TYPE_IMEI:
1253 case GSM_MI_TYPE_IMEISV:
1254 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001255 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001256 break;
1257 default:
Harald Weltea0368542009-06-27 02:58:43 +02001258 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001259 break;
1260 }
1261
Harald Welte24516ea2009-07-04 10:18:00 +02001262 /* schedule the reject timer */
1263 schedule_reject(lchan);
1264
Harald Welte4bfdfe72009-06-10 23:11:52 +08001265 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001266 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001267 /* FIXME: request id? close channel? */
1268 return -EINVAL;
1269 }
1270
Harald Welte255539c2008-12-28 02:26:27 +00001271 lchan->subscr = subscr;
1272
Harald Welte24516ea2009-07-04 10:18:00 +02001273 /* check if we can let the subscriber into our network immediately
1274 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001275 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001276}
1277
Harald Welte7584aea2009-02-11 11:44:12 +00001278/* 9.1.5 Channel mode modify */
1279int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1280{
1281 struct msgb *msg = gsm48_msgb_alloc();
1282 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1283 struct gsm48_chan_mode_modify *cmm =
1284 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001285 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001286
Harald Welte4a543e82009-02-28 13:17:55 +00001287 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001288
Harald Welte45b407a2009-05-23 15:51:12 +00001289 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001290 msg->lchan = lchan;
1291 gh->proto_discr = GSM48_PDISC_RR;
1292 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1293
1294 /* fill the channel information element, this code
1295 * should probably be shared with rsl_rx_chan_rqd() */
1296 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001297 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001298 cmm->chan_desc.h0.h = 0;
1299 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1300 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1301 cmm->mode = mode;
1302
1303 return gsm48_sendmsg(msg);
1304}
1305
Harald Welte4bfdfe72009-06-10 23:11:52 +08001306#if 0
1307static u_int8_t to_bcd8(u_int8_t val)
1308{
1309 return ((val / 10) << 4) | (val % 10);
1310}
1311#endif
1312
Harald Weltedb253af2008-12-30 17:56:55 +00001313/* Section 9.2.15a */
1314int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1315{
1316 struct msgb *msg = gsm48_msgb_alloc();
1317 struct gsm48_hdr *gh;
1318 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001319 u_int8_t *ptr8;
1320 u_int16_t *ptr16;
1321 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001322 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001323#if 0
1324 time_t cur_t;
1325 struct tm* cur_time;
1326 int tz15min;
1327#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001328
1329 msg->lchan = lchan;
1330
1331 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1332 gh->proto_discr = GSM48_PDISC_MM;
1333 gh->msg_type = GSM48_MT_MM_INFO;
1334
1335 if (net->name_long) {
1336 name_len = strlen(net->name_long);
1337 /* 10.5.3.5a */
1338 ptr8 = msgb_put(msg, 3);
1339 ptr8[0] = GSM48_IE_NAME_LONG;
1340 ptr8[1] = name_len*2 +1;
1341 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1342
1343 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1344 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001345 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001346
1347 /* FIXME: Use Cell Broadcast, not UCS-2, since
1348 * UCS-2 is only supported by later revisions of the spec */
1349 }
1350
1351 if (net->name_short) {
1352 name_len = strlen(net->name_short);
1353 /* 10.5.3.5a */
1354 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001355 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001356 ptr8[1] = name_len*2 + 1;
1357 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1358
Harald Weltee872cb12009-01-01 00:33:37 +00001359 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001360 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001361 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001362 }
1363
1364#if 0
1365 /* Section 10.5.3.9 */
1366 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001367 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001368 ptr8 = msgb_put(msg, 8);
1369 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1370 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1371 ptr8[2] = to_bcd8(cur_time->tm_mon);
1372 ptr8[3] = to_bcd8(cur_time->tm_mday);
1373 ptr8[4] = to_bcd8(cur_time->tm_hour);
1374 ptr8[5] = to_bcd8(cur_time->tm_min);
1375 ptr8[6] = to_bcd8(cur_time->tm_sec);
1376 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1377 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001378 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001379 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001380 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001381#endif
1382
1383 return gsm48_sendmsg(msg);
1384}
1385
Harald Welte4b634542008-12-27 01:55:51 +00001386static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1387{
Harald Welte4b634542008-12-27 01:55:51 +00001388 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001389 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001390}
Harald Welteba4cf162009-01-10 01:49:35 +00001391
1392/* 9.2.6 CM service reject */
1393static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1394 enum gsm48_reject_value value)
1395{
1396 struct msgb *msg = gsm48_msgb_alloc();
1397 struct gsm48_hdr *gh;
1398
1399 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1400
1401 msg->lchan = lchan;
1402 use_lchan(lchan);
1403
1404 gh->proto_discr = GSM48_PDISC_MM;
1405 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1406 gh->data[0] = value;
1407 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1408
1409 return gsm48_sendmsg(msg);
1410}
1411
Harald Welte4ed0e922009-01-10 03:17:30 +00001412
1413/*
1414 * Handle CM Service Requests
1415 * a) Verify that the packet is long enough to contain the information
1416 * we require otherwsie reject with INCORRECT_MESSAGE
1417 * b) Try to parse the TMSI. If we do not have one reject
1418 * c) Check that we know the subscriber with the TMSI otherwise reject
1419 * with a HLR cause
1420 * d) Set the subscriber on the gsm_lchan and accept
1421 */
Harald Welte4b634542008-12-27 01:55:51 +00001422static int gsm48_rx_mm_serv_req(struct msgb *msg)
1423{
Harald Welteba4cf162009-01-10 01:49:35 +00001424 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001425 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001426
Harald Welte9176bd42009-07-23 18:46:00 +02001427 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001428 struct gsm_subscriber *subscr;
1429 struct gsm48_hdr *gh = msgb_l3(msg);
1430 struct gsm48_service_request *req =
1431 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001432 /* unfortunately in Phase1 the classmar2 length is variable */
1433 u_int8_t classmark2_len = gh->data[1];
1434 u_int8_t *classmark2 = gh->data+2;
1435 u_int8_t mi_len = *(classmark2 + classmark2_len);
1436 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001437
Harald Weltec9e02182009-05-01 19:07:53 +00001438 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001439 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001440 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001441 return gsm48_tx_mm_serv_rej(msg->lchan,
1442 GSM48_REJECT_INCORRECT_MESSAGE);
1443 }
1444
1445 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001446 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001447 return gsm48_tx_mm_serv_rej(msg->lchan,
1448 GSM48_REJECT_INCORRECT_MESSAGE);
1449 }
1450
Harald Weltec9e02182009-05-01 19:07:53 +00001451 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001452 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001453 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001454 return gsm48_tx_mm_serv_rej(msg->lchan,
1455 GSM48_REJECT_INCORRECT_MESSAGE);
1456 }
1457
Harald Weltec9e02182009-05-01 19:07:53 +00001458 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001459 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001460 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001461
Harald Welte9176bd42009-07-23 18:46:00 +02001462 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001463
Harald Welte2a139372009-02-22 21:14:55 +00001464 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001465 if (!subscr)
1466 return gsm48_tx_mm_serv_rej(msg->lchan,
1467 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1468
1469 if (!msg->lchan->subscr)
1470 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001471 else if (msg->lchan->subscr != subscr) {
1472 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1473 subscr_put(subscr);
1474 }
1475
Harald Weltec2e302d2009-07-05 14:08:13 +02001476 subscr->equipment.classmark2_len = classmark2_len;
1477 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1478 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001479
Harald Welte4b634542008-12-27 01:55:51 +00001480 return gsm48_tx_mm_serv_ack(msg->lchan);
1481}
1482
Harald Welte2a139372009-02-22 21:14:55 +00001483static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1484{
Harald Welte9176bd42009-07-23 18:46:00 +02001485 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001486 struct gsm48_hdr *gh = msgb_l3(msg);
1487 struct gsm48_imsi_detach_ind *idi =
1488 (struct gsm48_imsi_detach_ind *) gh->data;
1489 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1490 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001491 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001492
1493 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1494 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1495 mi_type, mi_string);
1496
1497 switch (mi_type) {
1498 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001499 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001500 break;
1501 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001502 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001503 break;
1504 case GSM_MI_TYPE_IMEI:
1505 case GSM_MI_TYPE_IMEISV:
1506 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001507 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001508 break;
1509 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001510 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001511 break;
1512 }
1513
Holger Freyther4a49e772009-04-12 05:37:29 +00001514 if (subscr) {
1515 subscr_update(subscr, msg->trx->bts,
1516 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001517 DEBUGP(DMM, "Subscriber: %s\n",
1518 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001519 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001520 } else
Harald Welte2a139372009-02-22 21:14:55 +00001521 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1522
Harald Welte2a139372009-02-22 21:14:55 +00001523 return 0;
1524}
1525
Harald Welted2a7f5a2009-06-05 20:08:20 +00001526static int gsm48_rx_mm_status(struct msgb *msg)
1527{
1528 struct gsm48_hdr *gh = msgb_l3(msg);
1529
1530 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1531
1532 return 0;
1533}
1534
Harald Weltebf5e8df2009-02-03 12:59:45 +00001535/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001536static int gsm0408_rcv_mm(struct msgb *msg)
1537{
1538 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001539 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001540
1541 switch (gh->msg_type & 0xbf) {
1542 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001543 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001544 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001545 break;
1546 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001547 rc = mm_rx_id_resp(msg);
1548 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001549 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001550 rc = gsm48_rx_mm_serv_req(msg);
1551 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001552 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001553 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001554 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001555 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001556 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1557 msg->lchan->subscr ?
1558 msg->lchan->subscr->imsi :
1559 "unknown subscriber");
1560 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001561 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001562 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1563 break;
1564 case GSM48_MT_MM_CM_REEST_REQ:
1565 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1566 break;
1567 case GSM48_MT_MM_AUTH_RESP:
1568 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001569 break;
1570 default:
1571 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1572 gh->msg_type);
1573 break;
1574 }
1575
1576 return rc;
1577}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001578
Harald Welte2d35ae62009-02-06 12:02:13 +00001579/* Receive a PAGING RESPONSE message from the MS */
1580static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1581{
Harald Welte9176bd42009-07-23 18:46:00 +02001582 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001583 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001584 u_int8_t *classmark2_lv = gh->data + 1;
1585 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1586 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001587 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001588 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001589 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001590 int rc = 0;
1591
Harald Welte61548982009-02-22 21:26:29 +00001592 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001593 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1594 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001595 switch (mi_type) {
1596 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001597 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001598 break;
1599 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001600 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001601 break;
1602 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001603
1604 if (!subscr) {
1605 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001606 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001607 return -EINVAL;
1608 }
1609 DEBUGP(DRR, "<- Channel was requested by %s\n",
1610 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001611
Harald Weltec2e302d2009-07-05 14:08:13 +02001612 subscr->equipment.classmark2_len = *classmark2_lv;
1613 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1614 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001615
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001616 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001617 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001618 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001619 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1620 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001621 return -EINVAL;
1622 } else {
1623 DEBUGP(DRR, "<- Channel already owned by us\n");
1624 subscr_put(subscr);
1625 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001626 }
1627
Harald Welte595ad7b2009-02-16 22:05:44 +00001628 sig_data.subscr = subscr;
1629 sig_data.bts = msg->lchan->ts->trx->bts;
1630 sig_data.lchan = msg->lchan;
1631
1632 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001633
1634 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001635 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001636
Harald Welte7584aea2009-02-11 11:44:12 +00001637 /* FIXME: somehow signal the completion of the PAGING to
1638 * the entity that requested the paging */
1639
Harald Welte2d35ae62009-02-06 12:02:13 +00001640 return rc;
1641}
1642
Harald Weltef7c43522009-06-09 20:24:21 +00001643static int gsm48_rx_rr_classmark(struct msgb *msg)
1644{
1645 struct gsm48_hdr *gh = msgb_l3(msg);
1646 struct gsm_subscriber *subscr = msg->lchan->subscr;
1647 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1648 u_int8_t cm2_len, cm3_len = 0;
1649 u_int8_t *cm2, *cm3 = NULL;
1650
1651 DEBUGP(DRR, "CLASSMARK CHANGE ");
1652
1653 /* classmark 2 */
1654 cm2_len = gh->data[0];
1655 cm2 = &gh->data[1];
1656 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1657
1658 if (payload_len > cm2_len + 1) {
1659 /* we must have a classmark3 */
1660 if (gh->data[cm2_len+1] != 0x20) {
1661 DEBUGPC(DRR, "ERR CM3 TAG\n");
1662 return -EINVAL;
1663 }
1664 if (cm2_len > 3) {
1665 DEBUGPC(DRR, "CM2 too long!\n");
1666 return -EINVAL;
1667 }
1668
1669 cm3_len = gh->data[cm2_len+2];
1670 cm3 = &gh->data[cm2_len+3];
1671 if (cm3_len > 14) {
1672 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1673 return -EINVAL;
1674 }
1675 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1676 }
1677 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001678 subscr->equipment.classmark2_len = cm2_len;
1679 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001680 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001681 subscr->equipment.classmark3_len = cm3_len;
1682 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001683 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001684 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001685 }
1686
Harald Weltef7c43522009-06-09 20:24:21 +00001687 return 0;
1688}
1689
Harald Weltecf5b3592009-05-01 18:28:42 +00001690static int gsm48_rx_rr_status(struct msgb *msg)
1691{
1692 struct gsm48_hdr *gh = msgb_l3(msg);
1693
1694 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1695 rr_cause_name(gh->data[0]));
1696
1697 return 0;
1698}
1699
Harald Weltef7c43522009-06-09 20:24:21 +00001700static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1701{
1702 struct gsm48_hdr *gh = msgb_l3(msg);
1703 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1704 static struct gsm_meas_rep meas_rep;
1705
Harald Welte10d0e672009-06-27 02:53:10 +02001706 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001707 parse_meas_rep(&meas_rep, gh->data, payload_len);
1708 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001709 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001710 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001711 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001712 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001713 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001714 else
Harald Welte10d0e672009-06-27 02:53:10 +02001715 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001716 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1717 meas_rep.rxqual_sub);
1718
Harald Welte10d0e672009-06-27 02:53:10 +02001719 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001720
1721 /* FIXME: put the results somwhere */
1722
1723 return 0;
1724}
1725
Harald Weltebf5e8df2009-02-03 12:59:45 +00001726/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001727static int gsm0408_rcv_rr(struct msgb *msg)
1728{
1729 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001730 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001731
1732 switch (gh->msg_type) {
1733 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001734 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001735 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001736 case GSM48_MT_RR_GPRS_SUSP_REQ:
1737 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1738 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001739 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001740 rc = gsm48_rr_rx_pag_resp(msg);
1741 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001742 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1743 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001744 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001745 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001746 case GSM48_MT_RR_STATUS:
1747 rc = gsm48_rx_rr_status(msg);
1748 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001749 case GSM48_MT_RR_MEAS_REP:
1750 rc = gsm48_rx_rr_meas_rep(msg);
1751 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001752 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001753 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001754 gh->msg_type);
1755 break;
1756 }
1757
Harald Welte2d35ae62009-02-06 12:02:13 +00001758 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001759}
1760
Holger Freythere64a7a32009-02-06 21:55:37 +00001761/* 7.1.7 and 9.1.7 Channel release*/
1762int gsm48_send_rr_release(struct gsm_lchan *lchan)
1763{
1764 struct msgb *msg = gsm48_msgb_alloc();
1765 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1766 u_int8_t *cause;
1767
1768 msg->lchan = lchan;
1769 gh->proto_discr = GSM48_PDISC_RR;
1770 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1771
1772 cause = msgb_put(msg, 1);
1773 cause[0] = GSM48_RR_CAUSE_NORMAL;
1774
1775 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1776 lchan->nr, lchan->type);
1777
Harald Welteae0f2362009-07-19 18:36:49 +02001778 /* Send actual release request to MS */
1779 gsm48_sendmsg(msg);
1780
1781 /* Deactivate the SACCH on the BTS side */
1782 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001783}
1784
Harald Welte4bc90a12008-12-27 16:32:52 +00001785/* Call Control */
1786
Harald Welte7584aea2009-02-11 11:44:12 +00001787/* The entire call control code is written in accordance with Figure 7.10c
1788 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1789 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1790 * it for voice */
1791
Harald Welte4bfdfe72009-06-10 23:11:52 +08001792static void new_cc_state(struct gsm_trans *trans, int state)
1793{
1794 if (state > 31 || state < 0)
1795 return;
1796
1797 DEBUGP(DCC, "new state %s -> %s\n",
1798 cc_state_names[trans->state], cc_state_names[state]);
1799
1800 trans->state = state;
1801}
1802
1803static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001804{
1805 struct msgb *msg = gsm48_msgb_alloc();
1806 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1807 u_int8_t *cause, *call_state;
1808
Harald Welte4bfdfe72009-06-10 23:11:52 +08001809 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1810 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001811 gh->msg_type = GSM48_MT_CC_STATUS;
1812
1813 cause = msgb_put(msg, 3);
1814 cause[0] = 2;
1815 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1816 cause[2] = 0x80 | 30; /* response to status inquiry */
1817
1818 call_state = msgb_put(msg, 1);
1819 call_state[0] = 0xc0 | 0x00;
1820
Harald Welte65e74cc2008-12-29 01:55:35 +00001821 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001822}
1823
Harald Welte6f4b7532008-12-29 00:39:37 +00001824static int gsm48_tx_simple(struct gsm_lchan *lchan,
1825 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001826{
1827 struct msgb *msg = gsm48_msgb_alloc();
1828 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1829
1830 msg->lchan = lchan;
1831
Harald Welte6f4b7532008-12-29 00:39:37 +00001832 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001833 gh->msg_type = msg_type;
1834
Harald Welte65e74cc2008-12-29 01:55:35 +00001835 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001836}
1837
Harald Welte4bfdfe72009-06-10 23:11:52 +08001838static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1839{
1840 if (bsc_timer_pending(&trans->cc_timer)) {
1841 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1842 bsc_del_timer(&trans->cc_timer);
1843 trans->Tcurrent = 0;
1844 }
1845}
1846
1847static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1848 int msg_type, struct gsm_mncc *mncc)
1849{
1850 struct msgb *msg;
1851
1852 if (trans)
1853 if (trans->lchan)
1854 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1855 "Sending '%s' to MNCC.\n",
1856 trans->lchan->ts->trx->bts->nr,
1857 trans->lchan->ts->trx->nr,
1858 trans->lchan->ts->nr, trans->transaction_id,
1859 (trans->subscr)?(trans->subscr->extension):"-",
1860 get_mncc_name(msg_type));
1861 else
1862 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1863 "Sending '%s' to MNCC.\n",
1864 (trans->subscr)?(trans->subscr->extension):"-",
1865 get_mncc_name(msg_type));
1866 else
1867 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1868 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1869
1870 mncc->msg_type = msg_type;
1871
Harald Welte966636f2009-06-26 19:39:35 +02001872 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001873 if (!msg)
1874 return -ENOMEM;
1875 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1876 msgb_enqueue(&net->upqueue, msg);
1877
1878 return 0;
1879}
1880
1881int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1882 u_int32_t callref, int location, int value)
1883{
1884 struct gsm_mncc rel;
1885
Harald Welte92f70c52009-06-12 01:54:08 +08001886 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001887 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001888 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001889 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1890}
1891
1892void free_trans(struct gsm_trans *trans)
1893{
1894 struct gsm_bts *bts;
1895
1896 gsm48_stop_cc_timer(trans);
1897
1898 /* send release to L4, if callref still exists */
1899 if (trans->callref) {
1900 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001901 mncc_release_ind(trans->network, trans, trans->callref,
1902 GSM48_CAUSE_LOC_PRN_S_LU,
1903 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001904 if (trans->state != GSM_CSTATE_NULL)
1905 new_cc_state(trans, GSM_CSTATE_NULL);
1906 }
1907
1908 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1909 /* Stop paging on all bts' */
1910 bts = NULL;
1911 do {
1912 bts = gsm_bts_by_lac(trans->subscr->net,
1913 trans->subscr->lac, bts);
1914 if (!bts)
1915 break;
1916 /* Stop paging */
1917 paging_request_stop(bts, trans->subscr, NULL);
1918 } while (1);
1919 }
1920
1921 if (trans->lchan) {
1922 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1923 put_lchan(trans->lchan);
1924 }
1925
1926 if (trans->subscr)
1927 subscr_put(trans->subscr);
1928
1929 if (trans->state != GSM_CSTATE_NULL)
1930 new_cc_state(trans, GSM_CSTATE_NULL);
1931
1932 llist_del(&trans->entry);
1933
Harald Welte2cf161b2009-06-20 22:36:41 +02001934 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001935}
1936
1937static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1938
Harald Welte09e38af2009-02-16 22:52:23 +00001939/* call-back from paging the B-end of the connection */
1940static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001941 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001942{
Harald Welte7ccf7782009-02-17 01:43:01 +00001943 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001944 struct gsm_subscriber *subscr = param;
1945 struct gsm_trans *transt, *tmp;
1946 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001947
Harald Welte09e38af2009-02-16 22:52:23 +00001948 if (hooknum != GSM_HOOK_RR_PAGING)
1949 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001950
1951 if (!subscr)
1952 return -EINVAL;
1953 net = subscr->net;
1954 if (!net) {
1955 DEBUGP(DCC, "Error Network not set!\n");
1956 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001957 }
Harald Welte7584aea2009-02-11 11:44:12 +00001958
Harald Welte4bfdfe72009-06-10 23:11:52 +08001959 /* check all tranactions (without lchan) for subscriber */
1960 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1961 if (transt->subscr != subscr || transt->lchan)
1962 continue;
1963 switch (event) {
1964 case GSM_PAGING_SUCCEEDED:
1965 if (!lchan) // paranoid
1966 break;
1967 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1968 subscr->extension);
1969 /* Assign lchan */
1970 if (!transt->lchan) {
1971 transt->lchan = lchan;
1972 use_lchan(lchan);
1973 }
1974 /* send SETUP request to called party */
1975 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1976 if (is_ipaccess_bts(lchan->ts->trx->bts))
1977 rsl_ipacc_bind(lchan);
1978 break;
1979 case GSM_PAGING_EXPIRED:
1980 DEBUGP(DCC, "Paging subscr %s expired!\n",
1981 subscr->extension);
1982 /* Temporarily out of order */
1983 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001984 GSM48_CAUSE_LOC_PRN_S_LU,
1985 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001986 transt->callref = 0;
1987 free_trans(transt);
1988 break;
1989 }
1990 }
Harald Welte09e38af2009-02-16 22:52:23 +00001991 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001992}
Harald Welte7584aea2009-02-11 11:44:12 +00001993
Harald Welte49f48b82009-02-17 15:29:33 +00001994/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001995static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001996{
Harald Welte11fa29c2009-02-19 17:24:39 +00001997 struct gsm_bts *bts = lchan->ts->trx->bts;
1998 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001999 struct gsm_bts_trx_ts *ts;
2000
Harald Welte11fa29c2009-02-19 17:24:39 +00002001 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2002 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2003 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2004
2005 if (bts->type != remote_bts->type) {
2006 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2007 return -EINVAL;
2008 }
Harald Welte49f48b82009-02-17 15:29:33 +00002009
Harald Welte11fa29c2009-02-19 17:24:39 +00002010 switch (bts->type) {
2011 case GSM_BTS_TYPE_NANOBTS_900:
2012 case GSM_BTS_TYPE_NANOBTS_1800:
2013 ts = remote_lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002014 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2015 ts->abis_ip.bound_port,
2016 lchan->ts->abis_ip.conn_id,
2017 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002018
2019 ts = lchan->ts;
Harald Welte20855542009-07-12 09:50:35 +02002020 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2021 ts->abis_ip.bound_port,
2022 remote_lchan->ts->abis_ip.conn_id,
2023 ts->abis_ip.rtp_payload2);
Harald Welte11fa29c2009-02-19 17:24:39 +00002024 break;
2025 case GSM_BTS_TYPE_BS11:
2026 trau_mux_map_lchan(lchan, remote_lchan);
2027 break;
2028 default:
2029 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2030 break;
2031 }
Harald Welte49f48b82009-02-17 15:29:33 +00002032
2033 return 0;
2034}
2035
Harald Welte4bfdfe72009-06-10 23:11:52 +08002036static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002037{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002038 struct gsm_trans *trans;
2039 llist_for_each_entry(trans, &net->trans_list, entry) {
2040 if (trans->callref == callref)
2041 return trans;
2042 }
2043 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002044}
2045
Harald Welte4bfdfe72009-06-10 23:11:52 +08002046/* bridge channels of two transactions */
2047static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002048{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002049 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2050 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002051
Harald Welte4bfdfe72009-06-10 23:11:52 +08002052 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002053 return -EIO;
2054
Harald Welte4bfdfe72009-06-10 23:11:52 +08002055 if (!trans1->lchan || !trans2->lchan)
2056 return -EIO;
2057
2058 /* through-connect channel */
2059 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002060}
2061
Harald Welte4bfdfe72009-06-10 23:11:52 +08002062/* enable receive of channels to upqueue */
2063static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2064{
2065 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002066
Harald Welte4bfdfe72009-06-10 23:11:52 +08002067 /* Find callref */
2068 trans = get_trans_ref(net, data->callref);
2069 if (!trans)
2070 return -EIO;
2071 if (!trans->lchan)
2072 return 0;
2073
2074 // todo IPACCESS
2075 if (enable)
2076 return trau_recv_lchan(trans->lchan, data->callref);
2077 return trau_mux_unmap(NULL, data->callref);
2078}
2079
2080/* send a frame to channel */
2081static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2082{
2083 struct gsm_trans *trans;
2084
2085 /* Find callref */
2086 trans = get_trans_ref(net, frame->callref);
2087 if (!trans)
2088 return -EIO;
2089 if (!trans->lchan)
2090 return 0;
2091 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2092 trans->lchan->type != GSM_LCHAN_TCH_H)
2093 return 0;
2094
2095 // todo IPACCESS
2096 return trau_send_lchan(trans->lchan,
2097 (struct decoded_trau_frame *)frame->data);
2098}
2099
2100
2101static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2102{
2103 DEBUGP(DCC, "-> STATUS ENQ\n");
2104 return gsm48_cc_tx_status(trans, msg);
2105}
2106
2107static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2108static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2109
2110static void gsm48_cc_timeout(void *arg)
2111{
2112 struct gsm_trans *trans = arg;
2113 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002114 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2115 int mo_location = GSM48_CAUSE_LOC_USER;
2116 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2117 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002118 struct gsm_mncc mo_rel, l4_rel;
2119
2120 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2121 mo_rel.callref = trans->callref;
2122 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2123 l4_rel.callref = trans->callref;
2124
2125 switch(trans->Tcurrent) {
2126 case 0x303:
2127 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002128 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002129 break;
2130 case 0x310:
2131 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002132 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002133 break;
2134 case 0x313:
2135 disconnect = 1;
2136 /* unknown, did not find it in the specs */
2137 break;
2138 case 0x301:
2139 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002140 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002141 break;
2142 case 0x308:
2143 if (!trans->T308_second) {
2144 /* restart T308 a second time */
2145 gsm48_cc_tx_release(trans, &trans->cc_msg);
2146 trans->T308_second = 1;
2147 break; /* stay in release state */
2148 }
2149 free_trans(trans);
2150 return;
2151// release = 1;
2152// l4_cause = 14;
2153// break;
2154 case 0x306:
2155 release = 1;
2156 mo_cause = trans->cc_msg.cause.value;
2157 mo_location = trans->cc_msg.cause.location;
2158 break;
2159 case 0x323:
2160 disconnect = 1;
2161 break;
2162 default:
2163 release = 1;
2164 }
2165
2166 if (release && trans->callref) {
2167 /* process release towards layer 4 */
2168 mncc_release_ind(trans->network, trans, trans->callref,
2169 l4_location, l4_cause);
2170 trans->callref = 0;
2171 }
2172
2173 if (disconnect && trans->callref) {
2174 /* process disconnect towards layer 4 */
2175 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2176 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2177 }
2178
2179 /* process disconnect towards mobile station */
2180 if (disconnect || release) {
2181 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2182 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2183 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2184 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2185 mo_rel.cause.diag_len = 3;
2186
2187 if (disconnect)
2188 gsm48_cc_tx_disconnect(trans, &mo_rel);
2189 if (release)
2190 gsm48_cc_tx_release(trans, &mo_rel);
2191 }
2192
2193}
2194
2195static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2196 int sec, int micro)
2197{
2198 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2199 trans->cc_timer.cb = gsm48_cc_timeout;
2200 trans->cc_timer.data = trans;
2201 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2202 trans->Tcurrent = current;
2203}
2204
2205static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2206{
2207 struct gsm48_hdr *gh = msgb_l3(msg);
2208 u_int8_t msg_type = gh->msg_type & 0xbf;
2209 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2210 struct tlv_parsed tp;
2211 struct gsm_mncc setup;
2212
2213 memset(&setup, 0, sizeof(struct gsm_mncc));
2214 setup.callref = trans->callref;
2215 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2216 /* emergency setup is identified by msg_type */
2217 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2218 setup.emergency = 1;
2219
2220 /* use subscriber as calling party number */
2221 if (trans->subscr) {
2222 setup.fields |= MNCC_F_CALLING;
2223 strncpy(setup.calling.number, trans->subscr->extension,
2224 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002225 strncpy(setup.imsi, trans->subscr->imsi,
2226 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002227 }
2228 /* bearer capability */
2229 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2230 setup.fields |= MNCC_F_BEARER_CAP;
2231 decode_bearer_cap(&setup.bearer_cap,
2232 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2233 }
2234 /* facility */
2235 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2236 setup.fields |= MNCC_F_FACILITY;
2237 decode_facility(&setup.facility,
2238 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2239 }
2240 /* called party bcd number */
2241 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2242 setup.fields |= MNCC_F_CALLED;
2243 decode_called(&setup.called,
2244 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2245 }
2246 /* user-user */
2247 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2248 setup.fields |= MNCC_F_USERUSER;
2249 decode_useruser(&setup.useruser,
2250 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2251 }
2252 /* ss-version */
2253 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2254 setup.fields |= MNCC_F_SSVERSION;
2255 decode_ssversion(&setup.ssversion,
2256 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2257 }
2258 /* CLIR suppression */
2259 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2260 setup.clir.sup = 1;
2261 /* CLIR invocation */
2262 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2263 setup.clir.inv = 1;
2264 /* cc cap */
2265 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2266 setup.fields |= MNCC_F_CCCAP;
2267 decode_cccap(&setup.cccap,
2268 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2269 }
2270
2271 if (is_ipaccess_bts(msg->trx->bts))
2272 rsl_ipacc_bind(msg->lchan);
2273
2274 new_cc_state(trans, GSM_CSTATE_INITIATED);
2275
2276 /* indicate setup to MNCC */
2277 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2278
2279 return 0;
2280}
2281
2282static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002283{
2284 struct msgb *msg = gsm48_msgb_alloc();
2285 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002286 struct gsm_mncc *setup = arg;
2287 struct gsm_trans *transt;
2288 u_int16_t trans_id_mask = 0;
2289 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002290
Harald Welte7ccf7782009-02-17 01:43:01 +00002291 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002292
Harald Welte4bfdfe72009-06-10 23:11:52 +08002293 /* transaction id must not be assigned */
2294 if (trans->transaction_id != 0xff) { /* unasssigned */
2295 DEBUGP(DCC, "TX Setup with assigned transaction. "
2296 "This is not allowed!\n");
2297 /* Temporarily out of order */
2298 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002299 GSM48_CAUSE_LOC_PRN_S_LU,
2300 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002301 trans->callref = 0;
2302 free_trans(trans);
2303 return rc;
2304 }
2305
2306 /* Get free transaction_id */
2307 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2308 /* Transaction of our lchan? */
2309 if (transt->lchan == trans->lchan &&
2310 transt->transaction_id != 0xff)
2311 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2312 }
2313 /* Assign free transaction ID */
2314 if ((trans_id_mask & 0x007f) == 0x7f) {
2315 /* no free transaction ID */
2316 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002317 GSM48_CAUSE_LOC_PRN_S_LU,
2318 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002319 trans->callref = 0;
2320 free_trans(trans);
2321 return rc;
2322 }
2323 for (i = 0; i < 7; i++) {
2324 if ((trans_id_mask & (1 << i)) == 0) {
2325 trans->transaction_id = i << 4; /* flag = 0 */
2326 break;
2327 }
2328 }
Harald Welte49f48b82009-02-17 15:29:33 +00002329
Harald Welte4bfdfe72009-06-10 23:11:52 +08002330 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2331 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002332 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002333
Harald Welte4bfdfe72009-06-10 23:11:52 +08002334 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002335
Harald Welte4bfdfe72009-06-10 23:11:52 +08002336 /* bearer capability */
2337 if (setup->fields & MNCC_F_BEARER_CAP)
2338 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2339 /* facility */
2340 if (setup->fields & MNCC_F_FACILITY)
2341 encode_facility(msg, 0, &setup->facility);
2342 /* progress */
2343 if (setup->fields & MNCC_F_PROGRESS)
2344 encode_progress(msg, 0, &setup->progress);
2345 /* calling party BCD number */
2346 if (setup->fields & MNCC_F_CALLING)
2347 encode_calling(msg, &setup->calling);
2348 /* called party BCD number */
2349 if (setup->fields & MNCC_F_CALLED)
2350 encode_called(msg, &setup->called);
2351 /* user-user */
2352 if (setup->fields & MNCC_F_USERUSER)
2353 encode_useruser(msg, 0, &setup->useruser);
2354 /* redirecting party BCD number */
2355 if (setup->fields & MNCC_F_REDIRECTING)
2356 encode_redirecting(msg, &setup->redirecting);
2357 /* signal */
2358 if (setup->fields & MNCC_F_SIGNAL)
2359 encode_signal(msg, setup->signal);
2360
2361 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002362
2363 return gsm48_sendmsg(msg);
2364}
2365
Harald Welte4bfdfe72009-06-10 23:11:52 +08002366static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2367{
2368 struct gsm48_hdr *gh = msgb_l3(msg);
2369 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2370 struct tlv_parsed tp;
2371 struct gsm_mncc call_conf;
2372
2373 gsm48_stop_cc_timer(trans);
2374 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2375
2376 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2377 call_conf.callref = trans->callref;
2378 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2379#if 0
2380 /* repeat */
2381 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2382 call_conf.repeat = 1;
2383 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2384 call_conf.repeat = 2;
2385#endif
2386 /* bearer capability */
2387 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2388 call_conf.fields |= MNCC_F_BEARER_CAP;
2389 decode_bearer_cap(&call_conf.bearer_cap,
2390 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2391 }
2392 /* cause */
2393 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2394 call_conf.fields |= MNCC_F_CAUSE;
2395 decode_cause(&call_conf.cause,
2396 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2397 }
2398 /* cc cap */
2399 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2400 call_conf.fields |= MNCC_F_CCCAP;
2401 decode_cccap(&call_conf.cccap,
2402 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2403 }
2404
2405 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2406
2407 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2408}
2409
2410static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2411{
2412 struct gsm_mncc *proceeding = arg;
2413 struct msgb *msg = gsm48_msgb_alloc();
2414 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2415
2416 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2417 msg->lchan = trans->lchan;
2418 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2419
2420 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2421
2422 /* bearer capability */
2423 if (proceeding->fields & MNCC_F_BEARER_CAP)
2424 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2425 /* facility */
2426 if (proceeding->fields & MNCC_F_FACILITY)
2427 encode_facility(msg, 0, &proceeding->facility);
2428 /* progress */
2429 if (proceeding->fields & MNCC_F_PROGRESS)
2430 encode_progress(msg, 0, &proceeding->progress);
2431
2432 return gsm48_sendmsg(msg);
2433}
2434
2435static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2436{
2437 struct gsm48_hdr *gh = msgb_l3(msg);
2438 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2439 struct tlv_parsed tp;
2440 struct gsm_mncc alerting;
2441
2442 gsm48_stop_cc_timer(trans);
2443 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2444
2445 memset(&alerting, 0, sizeof(struct gsm_mncc));
2446 alerting.callref = trans->callref;
2447 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2448 /* facility */
2449 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2450 alerting.fields |= MNCC_F_FACILITY;
2451 decode_facility(&alerting.facility,
2452 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2453 }
2454
2455 /* progress */
2456 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2457 alerting.fields |= MNCC_F_PROGRESS;
2458 decode_progress(&alerting.progress,
2459 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2460 }
2461 /* ss-version */
2462 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2463 alerting.fields |= MNCC_F_SSVERSION;
2464 decode_ssversion(&alerting.ssversion,
2465 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2466 }
2467
2468 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2469
2470 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2471}
2472
2473static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2474{
2475 struct gsm_mncc *alerting = arg;
2476 struct msgb *msg = gsm48_msgb_alloc();
2477 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2478
2479 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2480 msg->lchan = trans->lchan;
2481 gh->msg_type = GSM48_MT_CC_ALERTING;
2482
2483 /* facility */
2484 if (alerting->fields & MNCC_F_FACILITY)
2485 encode_facility(msg, 0, &alerting->facility);
2486 /* progress */
2487 if (alerting->fields & MNCC_F_PROGRESS)
2488 encode_progress(msg, 0, &alerting->progress);
2489 /* user-user */
2490 if (alerting->fields & MNCC_F_USERUSER)
2491 encode_useruser(msg, 0, &alerting->useruser);
2492
2493 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2494
2495 return gsm48_sendmsg(msg);
2496}
2497
2498static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2499{
2500 struct gsm_mncc *progress = arg;
2501 struct msgb *msg = gsm48_msgb_alloc();
2502 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2503
2504 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2505 msg->lchan = trans->lchan;
2506 gh->msg_type = GSM48_MT_CC_PROGRESS;
2507
2508 /* progress */
2509 encode_progress(msg, 1, &progress->progress);
2510 /* user-user */
2511 if (progress->fields & MNCC_F_USERUSER)
2512 encode_useruser(msg, 0, &progress->useruser);
2513
2514 return gsm48_sendmsg(msg);
2515}
2516
2517static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2518{
2519 struct gsm_mncc *connect = arg;
2520 struct msgb *msg = gsm48_msgb_alloc();
2521 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2522
2523 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2524 msg->lchan = trans->lchan;
2525 gh->msg_type = GSM48_MT_CC_CONNECT;
2526
2527 gsm48_stop_cc_timer(trans);
2528 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2529
2530 /* facility */
2531 if (connect->fields & MNCC_F_FACILITY)
2532 encode_facility(msg, 0, &connect->facility);
2533 /* progress */
2534 if (connect->fields & MNCC_F_PROGRESS)
2535 encode_progress(msg, 0, &connect->progress);
2536 /* connected number */
2537 if (connect->fields & MNCC_F_CONNECTED)
2538 encode_connected(msg, &connect->connected);
2539 /* user-user */
2540 if (connect->fields & MNCC_F_USERUSER)
2541 encode_useruser(msg, 0, &connect->useruser);
2542
2543 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2544
2545 return gsm48_sendmsg(msg);
2546}
2547
2548static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2549{
2550 struct gsm48_hdr *gh = msgb_l3(msg);
2551 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2552 struct tlv_parsed tp;
2553 struct gsm_mncc connect;
2554
2555 gsm48_stop_cc_timer(trans);
2556
2557 memset(&connect, 0, sizeof(struct gsm_mncc));
2558 connect.callref = trans->callref;
2559 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2560 /* use subscriber as connected party number */
2561 if (trans->subscr) {
2562 connect.fields |= MNCC_F_CONNECTED;
2563 strncpy(connect.connected.number, trans->subscr->extension,
2564 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002565 strncpy(connect.imsi, trans->subscr->imsi,
2566 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002567 }
2568 /* facility */
2569 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2570 connect.fields |= MNCC_F_FACILITY;
2571 decode_facility(&connect.facility,
2572 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2573 }
2574 /* user-user */
2575 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2576 connect.fields |= MNCC_F_USERUSER;
2577 decode_useruser(&connect.useruser,
2578 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2579 }
2580 /* ss-version */
2581 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2582 connect.fields |= MNCC_F_SSVERSION;
2583 decode_ssversion(&connect.ssversion,
2584 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2585 }
2586
2587 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2588
2589 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2590}
2591
2592
2593static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2594{
2595 struct gsm_mncc connect_ack;
2596
2597 gsm48_stop_cc_timer(trans);
2598
2599 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2600
2601 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2602 connect_ack.callref = trans->callref;
2603 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2604 &connect_ack);
2605}
2606
2607static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2608{
2609 struct msgb *msg = gsm48_msgb_alloc();
2610 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2611
2612 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2613 msg->lchan = trans->lchan;
2614 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2615
2616 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2617
2618 return gsm48_sendmsg(msg);
2619}
2620
2621static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2622{
2623 struct gsm48_hdr *gh = msgb_l3(msg);
2624 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2625 struct tlv_parsed tp;
2626 struct gsm_mncc disc;
2627
2628 gsm48_stop_cc_timer(trans);
2629
2630 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2631
2632 memset(&disc, 0, sizeof(struct gsm_mncc));
2633 disc.callref = trans->callref;
2634 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2635 /* cause */
2636 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2637 disc.fields |= MNCC_F_CAUSE;
2638 decode_cause(&disc.cause,
2639 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2640 }
2641 /* facility */
2642 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2643 disc.fields |= MNCC_F_FACILITY;
2644 decode_facility(&disc.facility,
2645 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2646 }
2647 /* user-user */
2648 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2649 disc.fields |= MNCC_F_USERUSER;
2650 decode_useruser(&disc.useruser,
2651 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2652 }
2653 /* ss-version */
2654 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2655 disc.fields |= MNCC_F_SSVERSION;
2656 decode_ssversion(&disc.ssversion,
2657 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2658 }
2659
2660 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2661
2662}
2663
Harald Weltec66b71c2009-06-11 14:23:20 +08002664static struct gsm_mncc_cause default_cause = {
2665 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2666 .coding = 0,
2667 .rec = 0,
2668 .rec_val = 0,
2669 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2670 .diag_len = 0,
2671 .diag = { 0 },
2672};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002673
2674static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2675{
2676 struct gsm_mncc *disc = arg;
2677 struct msgb *msg = gsm48_msgb_alloc();
2678 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2679
2680 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2681 msg->lchan = trans->lchan;
2682 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2683
2684 gsm48_stop_cc_timer(trans);
2685 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2686
2687 /* cause */
2688 if (disc->fields & MNCC_F_CAUSE)
2689 encode_cause(msg, 1, &disc->cause);
2690 else
2691 encode_cause(msg, 1, &default_cause);
2692
2693 /* facility */
2694 if (disc->fields & MNCC_F_FACILITY)
2695 encode_facility(msg, 0, &disc->facility);
2696 /* progress */
2697 if (disc->fields & MNCC_F_PROGRESS)
2698 encode_progress(msg, 0, &disc->progress);
2699 /* user-user */
2700 if (disc->fields & MNCC_F_USERUSER)
2701 encode_useruser(msg, 0, &disc->useruser);
2702
2703 /* store disconnect cause for T306 expiry */
2704 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2705
2706 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2707
2708 return gsm48_sendmsg(msg);
2709}
2710
2711static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2712{
2713 struct gsm48_hdr *gh = msgb_l3(msg);
2714 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2715 struct tlv_parsed tp;
2716 struct gsm_mncc rel;
2717 int rc;
2718
2719 gsm48_stop_cc_timer(trans);
2720
2721 memset(&rel, 0, sizeof(struct gsm_mncc));
2722 rel.callref = trans->callref;
2723 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2724 /* cause */
2725 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2726 rel.fields |= MNCC_F_CAUSE;
2727 decode_cause(&rel.cause,
2728 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2729 }
2730 /* facility */
2731 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2732 rel.fields |= MNCC_F_FACILITY;
2733 decode_facility(&rel.facility,
2734 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2735 }
2736 /* user-user */
2737 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2738 rel.fields |= MNCC_F_USERUSER;
2739 decode_useruser(&rel.useruser,
2740 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2741 }
2742 /* ss-version */
2743 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2744 rel.fields |= MNCC_F_SSVERSION;
2745 decode_ssversion(&rel.ssversion,
2746 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2747 }
2748
2749 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2750 /* release collision 5.4.5 */
2751 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2752 } else {
2753 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2754 GSM48_MT_CC_RELEASE_COMPL);
2755 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2756 }
2757
2758 new_cc_state(trans, GSM_CSTATE_NULL);
2759
2760 trans->callref = 0;
2761 free_trans(trans);
2762
2763 return rc;
2764}
2765
2766static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2767{
2768 struct gsm_mncc *rel = arg;
2769 struct msgb *msg = gsm48_msgb_alloc();
2770 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2771
2772 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2773 msg->lchan = trans->lchan;
2774 gh->msg_type = GSM48_MT_CC_RELEASE;
2775
2776 trans->callref = 0;
2777
2778 gsm48_stop_cc_timer(trans);
2779 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2780
2781 /* cause */
2782 if (rel->fields & MNCC_F_CAUSE)
2783 encode_cause(msg, 0, &rel->cause);
2784 /* facility */
2785 if (rel->fields & MNCC_F_FACILITY)
2786 encode_facility(msg, 0, &rel->facility);
2787 /* user-user */
2788 if (rel->fields & MNCC_F_USERUSER)
2789 encode_useruser(msg, 0, &rel->useruser);
2790
2791 trans->T308_second = 0;
2792 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2793
2794 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2795 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2796
2797 return gsm48_sendmsg(msg);
2798}
2799
2800static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2801{
2802 struct gsm48_hdr *gh = msgb_l3(msg);
2803 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2804 struct tlv_parsed tp;
2805 struct gsm_mncc rel;
2806 int rc = 0;
2807
2808 gsm48_stop_cc_timer(trans);
2809
2810 memset(&rel, 0, sizeof(struct gsm_mncc));
2811 rel.callref = trans->callref;
2812 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2813 /* cause */
2814 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2815 rel.fields |= MNCC_F_CAUSE;
2816 decode_cause(&rel.cause,
2817 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2818 }
2819 /* facility */
2820 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2821 rel.fields |= MNCC_F_FACILITY;
2822 decode_facility(&rel.facility,
2823 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2824 }
2825 /* user-user */
2826 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2827 rel.fields |= MNCC_F_USERUSER;
2828 decode_useruser(&rel.useruser,
2829 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2830 }
2831 /* ss-version */
2832 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2833 rel.fields |= MNCC_F_SSVERSION;
2834 decode_ssversion(&rel.ssversion,
2835 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2836 }
2837
2838 if (trans->callref) {
2839 switch (trans->state) {
2840 case GSM_CSTATE_CALL_PRESENT:
2841 rc = mncc_recvmsg(trans->network, trans,
2842 MNCC_REJ_IND, &rel);
2843 break;
2844 case GSM_CSTATE_RELEASE_REQ:
2845 rc = mncc_recvmsg(trans->network, trans,
2846 MNCC_REL_CNF, &rel);
2847 break;
2848 default:
2849 rc = mncc_recvmsg(trans->network, trans,
2850 MNCC_REL_IND, &rel);
2851 }
2852 }
2853
2854 trans->callref = 0;
2855 free_trans(trans);
2856
2857 return rc;
2858}
2859
2860static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2861{
2862 struct gsm_mncc *rel = arg;
2863 struct msgb *msg = gsm48_msgb_alloc();
2864 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2865
2866 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2867 msg->lchan = trans->lchan;
2868 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2869
2870 trans->callref = 0;
2871
2872 gsm48_stop_cc_timer(trans);
2873
2874 /* cause */
2875 if (rel->fields & MNCC_F_CAUSE)
2876 encode_cause(msg, 0, &rel->cause);
2877 /* facility */
2878 if (rel->fields & MNCC_F_FACILITY)
2879 encode_facility(msg, 0, &rel->facility);
2880 /* user-user */
2881 if (rel->fields & MNCC_F_USERUSER)
2882 encode_useruser(msg, 0, &rel->useruser);
2883
2884 free_trans(trans);
2885
2886 return gsm48_sendmsg(msg);
2887}
2888
2889static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2890{
2891 struct gsm48_hdr *gh = msgb_l3(msg);
2892 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2893 struct tlv_parsed tp;
2894 struct gsm_mncc fac;
2895
2896 memset(&fac, 0, sizeof(struct gsm_mncc));
2897 fac.callref = trans->callref;
2898 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2899 /* facility */
2900 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2901 fac.fields |= MNCC_F_FACILITY;
2902 decode_facility(&fac.facility,
2903 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2904 }
2905 /* ss-version */
2906 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2907 fac.fields |= MNCC_F_SSVERSION;
2908 decode_ssversion(&fac.ssversion,
2909 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2910 }
2911
2912 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2913}
2914
2915static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2916{
2917 struct gsm_mncc *fac = arg;
2918 struct msgb *msg = gsm48_msgb_alloc();
2919 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2920
2921 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2922 msg->lchan = trans->lchan;
2923 gh->msg_type = GSM48_MT_CC_FACILITY;
2924
2925 /* facility */
2926 encode_facility(msg, 1, &fac->facility);
2927
2928 return gsm48_sendmsg(msg);
2929}
2930
2931static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2932{
2933 struct gsm_mncc hold;
2934
2935 memset(&hold, 0, sizeof(struct gsm_mncc));
2936 hold.callref = trans->callref;
2937 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2938}
2939
2940static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2941{
2942 struct msgb *msg = gsm48_msgb_alloc();
2943 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2944
2945 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2946 msg->lchan = trans->lchan;
2947 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2948
2949 return gsm48_sendmsg(msg);
2950}
2951
2952static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2953{
2954 struct gsm_mncc *hold_rej = arg;
2955 struct msgb *msg = gsm48_msgb_alloc();
2956 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2957
2958 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2959 msg->lchan = trans->lchan;
2960 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2961
2962 /* cause */
2963 if (hold_rej->fields & MNCC_F_CAUSE)
2964 encode_cause(msg, 1, &hold_rej->cause);
2965 else
2966 encode_cause(msg, 1, &default_cause);
2967
2968 return gsm48_sendmsg(msg);
2969}
2970
2971static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2972{
2973 struct gsm_mncc retrieve;
2974
2975 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2976 retrieve.callref = trans->callref;
2977 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2978}
2979
2980static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2981{
2982 struct msgb *msg = gsm48_msgb_alloc();
2983 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2984
2985 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2986 msg->lchan = trans->lchan;
2987 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2988
2989 return gsm48_sendmsg(msg);
2990}
2991
2992static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2993{
2994 struct gsm_mncc *retrieve_rej = arg;
2995 struct msgb *msg = gsm48_msgb_alloc();
2996 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2997
2998 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2999 msg->lchan = trans->lchan;
3000 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3001
3002 /* cause */
3003 if (retrieve_rej->fields & MNCC_F_CAUSE)
3004 encode_cause(msg, 1, &retrieve_rej->cause);
3005 else
3006 encode_cause(msg, 1, &default_cause);
3007
3008 return gsm48_sendmsg(msg);
3009}
3010
3011static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3012{
3013 struct gsm48_hdr *gh = msgb_l3(msg);
3014 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3015 struct tlv_parsed tp;
3016 struct gsm_mncc dtmf;
3017
3018 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3019 dtmf.callref = trans->callref;
3020 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3021 /* keypad facility */
3022 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3023 dtmf.fields |= MNCC_F_KEYPAD;
3024 decode_keypad(&dtmf.keypad,
3025 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3026 }
3027
3028 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3029}
3030
3031static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3032{
3033 struct gsm_mncc *dtmf = arg;
3034 struct msgb *msg = gsm48_msgb_alloc();
3035 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3036
3037 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3038 msg->lchan = trans->lchan;
3039 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3040
3041 /* keypad */
3042 if (dtmf->fields & MNCC_F_KEYPAD)
3043 encode_keypad(msg, dtmf->keypad);
3044
3045 return gsm48_sendmsg(msg);
3046}
3047
3048static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3049{
3050 struct gsm_mncc *dtmf = arg;
3051 struct msgb *msg = gsm48_msgb_alloc();
3052 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3053
3054 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3055 msg->lchan = trans->lchan;
3056 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3057
3058 /* cause */
3059 if (dtmf->fields & MNCC_F_CAUSE)
3060 encode_cause(msg, 1, &dtmf->cause);
3061 else
3062 encode_cause(msg, 1, &default_cause);
3063
3064 return gsm48_sendmsg(msg);
3065}
3066
3067static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3068{
3069 struct msgb *msg = gsm48_msgb_alloc();
3070 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3071
3072 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3073 msg->lchan = trans->lchan;
3074 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3075
3076 return gsm48_sendmsg(msg);
3077}
3078
3079static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3080{
3081 struct gsm_mncc dtmf;
3082
3083 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3084 dtmf.callref = trans->callref;
3085
3086 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3087}
3088
3089static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3090{
3091 struct gsm48_hdr *gh = msgb_l3(msg);
3092 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3093 struct tlv_parsed tp;
3094 struct gsm_mncc modify;
3095
3096 memset(&modify, 0, sizeof(struct gsm_mncc));
3097 modify.callref = trans->callref;
3098 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3099 /* bearer capability */
3100 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3101 modify.fields |= MNCC_F_BEARER_CAP;
3102 decode_bearer_cap(&modify.bearer_cap,
3103 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3104 }
3105
3106 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3107
3108 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3109}
3110
3111static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3112{
3113 struct gsm_mncc *modify = arg;
3114 struct msgb *msg = gsm48_msgb_alloc();
3115 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3116
3117 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3118 msg->lchan = trans->lchan;
3119 gh->msg_type = GSM48_MT_CC_MODIFY;
3120
3121 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3122
3123 /* bearer capability */
3124 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3125
3126 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3127
3128 return gsm48_sendmsg(msg);
3129}
3130
3131static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3132{
3133 struct gsm48_hdr *gh = msgb_l3(msg);
3134 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3135 struct tlv_parsed tp;
3136 struct gsm_mncc modify;
3137
3138 gsm48_stop_cc_timer(trans);
3139
3140 memset(&modify, 0, sizeof(struct gsm_mncc));
3141 modify.callref = trans->callref;
3142 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3143 /* bearer capability */
3144 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3145 modify.fields |= MNCC_F_BEARER_CAP;
3146 decode_bearer_cap(&modify.bearer_cap,
3147 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3148 }
3149
3150 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3151
3152 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3153}
3154
3155static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3156{
3157 struct gsm_mncc *modify = arg;
3158 struct msgb *msg = gsm48_msgb_alloc();
3159 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3160
3161 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3162 msg->lchan = trans->lchan;
3163 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3164
3165 /* bearer capability */
3166 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3167
3168 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3169
3170 return gsm48_sendmsg(msg);
3171}
3172
3173static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3174{
3175 struct gsm48_hdr *gh = msgb_l3(msg);
3176 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3177 struct tlv_parsed tp;
3178 struct gsm_mncc modify;
3179
3180 gsm48_stop_cc_timer(trans);
3181
3182 memset(&modify, 0, sizeof(struct gsm_mncc));
3183 modify.callref = trans->callref;
3184 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3185 /* bearer capability */
3186 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3187 modify.fields |= GSM48_IE_BEARER_CAP;
3188 decode_bearer_cap(&modify.bearer_cap,
3189 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3190 }
3191 /* cause */
3192 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3193 modify.fields |= MNCC_F_CAUSE;
3194 decode_cause(&modify.cause,
3195 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3196 }
3197
3198 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3199
3200 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3201}
3202
3203static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3204{
3205 struct gsm_mncc *modify = arg;
3206 struct msgb *msg = gsm48_msgb_alloc();
3207 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3208
3209 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3210 msg->lchan = trans->lchan;
3211 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3212
3213 /* bearer capability */
3214 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3215 /* cause */
3216 encode_cause(msg, 1, &modify->cause);
3217
3218 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3219
3220 return gsm48_sendmsg(msg);
3221}
3222
3223static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3224{
3225 struct gsm_mncc *notify = arg;
3226 struct msgb *msg = gsm48_msgb_alloc();
3227 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3228
3229 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3230 msg->lchan = trans->lchan;
3231 gh->msg_type = GSM48_MT_CC_NOTIFY;
3232
3233 /* notify */
3234 encode_notify(msg, notify->notify);
3235
3236 return gsm48_sendmsg(msg);
3237}
3238
3239static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3240{
3241 struct gsm48_hdr *gh = msgb_l3(msg);
3242 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3243// struct tlv_parsed tp;
3244 struct gsm_mncc notify;
3245
3246 memset(&notify, 0, sizeof(struct gsm_mncc));
3247 notify.callref = trans->callref;
3248// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3249 if (payload_len >= 1)
3250 decode_notify(&notify.notify, gh->data);
3251
3252 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3253}
3254
3255static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3256{
3257 struct gsm_mncc *user = arg;
3258 struct msgb *msg = gsm48_msgb_alloc();
3259 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3260
3261 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3262 msg->lchan = trans->lchan;
3263 gh->msg_type = GSM48_MT_CC_USER_INFO;
3264
3265 /* user-user */
3266 if (user->fields & MNCC_F_USERUSER)
3267 encode_useruser(msg, 1, &user->useruser);
3268 /* more data */
3269 if (user->more)
3270 encode_more(msg);
3271
3272 return gsm48_sendmsg(msg);
3273}
3274
3275static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3276{
3277 struct gsm48_hdr *gh = msgb_l3(msg);
3278 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3279 struct tlv_parsed tp;
3280 struct gsm_mncc user;
3281
3282 memset(&user, 0, sizeof(struct gsm_mncc));
3283 user.callref = trans->callref;
3284 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3285 /* user-user */
3286 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3287 user.fields |= MNCC_F_USERUSER;
3288 decode_useruser(&user.useruser,
3289 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3290 }
3291 /* more data */
3292 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3293 user.more = 1;
3294
3295 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3296}
3297
3298static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3299{
3300 struct gsm_mncc *mode = arg;
3301
3302 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3303}
3304
3305static struct downstate {
3306 u_int32_t states;
3307 int type;
3308 int (*rout) (struct gsm_trans *trans, void *arg);
3309} downstatelist[] = {
3310 /* mobile originating call establishment */
3311 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3312 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3313 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3314 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3315 {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 */
3316 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3317 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3318 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3319 /* mobile terminating call establishment */
3320 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3321 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3322 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3323 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3324 /* signalling during call */
3325 {SBIT(GSM_CSTATE_ACTIVE),
3326 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3327 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3328 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3329 {ALL_STATES,
3330 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3331 {ALL_STATES,
3332 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3333 {ALL_STATES,
3334 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3335 {SBIT(GSM_CSTATE_ACTIVE),
3336 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3337 {SBIT(GSM_CSTATE_ACTIVE),
3338 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3339 {SBIT(GSM_CSTATE_ACTIVE),
3340 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3341 {SBIT(GSM_CSTATE_ACTIVE),
3342 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3343 {SBIT(GSM_CSTATE_ACTIVE),
3344 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3345 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3346 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3347 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3348 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3349 {SBIT(GSM_CSTATE_ACTIVE),
3350 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3351 /* clearing */
3352 {SBIT(GSM_CSTATE_INITIATED),
3353 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3354 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3355 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3356 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3357 MNCC_REL_REQ, gsm48_cc_tx_release},
3358 /* special */
3359 {ALL_STATES,
3360 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3361};
3362
3363#define DOWNSLLEN \
3364 (sizeof(downstatelist) / sizeof(struct downstate))
3365
3366
3367int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3368{
3369 int i, j, k, l, rc = 0;
3370 struct gsm_trans *trans = NULL, *transt;
3371 struct gsm_subscriber *subscr;
3372 struct gsm_lchan *lchan = NULL, *lchant;
3373 struct gsm_bts *bts = NULL;
3374 struct gsm_bts_trx *trx;
3375 struct gsm_bts_trx_ts *ts;
3376 struct gsm_mncc *data = arg, rel;
3377
3378 /* handle special messages */
3379 switch(msg_type) {
3380 case MNCC_BRIDGE:
3381 return tch_bridge(net, arg);
3382 case MNCC_FRAME_DROP:
3383 return tch_recv(net, arg, 0);
3384 case MNCC_FRAME_RECV:
3385 return tch_recv(net, arg, 1);
3386 case GSM_TRAU_FRAME:
3387 return tch_frame(net, arg);
3388 }
3389
3390 memset(&rel, 0, sizeof(struct gsm_mncc));
3391 rel.callref = data->callref;
3392
3393 /* Find callref */
3394 trans = get_trans_ref(net, data->callref);
3395
3396 /* Callref unknown */
3397 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003398 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003399 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3400 "Received '%s' from MNCC with "
3401 "unknown callref %d\n", data->called.number,
3402 get_mncc_name(msg_type), data->callref);
3403 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003404 return mncc_release_ind(net, NULL, data->callref,
3405 GSM48_CAUSE_LOC_PRN_S_LU,
3406 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003407 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003408 if (!data->called.number[0] && !data->imsi[0]) {
3409 DEBUGP(DCC, "(bts - trx - ts - ti) "
3410 "Received '%s' from MNCC with "
3411 "no number or IMSI\n", get_mncc_name(msg_type));
3412 /* Invalid number */
3413 return mncc_release_ind(net, NULL, data->callref,
3414 GSM48_CAUSE_LOC_PRN_S_LU,
3415 GSM48_CC_CAUSE_INV_NR_FORMAT);
3416 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003417 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003418 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02003419 subscr = subscr_get_by_extension(net,
3420 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003421 else
Harald Welte9176bd42009-07-23 18:46:00 +02003422 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003423 /* If subscriber is not found */
3424 if (!subscr) {
3425 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3426 "Received '%s' from MNCC with "
3427 "unknown subscriber %s\n", data->called.number,
3428 get_mncc_name(msg_type), data->called.number);
3429 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003430 return mncc_release_ind(net, NULL, data->callref,
3431 GSM48_CAUSE_LOC_PRN_S_LU,
3432 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003433 }
3434 /* If subscriber is not "attached" */
3435 if (!subscr->lac) {
3436 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3437 "Received '%s' from MNCC with "
3438 "detached subscriber %s\n", data->called.number,
3439 get_mncc_name(msg_type), data->called.number);
3440 subscr_put(subscr);
3441 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003442 return mncc_release_ind(net, NULL, data->callref,
3443 GSM48_CAUSE_LOC_PRN_S_LU,
3444 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003445 }
3446 /* Create transaction */
Harald Weltec05677b2009-06-26 20:17:06 +02003447 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003448 DEBUGP(DCC, "No memory for trans.\n");
3449 subscr_put(subscr);
3450 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003451 mncc_release_ind(net, NULL, data->callref,
3452 GSM48_CAUSE_LOC_PRN_S_LU,
3453 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003454 return -ENOMEM;
3455 }
3456 trans->callref = data->callref;
3457 trans->network = net;
3458 trans->transaction_id = 0xff; /* unassigned */
3459 llist_add_tail(&trans->entry, &net->trans_list);
3460 /* Assign subscriber to transaction */
3461 trans->subscr = subscr;
3462 /* Find lchan */
3463 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003464 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003465 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003466 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003467 for (k = 0; k < TRX_NR_TS; k++) {
3468 ts = &trx->ts[k];
3469 for (l = 0; l < TS_MAX_LCHAN; l++) {
3470 lchant = &ts->lchan[l];
3471 if (lchant->subscr == subscr) {
3472 lchan = lchant;
3473 break;
3474 }
3475 }
3476 }
3477 }
3478 }
3479
3480 /* If subscriber has no lchan */
3481 if (!lchan) {
3482 /* find transaction with this subscriber already paging */
3483 llist_for_each_entry(transt, &net->trans_list, entry) {
3484 /* Transaction of our lchan? */
3485 if (transt == trans ||
3486 transt->subscr != subscr)
3487 continue;
3488 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3489 "Received '%s' from MNCC with "
3490 "unallocated channel, paging already "
3491 "started.\n", bts->nr,
3492 data->called.number,
3493 get_mncc_name(msg_type));
3494 return 0;
3495 }
3496 /* store setup informations until paging was successfull */
3497 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3498 /* start paging subscriber on all BTS with her location */
3499 subscr->net = net;
3500 bts = NULL;
3501 do {
3502 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3503 if (!bts)
3504 break;
3505 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3506 "Received '%s' from MNCC with "
3507 "unallocated channel, paging.\n",
3508 bts->nr, data->called.number,
3509 get_mncc_name(msg_type));
3510 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003511 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003512 setup_trig_pag_evt, subscr);
3513 } while (1);
3514 return 0;
3515 }
3516 /* Assign lchan */
3517 trans->lchan = lchan;
3518 use_lchan(lchan);
3519 }
3520 lchan = trans->lchan;
3521
3522 /* if paging did not respond yet */
3523 if (!lchan) {
3524 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3525 "Received '%s' from MNCC in paging state\n",
3526 (trans->subscr)?(trans->subscr->extension):"-",
3527 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003528 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3529 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003530 if (msg_type == MNCC_REL_REQ)
3531 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3532 else
3533 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3534 trans->callref = 0;
3535 free_trans(trans);
3536 return rc;
3537 }
3538
3539 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3540 "Received '%s' from MNCC in state %d (%s)\n",
3541 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3542 trans->transaction_id,
3543 (lchan->subscr)?(lchan->subscr->extension):"-",
3544 get_mncc_name(msg_type), trans->state,
3545 cc_state_names[trans->state]);
3546
3547 /* Find function for current state and message */
3548 for (i = 0; i < DOWNSLLEN; i++)
3549 if ((msg_type == downstatelist[i].type)
3550 && ((1 << trans->state) & downstatelist[i].states))
3551 break;
3552 if (i == DOWNSLLEN) {
3553 DEBUGP(DCC, "Message unhandled at this state.\n");
3554 return 0;
3555 }
3556
3557 rc = downstatelist[i].rout(trans, arg);
3558
3559 return rc;
3560}
3561
3562
3563static struct datastate {
3564 u_int32_t states;
3565 int type;
3566 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3567} datastatelist[] = {
3568 /* mobile originating call establishment */
3569 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3570 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3571 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3572 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3573 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3574 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3575 /* mobile terminating call establishment */
3576 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3577 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3578 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3579 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3580 {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 */
3581 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3582 /* signalling during call */
3583 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3584 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3585 {SBIT(GSM_CSTATE_ACTIVE),
3586 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3587 {ALL_STATES,
3588 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3589 {ALL_STATES,
3590 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3591 {ALL_STATES,
3592 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3593 {SBIT(GSM_CSTATE_ACTIVE),
3594 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3595 {SBIT(GSM_CSTATE_ACTIVE),
3596 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3597 {SBIT(GSM_CSTATE_ACTIVE),
3598 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3599 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3600 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3601 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3602 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3603 {SBIT(GSM_CSTATE_ACTIVE),
3604 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3605 /* clearing */
3606 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3607 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3608 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3609 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3610 {ALL_STATES, /* 5.4.3.4 */
3611 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3612};
3613
3614#define DATASLLEN \
3615 (sizeof(datastatelist) / sizeof(struct datastate))
3616
Harald Welte4bc90a12008-12-27 16:32:52 +00003617static int gsm0408_rcv_cc(struct msgb *msg)
3618{
3619 struct gsm48_hdr *gh = msgb_l3(msg);
3620 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003621 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3622 struct gsm_lchan *lchan = msg->lchan;
3623 struct gsm_trans *trans = NULL, *transt;
3624 struct gsm_network *net = lchan->ts->trx->bts->network;
3625 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003626
Harald Welte4bfdfe72009-06-10 23:11:52 +08003627 if (msg_type & 0x80) {
3628 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3629 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003630 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003631
3632 /* Find transaction */
3633 llist_for_each_entry(transt, &net->trans_list, entry) {
3634 /* Transaction of our lchan? */
3635 if (transt->lchan == lchan
3636 && transt->transaction_id == transaction_id) {
3637 trans = transt;
3638 }
3639 }
3640
3641 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3642 "Received '%s' from MS in state %d (%s)\n",
3643 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3644 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3645 cc_msg_names[msg_type], trans?(trans->state):0,
3646 cc_state_names[trans?(trans->state):0]);
3647
3648 /* Create transaction */
3649 if (!trans) {
3650 DEBUGP(DCC, "Unknown transaction ID %02x, "
3651 "creating new trans.\n", transaction_id);
3652 /* Create transaction */
Harald Welte9b11e872009-06-26 19:42:28 +02003653 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003654 DEBUGP(DCC, "No memory for trans.\n");
3655 rc = gsm48_tx_simple(msg->lchan,
3656 GSM48_PDISC_CC | transaction_id,
3657 GSM48_MT_CC_RELEASE_COMPL);
3658 return -ENOMEM;
3659 }
3660 llist_add_tail(&trans->entry, &net->trans_list);
3661 /* Assign transaction */
3662 trans->callref = new_callref++;
3663 trans->network = net;
3664 trans->transaction_id = transaction_id;
3665 trans->lchan = lchan;
3666 use_lchan(lchan);
3667 if (lchan->subscr) {
3668 trans->subscr = lchan->subscr;
3669 subscr_get(trans->subscr);
3670 }
3671 }
3672
3673 /* find function for current state and message */
3674 for (i = 0; i < DATASLLEN; i++)
3675 if ((msg_type == datastatelist[i].type)
3676 && ((1 << trans->state) & datastatelist[i].states))
3677 break;
3678 if (i == DATASLLEN) {
3679 DEBUGP(DCC, "Message unhandled at this state.\n");
3680 return 0;
3681 }
3682
3683 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003684
3685 return rc;
3686}
3687
Harald Welte52b1f982008-12-23 20:25:15 +00003688/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3689int gsm0408_rcvmsg(struct msgb *msg)
3690{
3691 struct gsm48_hdr *gh = msgb_l3(msg);
3692 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003693 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003694
3695 switch (pdisc) {
3696 case GSM48_PDISC_CC:
3697 rc = gsm0408_rcv_cc(msg);
3698 break;
3699 case GSM48_PDISC_MM:
3700 rc = gsm0408_rcv_mm(msg);
3701 break;
3702 case GSM48_PDISC_RR:
3703 rc = gsm0408_rcv_rr(msg);
3704 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003705 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003706 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003707 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003708 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003709 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003710 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3711 pdisc);
3712 break;
3713 default:
3714 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3715 pdisc);
3716 break;
3717 }
3718
3719 return rc;
3720}
Harald Welte8470bf22008-12-25 23:28:35 +00003721
Harald Welte8470bf22008-12-25 23:28:35 +00003722/* Section 9.1.8 / Table 9.9 */
3723struct chreq {
3724 u_int8_t val;
3725 u_int8_t mask;
3726 enum chreq_type type;
3727};
3728
3729/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3730static const struct chreq chreq_type_neci1[] = {
3731 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3732 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3733 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3734 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3735 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3736 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3737 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3738 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3739 { 0x10, 0xf0, CHREQ_T_SDCCH },
3740 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3741 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3742 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3743};
3744
3745/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3746static const struct chreq chreq_type_neci0[] = {
3747 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3748 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3749 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3750 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3751 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3752 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3753 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3754 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3755};
3756
3757static const enum gsm_chan_t ctype_by_chreq[] = {
3758 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3759 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3760 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3761 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3762 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3763 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3764 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3765 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3766 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3767 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3768 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3769 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3770};
3771
Harald Weltee14a57c2008-12-29 04:08:28 +00003772static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3773 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3774 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3775 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3776 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3777 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3778 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3779 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3780 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3781 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3782 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3783 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3784 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3785};
3786
Harald Welte8470bf22008-12-25 23:28:35 +00003787enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3788{
3789 int i;
3790 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3791
3792 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3793 const struct chreq *chr = &chreq_type_neci0[i];
3794 if ((ra & chr->mask) == chr->val)
3795 return ctype_by_chreq[chr->type];
3796 }
3797 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3798 return GSM_LCHAN_SDCCH;
3799}
Harald Weltee14a57c2008-12-29 04:08:28 +00003800
3801enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3802{
3803 int i;
3804 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3805
3806 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3807 const struct chreq *chr = &chreq_type_neci0[i];
3808 if ((ra & chr->mask) == chr->val)
3809 return reason_by_chreq[chr->type];
3810 }
3811 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3812 return GSM_CHREQ_REASON_OTHER;
3813}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003814
3815/* dequeue messages to layer 4 */
3816int bsc_upqueue(struct gsm_network *net)
3817{
3818 struct gsm_mncc *mncc;
3819 struct msgb *msg;
3820 int work = 0;
3821
3822 if (net)
3823 while ((msg = msgb_dequeue(&net->upqueue))) {
3824 mncc = (struct gsm_mncc *)msg->data;
3825 if (net->mncc_recv)
3826 net->mncc_recv(net, mncc->msg_type, mncc);
3827 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003828 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003829 }
3830
3831 return work;
3832}