blob: 56d3a1ccbf79a766e1e0717f011a79bf6efee0ee [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
Harald Weltebf5e8df2009-02-03 12:59:45 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte498b0bb2009-01-09 21:27:43 +00005 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
Harald Welte7584aea2009-02-11 11:44:12 +000035#include <openbsc/tlv.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000040#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000042#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000043#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000044#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000045#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000046#include <openbsc/trau_mux.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020047#include <openbsc/talloc.h>
Harald Welte52b1f982008-12-23 20:25:15 +000048
Harald Welte8470bf22008-12-25 23:28:35 +000049#define GSM48_ALLOC_SIZE 1024
50#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000051
Harald Welte0c389302009-06-10 12:08:54 +080052#define GSM_MAX_FACILITY 128
53#define GSM_MAX_SSVERSION 128
54#define GSM_MAX_USERUSER 128
55
Harald Welte2cf161b2009-06-20 22:36:41 +020056static void *tall_locop_ctx;
57static void *tall_trans_ctx;
58
Harald Welte09e38af2009-02-16 22:52:23 +000059static const struct tlv_definition rsl_att_tlvdef = {
60 .def = {
61 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
62 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
63 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
64 [GSM48_IE_UTC] = { TLV_TYPE_TV },
65 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
66 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
67
68 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
69 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
70 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
71 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
72 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
73 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
74 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080075 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000076 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
77 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080078 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
79 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000080 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
81 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
82 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
83 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
84 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
86 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
87 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
88 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
89 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
90 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
91 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
92 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
93 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080094 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
95 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +000096 /* FIXME: more elements */
97 },
98};
Harald Weltecf5b3592009-05-01 18:28:42 +000099
100static const char *rr_cause_names[] = {
101 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
102 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
103 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
104 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
105 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
106 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
107 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
108 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
109 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
110 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
111 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
112 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
113 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
114 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
115 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
116 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
117 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
118};
119
Harald Welte4bfdfe72009-06-10 23:11:52 +0800120static const char *cc_state_names[] = {
121 "NULL",
122 "INITIATED",
123 "illegal state 2",
124 "MO_CALL_PROC",
125 "CALL_DELIVERED",
126 "illegal state 5",
127 "CALL_PRESENT",
128 "CALL_RECEIVED",
129 "CONNECT_REQUEST",
130 "MO_TERM_CALL_CONF",
131 "ACTIVE",
132 "DISCONNECT_REQ",
133 "DISCONNECT_IND",
134 "illegal state 13",
135 "illegal state 14",
136 "illegal state 15",
137 "illegal state 16",
138 "illegal state 17",
139 "illegal state 18",
140 "RELEASE_REQ",
141 "illegal state 20",
142 "illegal state 21",
143 "illegal state 22",
144 "illegal state 23",
145 "illegal state 24",
146 "illegal state 25",
147 "MO_ORIG_MODIFY",
148 "MO_TERM_MODIFY",
149 "CONNECT_IND",
150 "illegal state 29",
151 "illegal state 30",
152 "illegal state 31",
153};
154
155static const char *cc_msg_names[] = {
156 "unknown 0x00",
157 "ALERTING",
158 "CALL_PROC",
159 "PROGRESS",
160 "ESTAB",
161 "SETUP",
162 "ESTAB_CONF",
163 "CONNECT",
164 "CALL_CONF",
165 "START_CC",
166 "unknown 0x0a",
167 "RECALL",
168 "unknown 0x0c",
169 "unknown 0x0d",
170 "EMERG_SETUP",
171 "CONNECT_ACK",
172 "USER_INFO",
173 "unknown 0x11",
174 "unknown 0x12",
175 "MODIFY_REJECT",
176 "unknown 0x14",
177 "unknown 0x15",
178 "unknown 0x16",
179 "MODIFY",
180 "HOLD",
181 "HOLD_ACK",
182 "HOLD_REJ",
183 "unknown 0x1b",
184 "RETR",
185 "RETR_ACK",
186 "RETR_REJ",
187 "MODIFY_COMPL",
188 "unknown 0x20",
189 "unknown 0x21",
190 "unknown 0x22",
191 "unknown 0x23",
192 "unknown 0x24",
193 "DISCONNECT",
194 "unknown 0x26",
195 "unknown 0x27",
196 "unknown 0x28",
197 "unknown 0x29",
198 "RELEASE_COMPL",
199 "unknown 0x2b",
200 "unknown 0x2c",
201 "RELEASE",
202 "unknown 0x2e",
203 "unknown 0x2f",
204 "unknown 0x30",
205 "STOP_DTMF",
206 "STOP_DTMF_ACK",
207 "unknown 0x33",
208 "STATUS_ENQ",
209 "START_DTMF",
210 "START_DTMF_ACK",
211 "START_DTMF_REJ",
212 "unknown 0x38",
213 "CONG_CTRL",
214 "FACILITY",
215 "unknown 0x3b",
216 "STATUS",
217 "unknown 0x3c",
218 "NOTIFY",
219 "unknown 0x3f",
220};
221
Harald Weltecf5b3592009-05-01 18:28:42 +0000222static char strbuf[64];
223
224static const char *rr_cause_name(u_int8_t cause)
225{
226 if (cause < ARRAY_SIZE(rr_cause_names) &&
227 rr_cause_names[cause])
228 return rr_cause_names[cause];
229
230 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
231 return strbuf;
232}
233
Harald Weltef7c43522009-06-09 20:24:21 +0000234static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
235 int len)
236{
237 memset(rep, 0, sizeof(*rep));
238
239 if (data[0] & 0x80)
240 rep->flags |= MEAS_REP_F_BA1;
241 if (data[0] & 0x40)
242 rep->flags |= MEAS_REP_F_DTX;
243 if (data[1] & 0x40)
244 rep->flags |= MEAS_REP_F_VALID;
245
246 rep->rxlev_full = data[0] & 0x3f;
247 rep->rxlev_sub = data[1] & 0x3f;
248 rep->rxqual_full = (data[3] >> 4) & 0x7;
249 rep->rxqual_sub = (data[3] >> 1) & 0x7;
250 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
251 if (rep->num_cell < 1)
252 return;
253
254 /* an encoding nightmare in perfection */
255
256 rep->cell[0].rxlev = data[4] & 0x3f;
257 rep->cell[0].bcch_freq = data[5] >> 2;
258 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
259 if (rep->num_cell < 2)
260 return;
261
262 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
263 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
264 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
265 if (rep->num_cell < 3)
266 return;
267
268 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
269 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
270 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
271 if (rep->num_cell < 4)
272 return;
273
274 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
275 rep->cell[3].bcch_freq = data[11] & 0x1f;
276 rep->cell[3].bsic = data[12] >> 2;
277 if (rep->num_cell < 5)
278 return;
279
280 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
281 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
282 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
283 if (rep->num_cell < 6)
284 return;
285
286 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
287 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
288 rep->cell[5].bsic = data[16] & 0x3f;
289}
290
Holger Freytherd51524f2009-06-09 08:27:07 +0000291int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000292static int gsm48_tx_simple(struct gsm_lchan *lchan,
293 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000294static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800295void free_trans(struct gsm_trans *trans);
Harald Welte65e74cc2008-12-29 01:55:35 +0000296
Harald Welte52b1f982008-12-23 20:25:15 +0000297struct gsm_lai {
298 u_int16_t mcc;
299 u_int16_t mnc;
300 u_int16_t lac;
301};
302
Holger Freyther89824fc2008-12-30 16:18:18 +0000303static int authorize_everonye = 0;
304void gsm0408_allow_everyone(int everyone)
305{
306 printf("Allowing everyone?\n");
307 authorize_everonye = everyone;
308}
309
Holger Freythere97f7fb2008-12-31 18:52:11 +0000310static int reject_cause = 0;
311void gsm0408_set_reject_cause(int cause)
312{
313 reject_cause = cause;
314}
315
Harald Welte4bfdfe72009-06-10 23:11:52 +0800316static u_int32_t new_callref = 0x80000001;
317
Holger Freyther73487a22008-12-31 18:53:57 +0000318static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
319 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000320{
321 if (!subscriber)
322 return 0;
323
Holger Freyther73487a22008-12-31 18:53:57 +0000324 /*
325 * Do not send accept yet as more information should arrive. Some
326 * phones will not send us the information and we will have to check
327 * what we want to do with that.
328 */
329 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
330 return 0;
331
Holger Freyther89824fc2008-12-30 16:18:18 +0000332 if (authorize_everonye)
333 return 1;
334
335 return subscriber->authorized;
336}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000337
Holger Freyther73487a22008-12-31 18:53:57 +0000338static void release_loc_updating_req(struct gsm_lchan *lchan)
339{
Harald Welte179f0642008-12-31 23:59:18 +0000340 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000341 return;
342
Harald Welteff117a82009-05-23 05:22:08 +0000343 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200344 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000345 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000346 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000347}
348
349static void allocate_loc_updating_req(struct gsm_lchan *lchan)
350{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000351 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000352 release_loc_updating_req(lchan);
353
Harald Welte2cf161b2009-06-20 22:36:41 +0200354 if (!tall_locop_ctx)
355 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
356 "loc_updating_oper");
Harald Welte470ec292009-06-26 20:25:23 +0200357 lchan->loc_operation = talloc_zero(tall_locop_ctx,
358 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000359}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000360
Holger Freytherd51524f2009-06-09 08:27:07 +0000361static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
362{
363 u_int32_t tmsi;
364
365 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
366 db_subscriber_alloc_tmsi(lchan->subscr);
367 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
368 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
369 release_loc_updating_req(lchan);
370 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
371 }
372
373 return 0;
374}
375
Holger Freyther7c19f742009-06-06 13:54:35 +0000376static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
377 void *handler_data, void *signal_data)
378{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800379 struct gsm_trans *trans, *temp;
380
Holger Freyther7c19f742009-06-06 13:54:35 +0000381 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
382 return 0;
383
384 /*
385 * Cancel any outstanding location updating request
386 * operation taking place on the lchan.
387 */
388 struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200389 if (!lchan)
390 return 0;
391
Holger Freyther7c19f742009-06-06 13:54:35 +0000392 release_loc_updating_req(lchan);
393
Harald Welte4bfdfe72009-06-10 23:11:52 +0800394 /* Free all transactions that are associated with the released lchan */
395 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
396 if (trans->lchan == lchan)
397 free_trans(trans);
398 }
399
Holger Freyther7c19f742009-06-06 13:54:35 +0000400 return 0;
401}
402
403/*
404 * This will be ran by the linker when loading the DSO. We use it to
405 * do system initialization, e.g. registration of signal handlers.
406 */
407static __attribute__((constructor)) void on_dso_load_0408(void)
408{
409 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
410}
411
Harald Welte52b1f982008-12-23 20:25:15 +0000412static void to_bcd(u_int8_t *bcd, u_int16_t val)
413{
Harald Welte4b634542008-12-27 01:55:51 +0000414 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000415 val = val / 10;
416 bcd[1] = val % 10;
417 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000418 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000419 val = val / 10;
420}
421
Holger Freyther17746612008-12-28 16:32:44 +0000422void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000423 u_int16_t mnc, u_int16_t lac)
424{
425 u_int8_t bcd[3];
426
427 to_bcd(bcd, mcc);
428 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
429 lai48->digits[1] = bcd[2];
430
431 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000432 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
433#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000434 lai48->digits[1] |= bcd[2] << 4;
435 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000436#else
437 lai48->digits[1] |= 0xf << 4;
438 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
439#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000440
Harald Welte4b634542008-12-27 01:55:51 +0000441 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000442}
443
Harald Welte255539c2008-12-28 02:26:27 +0000444#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000445#define MID_TMSI_LEN (TMSI_LEN + 2)
446
Harald Welte255539c2008-12-28 02:26:27 +0000447int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000448{
Harald Welte65e74cc2008-12-29 01:55:35 +0000449 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000450
Harald Welte4b634542008-12-27 01:55:51 +0000451 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000452 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000453 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000454 *tptr = htonl(tmsi);
455
456 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000457}
458
Harald Welte09e38af2009-02-16 22:52:23 +0000459static const char bcd_num_digits[] = {
460 '0', '1', '2', '3', '4', '5', '6', '7',
461 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
462};
463
Harald Welte0c389302009-06-10 12:08:54 +0800464/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
465int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
466 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000467{
468 u_int8_t in_len = bcd_lv[0];
469 int i;
470
Harald Welte0c389302009-06-10 12:08:54 +0800471 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000472 /* lower nibble */
473 output_len--;
474 if (output_len <= 1)
475 break;
476 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
477
478 /* higher nibble */
479 output_len--;
480 if (output_len <= 1)
481 break;
482 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
483 }
484 if (output_len >= 1)
485 *output++ = '\0';
486
Harald Welte0c389302009-06-10 12:08:54 +0800487 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000488}
489
490/* convert a single ASCII character to call-control BCD */
491static int asc_to_bcd(const char asc)
492{
493 int i;
494
495 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
496 if (bcd_num_digits[i] == asc)
497 return i;
498 }
499 return -EINVAL;
500}
501
Harald Welte0c389302009-06-10 12:08:54 +0800502/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000503int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800504 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000505{
506 int in_len = strlen(input);
507 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800508 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000509
510 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800511 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000512 if (in_len % 2)
513 bcd_lv[0]++;
514
Harald Welte0c389302009-06-10 12:08:54 +0800515 if (bcd_lv[0] > max_len)
516 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000517
518 for (i = 0; i < in_len; i++) {
519 int rc = asc_to_bcd(input[i]);
520 if (rc < 0)
521 return rc;
522 if (i % 2 == 0)
523 *bcd_cur = rc;
524 else
525 *bcd_cur++ |= (rc << 4);
526 }
527 /* append padding nibble in case of odd length */
528 if (i % 2)
529 *bcd_cur++ |= 0xf0;
530
531 /* return how many bytes we used */
532 return (bcd_cur - bcd_lv);
533}
534
Harald Welte0c389302009-06-10 12:08:54 +0800535/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800536static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800537 const u_int8_t *lv)
538{
539 u_int8_t in_len = lv[0];
540 int i, s;
541
542 if (in_len < 1)
543 return -EINVAL;
544
Harald Welte4bfdfe72009-06-10 23:11:52 +0800545 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800546
547 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800548 bcap->transfer = lv[1] & 0x07;
549 bcap->mode = (lv[1] & 0x08) >> 3;
550 bcap->coding = (lv[1] & 0x10) >> 4;
551 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800552
553 i = 1;
554 s = 0;
555 while(!(lv[i] & 0x80)) {
556 i++; /* octet 3a etc */
557 if (in_len < i)
558 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800559 bcap->speech_ver[s++] = lv[i] & 0x0f;
560 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800561 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800562 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800563 if (s == 7) /* maximum speech versions + end of list */
564 return 0;
565 }
566
567 return 0;
568}
569
570/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800571static int encode_bearer_cap(struct msgb *msg, int lv_only,
572 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800573{
574 u_int8_t lv[32 + 1];
575 int i, s;
576
Harald Welte4bfdfe72009-06-10 23:11:52 +0800577 lv[1] = bcap->transfer;
578 lv[1] |= bcap->mode << 3;
579 lv[1] |= bcap->coding << 4;
580 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800581
582 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800583 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800584 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800586 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800588 }
589 lv[i] |= 0x80; /* last IE of octet 3 etc */
590
591 lv[0] = i;
592 if (lv_only)
593 msgb_lv_put(msg, lv[0], lv+1);
594 else
595 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
596
597 return 0;
598}
599
600/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800601static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800602{
603 u_int8_t in_len = lv[0];
604
605 if (in_len < 1)
606 return -EINVAL;
607
608 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800609 ccap->dtmf = lv[1] & 0x01;
610 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800611
612 return 0;
613}
614
615/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800616static int decode_called(struct gsm_mncc_number *called,
617 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800618{
619 u_int8_t in_len = lv[0];
620
621 if (in_len < 1)
622 return -EINVAL;
623
624 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800625 called->plan = lv[1] & 0x0f;
626 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800627
628 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800629 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800630
631 return 0;
632}
633
634/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800635static int encode_called(struct msgb *msg,
636 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800637{
638 u_int8_t lv[18];
639 int ret;
640
641 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800642 lv[1] = called->plan;
643 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800644
645 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800646 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800647 if (ret < 0)
648 return ret;
649
650 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
651
652 return 0;
653}
654
655/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800656static int encode_callerid(struct msgb *msg, int ie,
657 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800658{
659 u_int8_t lv[13];
660 int h_len = 1;
661 int ret;
662
663 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800664 lv[1] = callerid->plan;
665 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800666
Harald Welte4bfdfe72009-06-10 23:11:52 +0800667 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800668 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800669 lv[2] = callerid->screen;
670 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800671 lv[2] |= 0x80;
672 h_len++;
673 } else
674 lv[1] |= 0x80;
675
676 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800677 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800678 if (ret < 0)
679 return ret;
680
681 msgb_tlv_put(msg, ie, lv[0], lv+1);
682
683 return 0;
684}
685
686/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800687static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800688 const u_int8_t *lv)
689{
690 u_int8_t in_len = lv[0];
691 int i;
692
693 if (in_len < 2)
694 return -EINVAL;
695
Harald Welte4bfdfe72009-06-10 23:11:52 +0800696 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800697
698 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800699 cause->location = lv[1] & 0x0f;
700 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800701
702 i = 1;
703 if (!(lv[i] & 0x80)) {
704 i++; /* octet 3a */
705 if (in_len < i+1)
706 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800707 cause->rec = 1;
708 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800709
710 }
711 i++;
712
713 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800714 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800715 i++;
716
717 if (in_len < i) /* no diag */
718 return 0;
719
720 if (in_len - (i-1) > 32) /* maximum 32 octets */
721 return 0;
722
723 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800724 memcpy(cause->diag, lv + i, in_len - (i-1));
725 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800726
727 return 0;
728}
729
730/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800731static int encode_cause(struct msgb *msg, int lv_only,
732 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800733{
734 u_int8_t lv[32+4];
735 int i;
736
Harald Welte4bfdfe72009-06-10 23:11:52 +0800737 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800738 return -EINVAL;
739
740 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800741 lv[1] = cause->location;
742 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800743
744 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800746 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800748 }
749 lv[i] |= 0x80; /* end of octet 3 */
750
751 /* octet 4 */
752 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800753 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800754
755 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800756 if (cause->diag_len) {
757 memcpy(lv + i, cause->diag, cause->diag_len);
758 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800759 }
760
761 lv[0] = i;
762 if (lv_only)
763 msgb_lv_put(msg, lv[0], lv+1);
764 else
765 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
766
767 return 0;
768}
769
770/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800771static int encode_calling(struct msgb *msg,
772 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800773{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800774 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800775}
776
777/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800778static int encode_connected(struct msgb *msg,
779 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800780{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800781 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800782}
783
784/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800785static int encode_redirecting(struct msgb *msg,
786 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800787{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800788 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800789}
790
791/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800792static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800793 const u_int8_t *lv)
794{
795 u_int8_t in_len = lv[0];
796
797 if (in_len < 1)
798 return -EINVAL;
799
Harald Welte4bfdfe72009-06-10 23:11:52 +0800800 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800801 return -EINVAL;
802
Harald Welte4bfdfe72009-06-10 23:11:52 +0800803 memcpy(facility->info, lv+1, in_len);
804 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800805
806 return 0;
807}
808
809/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800810static int encode_facility(struct msgb *msg, int lv_only,
811 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800812{
813 u_int8_t lv[GSM_MAX_FACILITY + 1];
814
Harald Welte4bfdfe72009-06-10 23:11:52 +0800815 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800816 return -EINVAL;
817
Harald Welte4bfdfe72009-06-10 23:11:52 +0800818 memcpy(lv+1, facility->info, facility->len);
819 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800820 if (lv_only)
821 msgb_lv_put(msg, lv[0], lv+1);
822 else
823 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
824
825 return 0;
826}
827
828/* decode 'notify' */
829static int decode_notify(int *notify, const u_int8_t *v)
830{
831 *notify = v[0] & 0x7f;
832
833 return 0;
834}
835
836/* encode 'notify' */
837static int encode_notify(struct msgb *msg, int notify)
838{
839 msgb_v_put(msg, notify | 0x80);
840
841 return 0;
842}
843
844/* encode 'signal' */
845static int encode_signal(struct msgb *msg, int signal)
846{
847 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
848
849 return 0;
850}
851
852/* decode 'keypad' */
853static int decode_keypad(int *keypad, const u_int8_t *lv)
854{
855 u_int8_t in_len = lv[0];
856
857 if (in_len < 1)
858 return -EINVAL;
859
860 *keypad = lv[1] & 0x7f;
861
862 return 0;
863}
864
865/* encode 'keypad' */
866static int encode_keypad(struct msgb *msg, int keypad)
867{
868 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
869
870 return 0;
871}
872
873/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800874static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800875 const u_int8_t *lv)
876{
877 u_int8_t in_len = lv[0];
878
879 if (in_len < 2)
880 return -EINVAL;
881
Harald Welte4bfdfe72009-06-10 23:11:52 +0800882 progress->coding = (lv[1] & 0x60) >> 5;
883 progress->location = lv[1] & 0x0f;
884 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800885
886 return 0;
887}
888
889/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800890static int encode_progress(struct msgb *msg, int lv_only,
891 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800892{
893 u_int8_t lv[3];
894
895 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800896 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
897 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800898 if (lv_only)
899 msgb_lv_put(msg, lv[0], lv+1);
900 else
901 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
902
903 return 0;
904}
905
906/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800907static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800908 const u_int8_t *lv)
909{
910 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800911 char *info = uu->info;
912 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800913 int i;
914
915 if (in_len < 1)
916 return -EINVAL;
917
Harald Welte4bfdfe72009-06-10 23:11:52 +0800918 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800919
920 for (i = 2; i <= in_len; i++) {
921 info_len--;
922 if (info_len <= 1)
923 break;
924 *info++ = lv[i];
925 }
926 if (info_len >= 1)
927 *info++ = '\0';
928
929 return 0;
930}
931
932/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800933static int encode_useruser(struct msgb *msg, int lv_only,
934 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800935{
936 u_int8_t lv[GSM_MAX_USERUSER + 2];
937
Harald Welte4bfdfe72009-06-10 23:11:52 +0800938 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800939 return -EINVAL;
940
Harald Welte4bfdfe72009-06-10 23:11:52 +0800941 lv[0] = 1 + strlen(uu->info);
942 lv[1] = uu->proto;
943 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800944 if (lv_only)
945 msgb_lv_put(msg, lv[0], lv+1);
946 else
947 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
948
949 return 0;
950}
951
952/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800953static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800954 const u_int8_t *lv)
955{
956 u_int8_t in_len = lv[0];
957
Harald Welte4bfdfe72009-06-10 23:11:52 +0800958 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800959 return -EINVAL;
960
Harald Welte4bfdfe72009-06-10 23:11:52 +0800961 memcpy(ssv->info, lv + 1, in_len);
962 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800963
964 return 0;
965}
966
967/* encode 'more data' */
968static int encode_more(struct msgb *msg)
969{
970 u_int8_t *ie;
971
972 ie = msgb_put(msg, 1);
973 ie[0] = GSM48_IE_MORE_DATA;
974
975 return 0;
976}
977
Holger Freyther819dd202009-01-04 03:52:50 +0000978struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000979{
Harald Welte966636f2009-06-26 19:39:35 +0200980 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
981 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000982}
983
Holger Freyther3e2c3232009-01-04 03:55:31 +0000984int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000985{
Harald Welte65e74cc2008-12-29 01:55:35 +0000986 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800987 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000988 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000989
Harald Welte4bfdfe72009-06-10 23:11:52 +0800990 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
991 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
992 "Sending '%s' to MS.\n", msg->trx->bts->nr,
993 msg->trx->nr, msg->lchan->ts->nr,
994 gh->proto_discr & 0xf0,
995 cc_msg_names[gh->msg_type & 0x3f]);
996 else
997 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
998 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
999 msg->trx->nr, msg->lchan->ts->nr,
1000 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001001 }
1002
Harald Welte4b634542008-12-27 01:55:51 +00001003 msg->l3h = msg->data;
1004
Harald Welte8470bf22008-12-25 23:28:35 +00001005 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001006}
1007
Holger Freyther429e7762008-12-30 13:28:30 +00001008/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001009int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001010{
Harald Welte8470bf22008-12-25 23:28:35 +00001011 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001012 struct gsm48_hdr *gh;
1013
Harald Welte8470bf22008-12-25 23:28:35 +00001014 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001015
1016 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1017 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001018 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001019 gh->data[0] = cause;
1020
Harald Weltedb253af2008-12-30 17:56:55 +00001021 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1022
Harald Welte65e74cc2008-12-29 01:55:35 +00001023 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001024}
1025
1026/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001027int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001028{
Harald Welte8470bf22008-12-25 23:28:35 +00001029 struct gsm_bts *bts = lchan->ts->trx->bts;
1030 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001031 struct gsm48_hdr *gh;
1032 struct gsm48_loc_area_id *lai;
1033 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001034 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001035
Harald Welte8470bf22008-12-25 23:28:35 +00001036 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001037
1038 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1039 gh->proto_discr = GSM48_PDISC_MM;
1040 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1041
1042 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001043 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001044 bts->network->network_code, bts->location_area_code);
1045
1046 mid = msgb_put(msg, MID_TMSI_LEN);
1047 generate_mid_from_tmsi(mid, tmsi);
1048
1049 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1050
Harald Weltedb253af2008-12-30 17:56:55 +00001051 ret = gsm48_sendmsg(msg);
1052
Harald Weltedb253af2008-12-30 17:56:55 +00001053 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001054
Holger Freyther07cc8d82008-12-29 06:23:46 +00001055 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001056}
1057
Harald Weltefc977a82008-12-27 10:19:37 +00001058static char bcd2char(u_int8_t bcd)
1059{
1060 if (bcd < 0xa)
1061 return '0' + bcd;
1062 else
1063 return 'A' + (bcd - 0xa);
1064}
1065
Harald Weltebf5e8df2009-02-03 12:59:45 +00001066/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001067static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1068{
1069 int i;
1070 u_int8_t mi_type;
1071 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001072 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001073
1074 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1075
1076 switch (mi_type) {
1077 case GSM_MI_TYPE_NONE:
1078 break;
1079 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001080 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1081 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1082 memcpy(&tmsi, &mi[1], 4);
1083 tmsi = ntohl(tmsi);
1084 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001085 }
1086 break;
1087 case GSM_MI_TYPE_IMSI:
1088 case GSM_MI_TYPE_IMEI:
1089 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001090 *str_cur++ = bcd2char(mi[0] >> 4);
1091
1092 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001093 if (str_cur + 2 >= string + str_len)
1094 return str_cur - string;
1095 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001096 /* skip last nibble in last input byte when GSM_EVEN */
1097 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1098 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001099 }
1100 break;
1101 default:
1102 break;
1103 }
Harald Weltefc977a82008-12-27 10:19:37 +00001104 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001105
Harald Weltefc977a82008-12-27 10:19:37 +00001106 return str_cur - string;
1107}
1108
Harald Weltebf5e8df2009-02-03 12:59:45 +00001109/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001110static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1111{
1112 struct msgb *msg = gsm48_msgb_alloc();
1113 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001114
Harald Welte231ad4f2008-12-27 11:15:38 +00001115 msg->lchan = lchan;
1116
1117 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1118 gh->proto_discr = GSM48_PDISC_MM;
1119 gh->msg_type = GSM48_MT_MM_ID_REQ;
1120 gh->data[0] = id_type;
1121
Harald Welte65e74cc2008-12-29 01:55:35 +00001122 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001123}
1124
1125#define MI_SIZE 32
1126
Harald Weltebf5e8df2009-02-03 12:59:45 +00001127/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001128static int mm_rx_id_resp(struct msgb *msg)
1129{
1130 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001131 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001132 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1133 char mi_string[MI_SIZE];
1134
1135 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001136 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001137 mi_type, mi_string);
1138
Harald Welte75a983f2008-12-27 21:34:06 +00001139 switch (mi_type) {
1140 case GSM_MI_TYPE_IMSI:
1141 if (!lchan->subscr)
1142 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001143 if (lchan->loc_operation)
1144 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001145 break;
1146 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001147 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001148 /* update subscribe <-> IMEI mapping */
1149 if (lchan->subscr)
1150 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001151 if (lchan->loc_operation)
1152 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001153 break;
1154 }
Holger Freyther73487a22008-12-31 18:53:57 +00001155
1156 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001157 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001158}
1159
Harald Welte255539c2008-12-28 02:26:27 +00001160
1161static void loc_upd_rej_cb(void *data)
1162{
1163 struct gsm_lchan *lchan = data;
1164
Holger Freyther73487a22008-12-31 18:53:57 +00001165 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001166 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001167 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001168}
1169
Holger Freytherb7193e42008-12-29 17:44:08 +00001170static void schedule_reject(struct gsm_lchan *lchan)
1171{
Holger Freyther73487a22008-12-31 18:53:57 +00001172 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1173 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001174 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001175}
1176
Harald Welte2a139372009-02-22 21:14:55 +00001177static const char *lupd_name(u_int8_t type)
1178{
1179 switch (type) {
1180 case GSM48_LUPD_NORMAL:
1181 return "NORMAL";
1182 case GSM48_LUPD_PERIODIC:
1183 return "PEROIDOC";
1184 case GSM48_LUPD_IMSI_ATT:
1185 return "IMSI ATTACH";
1186 default:
1187 return "UNKNOWN";
1188 }
1189}
1190
Harald Welte231ad4f2008-12-27 11:15:38 +00001191#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001192/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001193static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001194{
Harald Welte8470bf22008-12-25 23:28:35 +00001195 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001196 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001197 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001198 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001199 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001200 char mi_string[MI_SIZE];
1201 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001202
Harald Welte8470bf22008-12-25 23:28:35 +00001203 lu = (struct gsm48_loc_upd_req *) gh->data;
1204
1205 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001206
Harald Weltefc977a82008-12-27 10:19:37 +00001207 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1208
Holger Freyther79f4ae62009-06-02 03:25:04 +00001209 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001210 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001211
Holger Freythereaf04692009-06-06 13:54:44 +00001212 /*
1213 * Pseudo Spoof detection: Just drop a second/concurrent
1214 * location updating request.
1215 */
1216 if (lchan->loc_operation) {
1217 DEBUGP(DMM, "LUPDREQ: ignoring request due an existing one: %p.\n",
1218 lchan->loc_operation);
1219 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1220 return 0;
1221 }
1222
Holger Freyther73487a22008-12-31 18:53:57 +00001223 allocate_loc_updating_req(lchan);
1224
Harald Welte52b1f982008-12-23 20:25:15 +00001225 switch (mi_type) {
1226 case GSM_MI_TYPE_IMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001227 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001228 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001229 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001230 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001231
Harald Welte52b1f982008-12-23 20:25:15 +00001232 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001233 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001234 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001235 case GSM_MI_TYPE_TMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001236 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001237 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001238 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001239 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001240
Harald Welte52b1f982008-12-23 20:25:15 +00001241 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001242 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001243 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001244 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001245 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001246 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001247 }
1248 break;
1249 case GSM_MI_TYPE_IMEI:
1250 case GSM_MI_TYPE_IMEISV:
1251 /* no sim card... FIXME: what to do ? */
Harald Welte2a139372009-02-22 21:14:55 +00001252 DEBUGP(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001253 break;
1254 default:
Harald Welte2a139372009-02-22 21:14:55 +00001255 DEBUGP(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001256 break;
1257 }
1258
Harald Welte4bfdfe72009-06-10 23:11:52 +08001259 if (!subscr) {
1260 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1261 /* FIXME: request id? close channel? */
1262 return -EINVAL;
1263 }
1264
Harald Welte255539c2008-12-28 02:26:27 +00001265 lchan->subscr = subscr;
1266
Holger Freyther73487a22008-12-31 18:53:57 +00001267 /*
1268 * Schedule the reject timer and check if we can let the
1269 * subscriber into our network immediately or if we need to wait
1270 * for identity responses.
1271 */
1272 schedule_reject(lchan);
Holger Freytherd51524f2009-06-09 08:27:07 +00001273 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001274}
1275
Harald Welte7584aea2009-02-11 11:44:12 +00001276/* 9.1.5 Channel mode modify */
1277int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1278{
1279 struct msgb *msg = gsm48_msgb_alloc();
1280 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1281 struct gsm48_chan_mode_modify *cmm =
1282 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001283 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001284
Harald Welte4a543e82009-02-28 13:17:55 +00001285 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001286
Harald Welte45b407a2009-05-23 15:51:12 +00001287 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001288 msg->lchan = lchan;
1289 gh->proto_discr = GSM48_PDISC_RR;
1290 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1291
1292 /* fill the channel information element, this code
1293 * should probably be shared with rsl_rx_chan_rqd() */
1294 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001295 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001296 cmm->chan_desc.h0.h = 0;
1297 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1298 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1299 cmm->mode = mode;
1300
1301 return gsm48_sendmsg(msg);
1302}
1303
Harald Welte4bfdfe72009-06-10 23:11:52 +08001304#if 0
1305static u_int8_t to_bcd8(u_int8_t val)
1306{
1307 return ((val / 10) << 4) | (val % 10);
1308}
1309#endif
1310
Harald Weltedb253af2008-12-30 17:56:55 +00001311/* Section 9.2.15a */
1312int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1313{
1314 struct msgb *msg = gsm48_msgb_alloc();
1315 struct gsm48_hdr *gh;
1316 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001317 u_int8_t *ptr8;
1318 u_int16_t *ptr16;
1319 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001320 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001321#if 0
1322 time_t cur_t;
1323 struct tm* cur_time;
1324 int tz15min;
1325#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001326
1327 msg->lchan = lchan;
1328
1329 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1330 gh->proto_discr = GSM48_PDISC_MM;
1331 gh->msg_type = GSM48_MT_MM_INFO;
1332
1333 if (net->name_long) {
1334 name_len = strlen(net->name_long);
1335 /* 10.5.3.5a */
1336 ptr8 = msgb_put(msg, 3);
1337 ptr8[0] = GSM48_IE_NAME_LONG;
1338 ptr8[1] = name_len*2 +1;
1339 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1340
1341 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1342 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001343 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001344
1345 /* FIXME: Use Cell Broadcast, not UCS-2, since
1346 * UCS-2 is only supported by later revisions of the spec */
1347 }
1348
1349 if (net->name_short) {
1350 name_len = strlen(net->name_short);
1351 /* 10.5.3.5a */
1352 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1353 ptr8[0] = GSM48_IE_NAME_LONG;
1354 ptr8[1] = name_len*2 + 1;
1355 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1356
Harald Weltee872cb12009-01-01 00:33:37 +00001357 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001358 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001359 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001360 }
1361
1362#if 0
1363 /* Section 10.5.3.9 */
1364 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001365 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001366 ptr8 = msgb_put(msg, 8);
1367 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1368 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1369 ptr8[2] = to_bcd8(cur_time->tm_mon);
1370 ptr8[3] = to_bcd8(cur_time->tm_mday);
1371 ptr8[4] = to_bcd8(cur_time->tm_hour);
1372 ptr8[5] = to_bcd8(cur_time->tm_min);
1373 ptr8[6] = to_bcd8(cur_time->tm_sec);
1374 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1375 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001376 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001377 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001378 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001379#endif
1380
1381 return gsm48_sendmsg(msg);
1382}
1383
Harald Welte4b634542008-12-27 01:55:51 +00001384static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1385{
Harald Welte4b634542008-12-27 01:55:51 +00001386 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001387 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001388}
Harald Welteba4cf162009-01-10 01:49:35 +00001389
1390/* 9.2.6 CM service reject */
1391static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1392 enum gsm48_reject_value value)
1393{
1394 struct msgb *msg = gsm48_msgb_alloc();
1395 struct gsm48_hdr *gh;
1396
1397 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1398
1399 msg->lchan = lchan;
1400 use_lchan(lchan);
1401
1402 gh->proto_discr = GSM48_PDISC_MM;
1403 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1404 gh->data[0] = value;
1405 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1406
1407 return gsm48_sendmsg(msg);
1408}
1409
Harald Welte4ed0e922009-01-10 03:17:30 +00001410
1411/*
1412 * Handle CM Service Requests
1413 * a) Verify that the packet is long enough to contain the information
1414 * we require otherwsie reject with INCORRECT_MESSAGE
1415 * b) Try to parse the TMSI. If we do not have one reject
1416 * c) Check that we know the subscriber with the TMSI otherwise reject
1417 * with a HLR cause
1418 * d) Set the subscriber on the gsm_lchan and accept
1419 */
Harald Welte4b634542008-12-27 01:55:51 +00001420static int gsm48_rx_mm_serv_req(struct msgb *msg)
1421{
Harald Welteba4cf162009-01-10 01:49:35 +00001422 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001423 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001424
Harald Welteba4cf162009-01-10 01:49:35 +00001425 struct gsm_subscriber *subscr;
1426 struct gsm48_hdr *gh = msgb_l3(msg);
1427 struct gsm48_service_request *req =
1428 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001429 /* unfortunately in Phase1 the classmar2 length is variable */
1430 u_int8_t classmark2_len = gh->data[1];
1431 u_int8_t *classmark2 = gh->data+2;
1432 u_int8_t mi_len = *(classmark2 + classmark2_len);
1433 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001434
Harald Weltec9e02182009-05-01 19:07:53 +00001435 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001436 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001437 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001438 return gsm48_tx_mm_serv_rej(msg->lchan,
1439 GSM48_REJECT_INCORRECT_MESSAGE);
1440 }
1441
1442 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001443 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001444 return gsm48_tx_mm_serv_rej(msg->lchan,
1445 GSM48_REJECT_INCORRECT_MESSAGE);
1446 }
1447
Harald Weltec9e02182009-05-01 19:07:53 +00001448 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001449 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001450 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001451 return gsm48_tx_mm_serv_rej(msg->lchan,
1452 GSM48_REJECT_INCORRECT_MESSAGE);
1453 }
1454
Harald Weltec9e02182009-05-01 19:07:53 +00001455 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001456 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001457 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001458
Holger Freythereb443982009-06-04 13:58:42 +00001459 subscr = subscr_get_by_tmsi(mi_string);
1460
Harald Welte2a139372009-02-22 21:14:55 +00001461 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001462 if (!subscr)
1463 return gsm48_tx_mm_serv_rej(msg->lchan,
1464 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1465
1466 if (!msg->lchan->subscr)
1467 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001468 else if (msg->lchan->subscr != subscr) {
1469 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1470 subscr_put(subscr);
1471 }
1472
Harald Weltef7c43522009-06-09 20:24:21 +00001473 subscr->classmark2_len = classmark2_len;
1474 memcpy(subscr->classmark2, classmark2, classmark2_len);
1475
Harald Welte4b634542008-12-27 01:55:51 +00001476 return gsm48_tx_mm_serv_ack(msg->lchan);
1477}
1478
Harald Welte2a139372009-02-22 21:14:55 +00001479static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1480{
1481 struct gsm48_hdr *gh = msgb_l3(msg);
1482 struct gsm48_imsi_detach_ind *idi =
1483 (struct gsm48_imsi_detach_ind *) gh->data;
1484 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1485 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001486 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001487
1488 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1489 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1490 mi_type, mi_string);
1491
1492 switch (mi_type) {
1493 case GSM_MI_TYPE_TMSI:
1494 subscr = subscr_get_by_tmsi(mi_string);
1495 break;
1496 case GSM_MI_TYPE_IMSI:
1497 subscr = subscr_get_by_imsi(mi_string);
1498 break;
1499 case GSM_MI_TYPE_IMEI:
1500 case GSM_MI_TYPE_IMEISV:
1501 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001502 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001503 break;
1504 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001505 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001506 break;
1507 }
1508
Holger Freyther4a49e772009-04-12 05:37:29 +00001509 if (subscr) {
1510 subscr_update(subscr, msg->trx->bts,
1511 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001512 DEBUGP(DMM, "Subscriber: %s\n",
1513 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001514 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001515 } else
Harald Welte2a139372009-02-22 21:14:55 +00001516 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1517
Harald Welte2a139372009-02-22 21:14:55 +00001518 return 0;
1519}
1520
Harald Welted2a7f5a2009-06-05 20:08:20 +00001521static int gsm48_rx_mm_status(struct msgb *msg)
1522{
1523 struct gsm48_hdr *gh = msgb_l3(msg);
1524
1525 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1526
1527 return 0;
1528}
1529
Harald Weltebf5e8df2009-02-03 12:59:45 +00001530/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001531static int gsm0408_rcv_mm(struct msgb *msg)
1532{
1533 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001534 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001535
1536 switch (gh->msg_type & 0xbf) {
1537 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +00001538 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001539 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001540 break;
1541 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001542 rc = mm_rx_id_resp(msg);
1543 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001544 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001545 rc = gsm48_rx_mm_serv_req(msg);
1546 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001547 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001548 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001549 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001550 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001551 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1552 msg->lchan->subscr ?
1553 msg->lchan->subscr->imsi :
1554 "unknown subscriber");
1555 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001556 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001557 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1558 break;
1559 case GSM48_MT_MM_CM_REEST_REQ:
1560 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1561 break;
1562 case GSM48_MT_MM_AUTH_RESP:
1563 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001564 break;
1565 default:
1566 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1567 gh->msg_type);
1568 break;
1569 }
1570
1571 return rc;
1572}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001573
Harald Welte2d35ae62009-02-06 12:02:13 +00001574/* Receive a PAGING RESPONSE message from the MS */
1575static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1576{
1577 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001578 u_int8_t *classmark2_lv = gh->data + 1;
1579 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1580 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001581 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001582 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001583 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001584 int rc = 0;
1585
Harald Welte61548982009-02-22 21:26:29 +00001586 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001587 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1588 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001589 switch (mi_type) {
1590 case GSM_MI_TYPE_TMSI:
1591 subscr = subscr_get_by_tmsi(mi_string);
1592 break;
1593 case GSM_MI_TYPE_IMSI:
1594 subscr = subscr_get_by_imsi(mi_string);
1595 break;
1596 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001597
1598 if (!subscr) {
1599 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001600 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001601 return -EINVAL;
1602 }
1603 DEBUGP(DRR, "<- Channel was requested by %s\n",
1604 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001605
Harald Weltef7c43522009-06-09 20:24:21 +00001606 subscr->classmark2_len = *classmark2_lv;
1607 memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv);
1608
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001609 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001610 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001611 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001612 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1613 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001614 return -EINVAL;
1615 } else {
1616 DEBUGP(DRR, "<- Channel already owned by us\n");
1617 subscr_put(subscr);
1618 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001619 }
1620
Harald Welte595ad7b2009-02-16 22:05:44 +00001621 sig_data.subscr = subscr;
1622 sig_data.bts = msg->lchan->ts->trx->bts;
1623 sig_data.lchan = msg->lchan;
1624
1625 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001626
1627 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001628 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001629
Harald Welte7584aea2009-02-11 11:44:12 +00001630 /* FIXME: somehow signal the completion of the PAGING to
1631 * the entity that requested the paging */
1632
Harald Welte2d35ae62009-02-06 12:02:13 +00001633 return rc;
1634}
1635
Harald Weltef7c43522009-06-09 20:24:21 +00001636static int gsm48_rx_rr_classmark(struct msgb *msg)
1637{
1638 struct gsm48_hdr *gh = msgb_l3(msg);
1639 struct gsm_subscriber *subscr = msg->lchan->subscr;
1640 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1641 u_int8_t cm2_len, cm3_len = 0;
1642 u_int8_t *cm2, *cm3 = NULL;
1643
1644 DEBUGP(DRR, "CLASSMARK CHANGE ");
1645
1646 /* classmark 2 */
1647 cm2_len = gh->data[0];
1648 cm2 = &gh->data[1];
1649 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1650
1651 if (payload_len > cm2_len + 1) {
1652 /* we must have a classmark3 */
1653 if (gh->data[cm2_len+1] != 0x20) {
1654 DEBUGPC(DRR, "ERR CM3 TAG\n");
1655 return -EINVAL;
1656 }
1657 if (cm2_len > 3) {
1658 DEBUGPC(DRR, "CM2 too long!\n");
1659 return -EINVAL;
1660 }
1661
1662 cm3_len = gh->data[cm2_len+2];
1663 cm3 = &gh->data[cm2_len+3];
1664 if (cm3_len > 14) {
1665 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1666 return -EINVAL;
1667 }
1668 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1669 }
1670 if (subscr) {
1671 subscr->classmark2_len = cm2_len;
1672 memcpy(subscr->classmark2, cm2, cm2_len);
1673 if (cm3) {
1674 subscr->classmark3_len = cm3_len;
1675 memcpy(subscr->classmark3, cm3, cm3_len);
1676 }
1677 }
1678
1679 /* FIXME: store the classmark2/3 values with the equipment register */
1680
1681 return 0;
1682}
1683
Harald Weltecf5b3592009-05-01 18:28:42 +00001684static int gsm48_rx_rr_status(struct msgb *msg)
1685{
1686 struct gsm48_hdr *gh = msgb_l3(msg);
1687
1688 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1689 rr_cause_name(gh->data[0]));
1690
1691 return 0;
1692}
1693
Harald Weltef7c43522009-06-09 20:24:21 +00001694static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1695{
1696 struct gsm48_hdr *gh = msgb_l3(msg);
1697 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1698 static struct gsm_meas_rep meas_rep;
1699
Harald Welte10d0e672009-06-27 02:53:10 +02001700 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001701 parse_meas_rep(&meas_rep, gh->data, payload_len);
1702 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001703 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001704 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001705 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001706 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001707 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001708 else
Harald Welte10d0e672009-06-27 02:53:10 +02001709 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001710 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1711 meas_rep.rxqual_sub);
1712
Harald Welte10d0e672009-06-27 02:53:10 +02001713 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001714
1715 /* FIXME: put the results somwhere */
1716
1717 return 0;
1718}
1719
Harald Weltebf5e8df2009-02-03 12:59:45 +00001720/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001721static int gsm0408_rcv_rr(struct msgb *msg)
1722{
1723 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001724 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001725
1726 switch (gh->msg_type) {
1727 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001728 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001729 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001730 case GSM48_MT_RR_GPRS_SUSP_REQ:
1731 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1732 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001733 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001734 rc = gsm48_rr_rx_pag_resp(msg);
1735 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001736 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1737 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001738 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001739 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001740 case GSM48_MT_RR_STATUS:
1741 rc = gsm48_rx_rr_status(msg);
1742 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001743 case GSM48_MT_RR_MEAS_REP:
1744 rc = gsm48_rx_rr_meas_rep(msg);
1745 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001746 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001747 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001748 gh->msg_type);
1749 break;
1750 }
1751
Harald Welte2d35ae62009-02-06 12:02:13 +00001752 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001753}
1754
Holger Freythere64a7a32009-02-06 21:55:37 +00001755/* 7.1.7 and 9.1.7 Channel release*/
1756int gsm48_send_rr_release(struct gsm_lchan *lchan)
1757{
1758 struct msgb *msg = gsm48_msgb_alloc();
1759 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1760 u_int8_t *cause;
1761
1762 msg->lchan = lchan;
1763 gh->proto_discr = GSM48_PDISC_RR;
1764 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1765
1766 cause = msgb_put(msg, 1);
1767 cause[0] = GSM48_RR_CAUSE_NORMAL;
1768
1769 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1770 lchan->nr, lchan->type);
1771
1772 return gsm48_sendmsg(msg);
1773}
1774
Harald Welte4bc90a12008-12-27 16:32:52 +00001775/* Call Control */
1776
Harald Welte7584aea2009-02-11 11:44:12 +00001777/* The entire call control code is written in accordance with Figure 7.10c
1778 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1779 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1780 * it for voice */
1781
Harald Welte4bfdfe72009-06-10 23:11:52 +08001782static void new_cc_state(struct gsm_trans *trans, int state)
1783{
1784 if (state > 31 || state < 0)
1785 return;
1786
1787 DEBUGP(DCC, "new state %s -> %s\n",
1788 cc_state_names[trans->state], cc_state_names[state]);
1789
1790 trans->state = state;
1791}
1792
1793static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001794{
1795 struct msgb *msg = gsm48_msgb_alloc();
1796 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1797 u_int8_t *cause, *call_state;
1798
Harald Welte4bfdfe72009-06-10 23:11:52 +08001799 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1800 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001801 gh->msg_type = GSM48_MT_CC_STATUS;
1802
1803 cause = msgb_put(msg, 3);
1804 cause[0] = 2;
1805 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1806 cause[2] = 0x80 | 30; /* response to status inquiry */
1807
1808 call_state = msgb_put(msg, 1);
1809 call_state[0] = 0xc0 | 0x00;
1810
Harald Welte65e74cc2008-12-29 01:55:35 +00001811 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001812}
1813
Harald Welte6f4b7532008-12-29 00:39:37 +00001814static int gsm48_tx_simple(struct gsm_lchan *lchan,
1815 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001816{
1817 struct msgb *msg = gsm48_msgb_alloc();
1818 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1819
1820 msg->lchan = lchan;
1821
Harald Welte6f4b7532008-12-29 00:39:37 +00001822 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001823 gh->msg_type = msg_type;
1824
Harald Welte65e74cc2008-12-29 01:55:35 +00001825 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001826}
1827
Harald Welte4bfdfe72009-06-10 23:11:52 +08001828static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1829{
1830 if (bsc_timer_pending(&trans->cc_timer)) {
1831 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1832 bsc_del_timer(&trans->cc_timer);
1833 trans->Tcurrent = 0;
1834 }
1835}
1836
1837static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1838 int msg_type, struct gsm_mncc *mncc)
1839{
1840 struct msgb *msg;
1841
1842 if (trans)
1843 if (trans->lchan)
1844 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1845 "Sending '%s' to MNCC.\n",
1846 trans->lchan->ts->trx->bts->nr,
1847 trans->lchan->ts->trx->nr,
1848 trans->lchan->ts->nr, trans->transaction_id,
1849 (trans->subscr)?(trans->subscr->extension):"-",
1850 get_mncc_name(msg_type));
1851 else
1852 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1853 "Sending '%s' to MNCC.\n",
1854 (trans->subscr)?(trans->subscr->extension):"-",
1855 get_mncc_name(msg_type));
1856 else
1857 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1858 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1859
1860 mncc->msg_type = msg_type;
1861
Harald Welte966636f2009-06-26 19:39:35 +02001862 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001863 if (!msg)
1864 return -ENOMEM;
1865 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1866 msgb_enqueue(&net->upqueue, msg);
1867
1868 return 0;
1869}
1870
1871int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1872 u_int32_t callref, int location, int value)
1873{
1874 struct gsm_mncc rel;
1875
Harald Welte92f70c52009-06-12 01:54:08 +08001876 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001877 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001878 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001879 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1880}
1881
1882void free_trans(struct gsm_trans *trans)
1883{
1884 struct gsm_bts *bts;
1885
1886 gsm48_stop_cc_timer(trans);
1887
1888 /* send release to L4, if callref still exists */
1889 if (trans->callref) {
1890 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001891 mncc_release_ind(trans->network, trans, trans->callref,
1892 GSM48_CAUSE_LOC_PRN_S_LU,
1893 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001894 if (trans->state != GSM_CSTATE_NULL)
1895 new_cc_state(trans, GSM_CSTATE_NULL);
1896 }
1897
1898 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1899 /* Stop paging on all bts' */
1900 bts = NULL;
1901 do {
1902 bts = gsm_bts_by_lac(trans->subscr->net,
1903 trans->subscr->lac, bts);
1904 if (!bts)
1905 break;
1906 /* Stop paging */
1907 paging_request_stop(bts, trans->subscr, NULL);
1908 } while (1);
1909 }
1910
1911 if (trans->lchan) {
1912 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1913 put_lchan(trans->lchan);
1914 }
1915
1916 if (trans->subscr)
1917 subscr_put(trans->subscr);
1918
1919 if (trans->state != GSM_CSTATE_NULL)
1920 new_cc_state(trans, GSM_CSTATE_NULL);
1921
1922 llist_del(&trans->entry);
1923
Harald Welte2cf161b2009-06-20 22:36:41 +02001924 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001925}
1926
1927static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1928
Harald Welte09e38af2009-02-16 22:52:23 +00001929/* call-back from paging the B-end of the connection */
1930static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001931 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001932{
Harald Welte7ccf7782009-02-17 01:43:01 +00001933 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001934 struct gsm_subscriber *subscr = param;
1935 struct gsm_trans *transt, *tmp;
1936 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001937
Harald Welte09e38af2009-02-16 22:52:23 +00001938 if (hooknum != GSM_HOOK_RR_PAGING)
1939 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001940
1941 if (!subscr)
1942 return -EINVAL;
1943 net = subscr->net;
1944 if (!net) {
1945 DEBUGP(DCC, "Error Network not set!\n");
1946 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001947 }
Harald Welte7584aea2009-02-11 11:44:12 +00001948
Harald Welte4bfdfe72009-06-10 23:11:52 +08001949 /* check all tranactions (without lchan) for subscriber */
1950 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1951 if (transt->subscr != subscr || transt->lchan)
1952 continue;
1953 switch (event) {
1954 case GSM_PAGING_SUCCEEDED:
1955 if (!lchan) // paranoid
1956 break;
1957 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1958 subscr->extension);
1959 /* Assign lchan */
1960 if (!transt->lchan) {
1961 transt->lchan = lchan;
1962 use_lchan(lchan);
1963 }
1964 /* send SETUP request to called party */
1965 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1966 if (is_ipaccess_bts(lchan->ts->trx->bts))
1967 rsl_ipacc_bind(lchan);
1968 break;
1969 case GSM_PAGING_EXPIRED:
1970 DEBUGP(DCC, "Paging subscr %s expired!\n",
1971 subscr->extension);
1972 /* Temporarily out of order */
1973 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001974 GSM48_CAUSE_LOC_PRN_S_LU,
1975 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001976 transt->callref = 0;
1977 free_trans(transt);
1978 break;
1979 }
1980 }
Harald Welte09e38af2009-02-16 22:52:23 +00001981 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001982}
Harald Welte7584aea2009-02-11 11:44:12 +00001983
Harald Welte49f48b82009-02-17 15:29:33 +00001984/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001985static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001986{
Harald Welte11fa29c2009-02-19 17:24:39 +00001987 struct gsm_bts *bts = lchan->ts->trx->bts;
1988 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001989 struct gsm_bts_trx_ts *ts;
1990
Harald Welte11fa29c2009-02-19 17:24:39 +00001991 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1992 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1993 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1994
1995 if (bts->type != remote_bts->type) {
1996 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1997 return -EINVAL;
1998 }
Harald Welte49f48b82009-02-17 15:29:33 +00001999
Harald Welte11fa29c2009-02-19 17:24:39 +00002000 switch (bts->type) {
2001 case GSM_BTS_TYPE_NANOBTS_900:
2002 case GSM_BTS_TYPE_NANOBTS_1800:
2003 ts = remote_lchan->ts;
2004 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2005 lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2006
2007 ts = lchan->ts;
2008 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2009 remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2010 break;
2011 case GSM_BTS_TYPE_BS11:
2012 trau_mux_map_lchan(lchan, remote_lchan);
2013 break;
2014 default:
2015 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2016 break;
2017 }
Harald Welte49f48b82009-02-17 15:29:33 +00002018
2019 return 0;
2020}
2021
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002023{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002024 struct gsm_trans *trans;
2025 llist_for_each_entry(trans, &net->trans_list, entry) {
2026 if (trans->callref == callref)
2027 return trans;
2028 }
2029 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002030}
2031
Harald Welte4bfdfe72009-06-10 23:11:52 +08002032/* bridge channels of two transactions */
2033static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002034{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002035 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2036 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002037
Harald Welte4bfdfe72009-06-10 23:11:52 +08002038 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002039 return -EIO;
2040
Harald Welte4bfdfe72009-06-10 23:11:52 +08002041 if (!trans1->lchan || !trans2->lchan)
2042 return -EIO;
2043
2044 /* through-connect channel */
2045 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002046}
2047
Harald Welte4bfdfe72009-06-10 23:11:52 +08002048/* enable receive of channels to upqueue */
2049static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2050{
2051 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002052
Harald Welte4bfdfe72009-06-10 23:11:52 +08002053 /* Find callref */
2054 trans = get_trans_ref(net, data->callref);
2055 if (!trans)
2056 return -EIO;
2057 if (!trans->lchan)
2058 return 0;
2059
2060 // todo IPACCESS
2061 if (enable)
2062 return trau_recv_lchan(trans->lchan, data->callref);
2063 return trau_mux_unmap(NULL, data->callref);
2064}
2065
2066/* send a frame to channel */
2067static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2068{
2069 struct gsm_trans *trans;
2070
2071 /* Find callref */
2072 trans = get_trans_ref(net, frame->callref);
2073 if (!trans)
2074 return -EIO;
2075 if (!trans->lchan)
2076 return 0;
2077 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2078 trans->lchan->type != GSM_LCHAN_TCH_H)
2079 return 0;
2080
2081 // todo IPACCESS
2082 return trau_send_lchan(trans->lchan,
2083 (struct decoded_trau_frame *)frame->data);
2084}
2085
2086
2087static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2088{
2089 DEBUGP(DCC, "-> STATUS ENQ\n");
2090 return gsm48_cc_tx_status(trans, msg);
2091}
2092
2093static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2094static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2095
2096static void gsm48_cc_timeout(void *arg)
2097{
2098 struct gsm_trans *trans = arg;
2099 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002100 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2101 int mo_location = GSM48_CAUSE_LOC_USER;
2102 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2103 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002104 struct gsm_mncc mo_rel, l4_rel;
2105
2106 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2107 mo_rel.callref = trans->callref;
2108 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2109 l4_rel.callref = trans->callref;
2110
2111 switch(trans->Tcurrent) {
2112 case 0x303:
2113 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002114 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002115 break;
2116 case 0x310:
2117 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002118 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002119 break;
2120 case 0x313:
2121 disconnect = 1;
2122 /* unknown, did not find it in the specs */
2123 break;
2124 case 0x301:
2125 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002126 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002127 break;
2128 case 0x308:
2129 if (!trans->T308_second) {
2130 /* restart T308 a second time */
2131 gsm48_cc_tx_release(trans, &trans->cc_msg);
2132 trans->T308_second = 1;
2133 break; /* stay in release state */
2134 }
2135 free_trans(trans);
2136 return;
2137// release = 1;
2138// l4_cause = 14;
2139// break;
2140 case 0x306:
2141 release = 1;
2142 mo_cause = trans->cc_msg.cause.value;
2143 mo_location = trans->cc_msg.cause.location;
2144 break;
2145 case 0x323:
2146 disconnect = 1;
2147 break;
2148 default:
2149 release = 1;
2150 }
2151
2152 if (release && trans->callref) {
2153 /* process release towards layer 4 */
2154 mncc_release_ind(trans->network, trans, trans->callref,
2155 l4_location, l4_cause);
2156 trans->callref = 0;
2157 }
2158
2159 if (disconnect && trans->callref) {
2160 /* process disconnect towards layer 4 */
2161 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2162 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2163 }
2164
2165 /* process disconnect towards mobile station */
2166 if (disconnect || release) {
2167 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2168 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2169 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2170 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2171 mo_rel.cause.diag_len = 3;
2172
2173 if (disconnect)
2174 gsm48_cc_tx_disconnect(trans, &mo_rel);
2175 if (release)
2176 gsm48_cc_tx_release(trans, &mo_rel);
2177 }
2178
2179}
2180
2181static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2182 int sec, int micro)
2183{
2184 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2185 trans->cc_timer.cb = gsm48_cc_timeout;
2186 trans->cc_timer.data = trans;
2187 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2188 trans->Tcurrent = current;
2189}
2190
2191static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2192{
2193 struct gsm48_hdr *gh = msgb_l3(msg);
2194 u_int8_t msg_type = gh->msg_type & 0xbf;
2195 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2196 struct tlv_parsed tp;
2197 struct gsm_mncc setup;
2198
2199 memset(&setup, 0, sizeof(struct gsm_mncc));
2200 setup.callref = trans->callref;
2201 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2202 /* emergency setup is identified by msg_type */
2203 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2204 setup.emergency = 1;
2205
2206 /* use subscriber as calling party number */
2207 if (trans->subscr) {
2208 setup.fields |= MNCC_F_CALLING;
2209 strncpy(setup.calling.number, trans->subscr->extension,
2210 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002211 strncpy(setup.imsi, trans->subscr->imsi,
2212 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002213 }
2214 /* bearer capability */
2215 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2216 setup.fields |= MNCC_F_BEARER_CAP;
2217 decode_bearer_cap(&setup.bearer_cap,
2218 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2219 }
2220 /* facility */
2221 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2222 setup.fields |= MNCC_F_FACILITY;
2223 decode_facility(&setup.facility,
2224 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2225 }
2226 /* called party bcd number */
2227 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2228 setup.fields |= MNCC_F_CALLED;
2229 decode_called(&setup.called,
2230 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2231 }
2232 /* user-user */
2233 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2234 setup.fields |= MNCC_F_USERUSER;
2235 decode_useruser(&setup.useruser,
2236 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2237 }
2238 /* ss-version */
2239 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2240 setup.fields |= MNCC_F_SSVERSION;
2241 decode_ssversion(&setup.ssversion,
2242 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2243 }
2244 /* CLIR suppression */
2245 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2246 setup.clir.sup = 1;
2247 /* CLIR invocation */
2248 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2249 setup.clir.inv = 1;
2250 /* cc cap */
2251 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2252 setup.fields |= MNCC_F_CCCAP;
2253 decode_cccap(&setup.cccap,
2254 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2255 }
2256
2257 if (is_ipaccess_bts(msg->trx->bts))
2258 rsl_ipacc_bind(msg->lchan);
2259
2260 new_cc_state(trans, GSM_CSTATE_INITIATED);
2261
2262 /* indicate setup to MNCC */
2263 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2264
2265 return 0;
2266}
2267
2268static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002269{
2270 struct msgb *msg = gsm48_msgb_alloc();
2271 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002272 struct gsm_mncc *setup = arg;
2273 struct gsm_trans *transt;
2274 u_int16_t trans_id_mask = 0;
2275 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002276
Harald Welte7ccf7782009-02-17 01:43:01 +00002277 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002278
Harald Welte4bfdfe72009-06-10 23:11:52 +08002279 /* transaction id must not be assigned */
2280 if (trans->transaction_id != 0xff) { /* unasssigned */
2281 DEBUGP(DCC, "TX Setup with assigned transaction. "
2282 "This is not allowed!\n");
2283 /* Temporarily out of order */
2284 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002285 GSM48_CAUSE_LOC_PRN_S_LU,
2286 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002287 trans->callref = 0;
2288 free_trans(trans);
2289 return rc;
2290 }
2291
2292 /* Get free transaction_id */
2293 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2294 /* Transaction of our lchan? */
2295 if (transt->lchan == trans->lchan &&
2296 transt->transaction_id != 0xff)
2297 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2298 }
2299 /* Assign free transaction ID */
2300 if ((trans_id_mask & 0x007f) == 0x7f) {
2301 /* no free transaction ID */
2302 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002303 GSM48_CAUSE_LOC_PRN_S_LU,
2304 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002305 trans->callref = 0;
2306 free_trans(trans);
2307 return rc;
2308 }
2309 for (i = 0; i < 7; i++) {
2310 if ((trans_id_mask & (1 << i)) == 0) {
2311 trans->transaction_id = i << 4; /* flag = 0 */
2312 break;
2313 }
2314 }
Harald Welte49f48b82009-02-17 15:29:33 +00002315
Harald Welte4bfdfe72009-06-10 23:11:52 +08002316 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2317 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002318 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002319
Harald Welte4bfdfe72009-06-10 23:11:52 +08002320 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002321
Harald Welte4bfdfe72009-06-10 23:11:52 +08002322 /* bearer capability */
2323 if (setup->fields & MNCC_F_BEARER_CAP)
2324 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2325 /* facility */
2326 if (setup->fields & MNCC_F_FACILITY)
2327 encode_facility(msg, 0, &setup->facility);
2328 /* progress */
2329 if (setup->fields & MNCC_F_PROGRESS)
2330 encode_progress(msg, 0, &setup->progress);
2331 /* calling party BCD number */
2332 if (setup->fields & MNCC_F_CALLING)
2333 encode_calling(msg, &setup->calling);
2334 /* called party BCD number */
2335 if (setup->fields & MNCC_F_CALLED)
2336 encode_called(msg, &setup->called);
2337 /* user-user */
2338 if (setup->fields & MNCC_F_USERUSER)
2339 encode_useruser(msg, 0, &setup->useruser);
2340 /* redirecting party BCD number */
2341 if (setup->fields & MNCC_F_REDIRECTING)
2342 encode_redirecting(msg, &setup->redirecting);
2343 /* signal */
2344 if (setup->fields & MNCC_F_SIGNAL)
2345 encode_signal(msg, setup->signal);
2346
2347 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002348
2349 return gsm48_sendmsg(msg);
2350}
2351
Harald Welte4bfdfe72009-06-10 23:11:52 +08002352static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2353{
2354 struct gsm48_hdr *gh = msgb_l3(msg);
2355 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2356 struct tlv_parsed tp;
2357 struct gsm_mncc call_conf;
2358
2359 gsm48_stop_cc_timer(trans);
2360 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2361
2362 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2363 call_conf.callref = trans->callref;
2364 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2365#if 0
2366 /* repeat */
2367 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2368 call_conf.repeat = 1;
2369 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2370 call_conf.repeat = 2;
2371#endif
2372 /* bearer capability */
2373 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2374 call_conf.fields |= MNCC_F_BEARER_CAP;
2375 decode_bearer_cap(&call_conf.bearer_cap,
2376 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2377 }
2378 /* cause */
2379 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2380 call_conf.fields |= MNCC_F_CAUSE;
2381 decode_cause(&call_conf.cause,
2382 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2383 }
2384 /* cc cap */
2385 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2386 call_conf.fields |= MNCC_F_CCCAP;
2387 decode_cccap(&call_conf.cccap,
2388 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2389 }
2390
2391 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2392
2393 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2394}
2395
2396static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2397{
2398 struct gsm_mncc *proceeding = arg;
2399 struct msgb *msg = gsm48_msgb_alloc();
2400 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2401
2402 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2403 msg->lchan = trans->lchan;
2404 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2405
2406 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2407
2408 /* bearer capability */
2409 if (proceeding->fields & MNCC_F_BEARER_CAP)
2410 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2411 /* facility */
2412 if (proceeding->fields & MNCC_F_FACILITY)
2413 encode_facility(msg, 0, &proceeding->facility);
2414 /* progress */
2415 if (proceeding->fields & MNCC_F_PROGRESS)
2416 encode_progress(msg, 0, &proceeding->progress);
2417
2418 return gsm48_sendmsg(msg);
2419}
2420
2421static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2422{
2423 struct gsm48_hdr *gh = msgb_l3(msg);
2424 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2425 struct tlv_parsed tp;
2426 struct gsm_mncc alerting;
2427
2428 gsm48_stop_cc_timer(trans);
2429 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2430
2431 memset(&alerting, 0, sizeof(struct gsm_mncc));
2432 alerting.callref = trans->callref;
2433 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2434 /* facility */
2435 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2436 alerting.fields |= MNCC_F_FACILITY;
2437 decode_facility(&alerting.facility,
2438 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2439 }
2440
2441 /* progress */
2442 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2443 alerting.fields |= MNCC_F_PROGRESS;
2444 decode_progress(&alerting.progress,
2445 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2446 }
2447 /* ss-version */
2448 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2449 alerting.fields |= MNCC_F_SSVERSION;
2450 decode_ssversion(&alerting.ssversion,
2451 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2452 }
2453
2454 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2455
2456 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2457}
2458
2459static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2460{
2461 struct gsm_mncc *alerting = arg;
2462 struct msgb *msg = gsm48_msgb_alloc();
2463 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2464
2465 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2466 msg->lchan = trans->lchan;
2467 gh->msg_type = GSM48_MT_CC_ALERTING;
2468
2469 /* facility */
2470 if (alerting->fields & MNCC_F_FACILITY)
2471 encode_facility(msg, 0, &alerting->facility);
2472 /* progress */
2473 if (alerting->fields & MNCC_F_PROGRESS)
2474 encode_progress(msg, 0, &alerting->progress);
2475 /* user-user */
2476 if (alerting->fields & MNCC_F_USERUSER)
2477 encode_useruser(msg, 0, &alerting->useruser);
2478
2479 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2480
2481 return gsm48_sendmsg(msg);
2482}
2483
2484static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2485{
2486 struct gsm_mncc *progress = arg;
2487 struct msgb *msg = gsm48_msgb_alloc();
2488 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2489
2490 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2491 msg->lchan = trans->lchan;
2492 gh->msg_type = GSM48_MT_CC_PROGRESS;
2493
2494 /* progress */
2495 encode_progress(msg, 1, &progress->progress);
2496 /* user-user */
2497 if (progress->fields & MNCC_F_USERUSER)
2498 encode_useruser(msg, 0, &progress->useruser);
2499
2500 return gsm48_sendmsg(msg);
2501}
2502
2503static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2504{
2505 struct gsm_mncc *connect = arg;
2506 struct msgb *msg = gsm48_msgb_alloc();
2507 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2508
2509 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2510 msg->lchan = trans->lchan;
2511 gh->msg_type = GSM48_MT_CC_CONNECT;
2512
2513 gsm48_stop_cc_timer(trans);
2514 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2515
2516 /* facility */
2517 if (connect->fields & MNCC_F_FACILITY)
2518 encode_facility(msg, 0, &connect->facility);
2519 /* progress */
2520 if (connect->fields & MNCC_F_PROGRESS)
2521 encode_progress(msg, 0, &connect->progress);
2522 /* connected number */
2523 if (connect->fields & MNCC_F_CONNECTED)
2524 encode_connected(msg, &connect->connected);
2525 /* user-user */
2526 if (connect->fields & MNCC_F_USERUSER)
2527 encode_useruser(msg, 0, &connect->useruser);
2528
2529 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2530
2531 return gsm48_sendmsg(msg);
2532}
2533
2534static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2535{
2536 struct gsm48_hdr *gh = msgb_l3(msg);
2537 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2538 struct tlv_parsed tp;
2539 struct gsm_mncc connect;
2540
2541 gsm48_stop_cc_timer(trans);
2542
2543 memset(&connect, 0, sizeof(struct gsm_mncc));
2544 connect.callref = trans->callref;
2545 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2546 /* use subscriber as connected party number */
2547 if (trans->subscr) {
2548 connect.fields |= MNCC_F_CONNECTED;
2549 strncpy(connect.connected.number, trans->subscr->extension,
2550 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002551 strncpy(connect.imsi, trans->subscr->imsi,
2552 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002553 }
2554 /* facility */
2555 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2556 connect.fields |= MNCC_F_FACILITY;
2557 decode_facility(&connect.facility,
2558 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2559 }
2560 /* user-user */
2561 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2562 connect.fields |= MNCC_F_USERUSER;
2563 decode_useruser(&connect.useruser,
2564 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2565 }
2566 /* ss-version */
2567 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2568 connect.fields |= MNCC_F_SSVERSION;
2569 decode_ssversion(&connect.ssversion,
2570 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2571 }
2572
2573 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2574
2575 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2576}
2577
2578
2579static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2580{
2581 struct gsm_mncc connect_ack;
2582
2583 gsm48_stop_cc_timer(trans);
2584
2585 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2586
2587 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2588 connect_ack.callref = trans->callref;
2589 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2590 &connect_ack);
2591}
2592
2593static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2594{
2595 struct msgb *msg = gsm48_msgb_alloc();
2596 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2597
2598 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2599 msg->lchan = trans->lchan;
2600 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2601
2602 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2603
2604 return gsm48_sendmsg(msg);
2605}
2606
2607static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2608{
2609 struct gsm48_hdr *gh = msgb_l3(msg);
2610 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2611 struct tlv_parsed tp;
2612 struct gsm_mncc disc;
2613
2614 gsm48_stop_cc_timer(trans);
2615
2616 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2617
2618 memset(&disc, 0, sizeof(struct gsm_mncc));
2619 disc.callref = trans->callref;
2620 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2621 /* cause */
2622 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2623 disc.fields |= MNCC_F_CAUSE;
2624 decode_cause(&disc.cause,
2625 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2626 }
2627 /* facility */
2628 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2629 disc.fields |= MNCC_F_FACILITY;
2630 decode_facility(&disc.facility,
2631 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2632 }
2633 /* user-user */
2634 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2635 disc.fields |= MNCC_F_USERUSER;
2636 decode_useruser(&disc.useruser,
2637 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2638 }
2639 /* ss-version */
2640 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2641 disc.fields |= MNCC_F_SSVERSION;
2642 decode_ssversion(&disc.ssversion,
2643 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2644 }
2645
2646 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2647
2648}
2649
Harald Weltec66b71c2009-06-11 14:23:20 +08002650static struct gsm_mncc_cause default_cause = {
2651 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2652 .coding = 0,
2653 .rec = 0,
2654 .rec_val = 0,
2655 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2656 .diag_len = 0,
2657 .diag = { 0 },
2658};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002659
2660static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2661{
2662 struct gsm_mncc *disc = arg;
2663 struct msgb *msg = gsm48_msgb_alloc();
2664 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2665
2666 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2667 msg->lchan = trans->lchan;
2668 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2669
2670 gsm48_stop_cc_timer(trans);
2671 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2672
2673 /* cause */
2674 if (disc->fields & MNCC_F_CAUSE)
2675 encode_cause(msg, 1, &disc->cause);
2676 else
2677 encode_cause(msg, 1, &default_cause);
2678
2679 /* facility */
2680 if (disc->fields & MNCC_F_FACILITY)
2681 encode_facility(msg, 0, &disc->facility);
2682 /* progress */
2683 if (disc->fields & MNCC_F_PROGRESS)
2684 encode_progress(msg, 0, &disc->progress);
2685 /* user-user */
2686 if (disc->fields & MNCC_F_USERUSER)
2687 encode_useruser(msg, 0, &disc->useruser);
2688
2689 /* store disconnect cause for T306 expiry */
2690 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2691
2692 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2693
2694 return gsm48_sendmsg(msg);
2695}
2696
2697static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2698{
2699 struct gsm48_hdr *gh = msgb_l3(msg);
2700 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2701 struct tlv_parsed tp;
2702 struct gsm_mncc rel;
2703 int rc;
2704
2705 gsm48_stop_cc_timer(trans);
2706
2707 memset(&rel, 0, sizeof(struct gsm_mncc));
2708 rel.callref = trans->callref;
2709 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2710 /* cause */
2711 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2712 rel.fields |= MNCC_F_CAUSE;
2713 decode_cause(&rel.cause,
2714 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2715 }
2716 /* facility */
2717 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2718 rel.fields |= MNCC_F_FACILITY;
2719 decode_facility(&rel.facility,
2720 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2721 }
2722 /* user-user */
2723 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2724 rel.fields |= MNCC_F_USERUSER;
2725 decode_useruser(&rel.useruser,
2726 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2727 }
2728 /* ss-version */
2729 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2730 rel.fields |= MNCC_F_SSVERSION;
2731 decode_ssversion(&rel.ssversion,
2732 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2733 }
2734
2735 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2736 /* release collision 5.4.5 */
2737 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2738 } else {
2739 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2740 GSM48_MT_CC_RELEASE_COMPL);
2741 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2742 }
2743
2744 new_cc_state(trans, GSM_CSTATE_NULL);
2745
2746 trans->callref = 0;
2747 free_trans(trans);
2748
2749 return rc;
2750}
2751
2752static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2753{
2754 struct gsm_mncc *rel = arg;
2755 struct msgb *msg = gsm48_msgb_alloc();
2756 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2757
2758 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2759 msg->lchan = trans->lchan;
2760 gh->msg_type = GSM48_MT_CC_RELEASE;
2761
2762 trans->callref = 0;
2763
2764 gsm48_stop_cc_timer(trans);
2765 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2766
2767 /* cause */
2768 if (rel->fields & MNCC_F_CAUSE)
2769 encode_cause(msg, 0, &rel->cause);
2770 /* facility */
2771 if (rel->fields & MNCC_F_FACILITY)
2772 encode_facility(msg, 0, &rel->facility);
2773 /* user-user */
2774 if (rel->fields & MNCC_F_USERUSER)
2775 encode_useruser(msg, 0, &rel->useruser);
2776
2777 trans->T308_second = 0;
2778 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2779
2780 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2781 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2782
2783 return gsm48_sendmsg(msg);
2784}
2785
2786static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2787{
2788 struct gsm48_hdr *gh = msgb_l3(msg);
2789 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2790 struct tlv_parsed tp;
2791 struct gsm_mncc rel;
2792 int rc = 0;
2793
2794 gsm48_stop_cc_timer(trans);
2795
2796 memset(&rel, 0, sizeof(struct gsm_mncc));
2797 rel.callref = trans->callref;
2798 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2799 /* cause */
2800 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2801 rel.fields |= MNCC_F_CAUSE;
2802 decode_cause(&rel.cause,
2803 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2804 }
2805 /* facility */
2806 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2807 rel.fields |= MNCC_F_FACILITY;
2808 decode_facility(&rel.facility,
2809 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2810 }
2811 /* user-user */
2812 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2813 rel.fields |= MNCC_F_USERUSER;
2814 decode_useruser(&rel.useruser,
2815 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2816 }
2817 /* ss-version */
2818 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2819 rel.fields |= MNCC_F_SSVERSION;
2820 decode_ssversion(&rel.ssversion,
2821 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2822 }
2823
2824 if (trans->callref) {
2825 switch (trans->state) {
2826 case GSM_CSTATE_CALL_PRESENT:
2827 rc = mncc_recvmsg(trans->network, trans,
2828 MNCC_REJ_IND, &rel);
2829 break;
2830 case GSM_CSTATE_RELEASE_REQ:
2831 rc = mncc_recvmsg(trans->network, trans,
2832 MNCC_REL_CNF, &rel);
2833 break;
2834 default:
2835 rc = mncc_recvmsg(trans->network, trans,
2836 MNCC_REL_IND, &rel);
2837 }
2838 }
2839
2840 trans->callref = 0;
2841 free_trans(trans);
2842
2843 return rc;
2844}
2845
2846static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2847{
2848 struct gsm_mncc *rel = arg;
2849 struct msgb *msg = gsm48_msgb_alloc();
2850 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2851
2852 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2853 msg->lchan = trans->lchan;
2854 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2855
2856 trans->callref = 0;
2857
2858 gsm48_stop_cc_timer(trans);
2859
2860 /* cause */
2861 if (rel->fields & MNCC_F_CAUSE)
2862 encode_cause(msg, 0, &rel->cause);
2863 /* facility */
2864 if (rel->fields & MNCC_F_FACILITY)
2865 encode_facility(msg, 0, &rel->facility);
2866 /* user-user */
2867 if (rel->fields & MNCC_F_USERUSER)
2868 encode_useruser(msg, 0, &rel->useruser);
2869
2870 free_trans(trans);
2871
2872 return gsm48_sendmsg(msg);
2873}
2874
2875static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2876{
2877 struct gsm48_hdr *gh = msgb_l3(msg);
2878 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2879 struct tlv_parsed tp;
2880 struct gsm_mncc fac;
2881
2882 memset(&fac, 0, sizeof(struct gsm_mncc));
2883 fac.callref = trans->callref;
2884 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2885 /* facility */
2886 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2887 fac.fields |= MNCC_F_FACILITY;
2888 decode_facility(&fac.facility,
2889 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2890 }
2891 /* ss-version */
2892 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2893 fac.fields |= MNCC_F_SSVERSION;
2894 decode_ssversion(&fac.ssversion,
2895 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2896 }
2897
2898 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2899}
2900
2901static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2902{
2903 struct gsm_mncc *fac = arg;
2904 struct msgb *msg = gsm48_msgb_alloc();
2905 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2906
2907 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2908 msg->lchan = trans->lchan;
2909 gh->msg_type = GSM48_MT_CC_FACILITY;
2910
2911 /* facility */
2912 encode_facility(msg, 1, &fac->facility);
2913
2914 return gsm48_sendmsg(msg);
2915}
2916
2917static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2918{
2919 struct gsm_mncc hold;
2920
2921 memset(&hold, 0, sizeof(struct gsm_mncc));
2922 hold.callref = trans->callref;
2923 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2924}
2925
2926static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2927{
2928 struct msgb *msg = gsm48_msgb_alloc();
2929 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2930
2931 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2932 msg->lchan = trans->lchan;
2933 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2934
2935 return gsm48_sendmsg(msg);
2936}
2937
2938static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2939{
2940 struct gsm_mncc *hold_rej = arg;
2941 struct msgb *msg = gsm48_msgb_alloc();
2942 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2943
2944 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2945 msg->lchan = trans->lchan;
2946 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2947
2948 /* cause */
2949 if (hold_rej->fields & MNCC_F_CAUSE)
2950 encode_cause(msg, 1, &hold_rej->cause);
2951 else
2952 encode_cause(msg, 1, &default_cause);
2953
2954 return gsm48_sendmsg(msg);
2955}
2956
2957static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2958{
2959 struct gsm_mncc retrieve;
2960
2961 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2962 retrieve.callref = trans->callref;
2963 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2964}
2965
2966static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2967{
2968 struct msgb *msg = gsm48_msgb_alloc();
2969 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2970
2971 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2972 msg->lchan = trans->lchan;
2973 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2974
2975 return gsm48_sendmsg(msg);
2976}
2977
2978static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2979{
2980 struct gsm_mncc *retrieve_rej = arg;
2981 struct msgb *msg = gsm48_msgb_alloc();
2982 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2983
2984 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2985 msg->lchan = trans->lchan;
2986 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2987
2988 /* cause */
2989 if (retrieve_rej->fields & MNCC_F_CAUSE)
2990 encode_cause(msg, 1, &retrieve_rej->cause);
2991 else
2992 encode_cause(msg, 1, &default_cause);
2993
2994 return gsm48_sendmsg(msg);
2995}
2996
2997static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2998{
2999 struct gsm48_hdr *gh = msgb_l3(msg);
3000 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3001 struct tlv_parsed tp;
3002 struct gsm_mncc dtmf;
3003
3004 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3005 dtmf.callref = trans->callref;
3006 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3007 /* keypad facility */
3008 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3009 dtmf.fields |= MNCC_F_KEYPAD;
3010 decode_keypad(&dtmf.keypad,
3011 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3012 }
3013
3014 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3015}
3016
3017static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3018{
3019 struct gsm_mncc *dtmf = arg;
3020 struct msgb *msg = gsm48_msgb_alloc();
3021 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3022
3023 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3024 msg->lchan = trans->lchan;
3025 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3026
3027 /* keypad */
3028 if (dtmf->fields & MNCC_F_KEYPAD)
3029 encode_keypad(msg, dtmf->keypad);
3030
3031 return gsm48_sendmsg(msg);
3032}
3033
3034static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3035{
3036 struct gsm_mncc *dtmf = arg;
3037 struct msgb *msg = gsm48_msgb_alloc();
3038 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3039
3040 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3041 msg->lchan = trans->lchan;
3042 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3043
3044 /* cause */
3045 if (dtmf->fields & MNCC_F_CAUSE)
3046 encode_cause(msg, 1, &dtmf->cause);
3047 else
3048 encode_cause(msg, 1, &default_cause);
3049
3050 return gsm48_sendmsg(msg);
3051}
3052
3053static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3054{
3055 struct msgb *msg = gsm48_msgb_alloc();
3056 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3057
3058 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3059 msg->lchan = trans->lchan;
3060 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3061
3062 return gsm48_sendmsg(msg);
3063}
3064
3065static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3066{
3067 struct gsm_mncc dtmf;
3068
3069 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3070 dtmf.callref = trans->callref;
3071
3072 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3073}
3074
3075static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3076{
3077 struct gsm48_hdr *gh = msgb_l3(msg);
3078 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3079 struct tlv_parsed tp;
3080 struct gsm_mncc modify;
3081
3082 memset(&modify, 0, sizeof(struct gsm_mncc));
3083 modify.callref = trans->callref;
3084 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3085 /* bearer capability */
3086 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3087 modify.fields |= MNCC_F_BEARER_CAP;
3088 decode_bearer_cap(&modify.bearer_cap,
3089 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3090 }
3091
3092 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3093
3094 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3095}
3096
3097static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3098{
3099 struct gsm_mncc *modify = arg;
3100 struct msgb *msg = gsm48_msgb_alloc();
3101 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3102
3103 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3104 msg->lchan = trans->lchan;
3105 gh->msg_type = GSM48_MT_CC_MODIFY;
3106
3107 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3108
3109 /* bearer capability */
3110 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3111
3112 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3113
3114 return gsm48_sendmsg(msg);
3115}
3116
3117static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3118{
3119 struct gsm48_hdr *gh = msgb_l3(msg);
3120 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3121 struct tlv_parsed tp;
3122 struct gsm_mncc modify;
3123
3124 gsm48_stop_cc_timer(trans);
3125
3126 memset(&modify, 0, sizeof(struct gsm_mncc));
3127 modify.callref = trans->callref;
3128 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3129 /* bearer capability */
3130 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3131 modify.fields |= MNCC_F_BEARER_CAP;
3132 decode_bearer_cap(&modify.bearer_cap,
3133 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3134 }
3135
3136 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3137
3138 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3139}
3140
3141static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3142{
3143 struct gsm_mncc *modify = arg;
3144 struct msgb *msg = gsm48_msgb_alloc();
3145 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3146
3147 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3148 msg->lchan = trans->lchan;
3149 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3150
3151 /* bearer capability */
3152 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3153
3154 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3155
3156 return gsm48_sendmsg(msg);
3157}
3158
3159static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3160{
3161 struct gsm48_hdr *gh = msgb_l3(msg);
3162 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3163 struct tlv_parsed tp;
3164 struct gsm_mncc modify;
3165
3166 gsm48_stop_cc_timer(trans);
3167
3168 memset(&modify, 0, sizeof(struct gsm_mncc));
3169 modify.callref = trans->callref;
3170 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3171 /* bearer capability */
3172 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3173 modify.fields |= GSM48_IE_BEARER_CAP;
3174 decode_bearer_cap(&modify.bearer_cap,
3175 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3176 }
3177 /* cause */
3178 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3179 modify.fields |= MNCC_F_CAUSE;
3180 decode_cause(&modify.cause,
3181 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3182 }
3183
3184 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3185
3186 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3187}
3188
3189static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3190{
3191 struct gsm_mncc *modify = arg;
3192 struct msgb *msg = gsm48_msgb_alloc();
3193 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3194
3195 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3196 msg->lchan = trans->lchan;
3197 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3198
3199 /* bearer capability */
3200 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3201 /* cause */
3202 encode_cause(msg, 1, &modify->cause);
3203
3204 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3205
3206 return gsm48_sendmsg(msg);
3207}
3208
3209static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3210{
3211 struct gsm_mncc *notify = arg;
3212 struct msgb *msg = gsm48_msgb_alloc();
3213 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3214
3215 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3216 msg->lchan = trans->lchan;
3217 gh->msg_type = GSM48_MT_CC_NOTIFY;
3218
3219 /* notify */
3220 encode_notify(msg, notify->notify);
3221
3222 return gsm48_sendmsg(msg);
3223}
3224
3225static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3226{
3227 struct gsm48_hdr *gh = msgb_l3(msg);
3228 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3229// struct tlv_parsed tp;
3230 struct gsm_mncc notify;
3231
3232 memset(&notify, 0, sizeof(struct gsm_mncc));
3233 notify.callref = trans->callref;
3234// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3235 if (payload_len >= 1)
3236 decode_notify(&notify.notify, gh->data);
3237
3238 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3239}
3240
3241static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3242{
3243 struct gsm_mncc *user = arg;
3244 struct msgb *msg = gsm48_msgb_alloc();
3245 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3246
3247 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3248 msg->lchan = trans->lchan;
3249 gh->msg_type = GSM48_MT_CC_USER_INFO;
3250
3251 /* user-user */
3252 if (user->fields & MNCC_F_USERUSER)
3253 encode_useruser(msg, 1, &user->useruser);
3254 /* more data */
3255 if (user->more)
3256 encode_more(msg);
3257
3258 return gsm48_sendmsg(msg);
3259}
3260
3261static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3262{
3263 struct gsm48_hdr *gh = msgb_l3(msg);
3264 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3265 struct tlv_parsed tp;
3266 struct gsm_mncc user;
3267
3268 memset(&user, 0, sizeof(struct gsm_mncc));
3269 user.callref = trans->callref;
3270 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3271 /* user-user */
3272 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3273 user.fields |= MNCC_F_USERUSER;
3274 decode_useruser(&user.useruser,
3275 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3276 }
3277 /* more data */
3278 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3279 user.more = 1;
3280
3281 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3282}
3283
3284static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3285{
3286 struct gsm_mncc *mode = arg;
3287
3288 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3289}
3290
3291static struct downstate {
3292 u_int32_t states;
3293 int type;
3294 int (*rout) (struct gsm_trans *trans, void *arg);
3295} downstatelist[] = {
3296 /* mobile originating call establishment */
3297 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3298 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3299 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3300 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3301 {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 */
3302 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3303 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3304 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3305 /* mobile terminating call establishment */
3306 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3307 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3308 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3309 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3310 /* signalling during call */
3311 {SBIT(GSM_CSTATE_ACTIVE),
3312 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3313 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3314 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3315 {ALL_STATES,
3316 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3317 {ALL_STATES,
3318 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3319 {ALL_STATES,
3320 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3321 {SBIT(GSM_CSTATE_ACTIVE),
3322 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3323 {SBIT(GSM_CSTATE_ACTIVE),
3324 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3325 {SBIT(GSM_CSTATE_ACTIVE),
3326 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3327 {SBIT(GSM_CSTATE_ACTIVE),
3328 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3329 {SBIT(GSM_CSTATE_ACTIVE),
3330 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3331 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3332 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3333 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3334 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3335 {SBIT(GSM_CSTATE_ACTIVE),
3336 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3337 /* clearing */
3338 {SBIT(GSM_CSTATE_INITIATED),
3339 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3340 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3341 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3342 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3343 MNCC_REL_REQ, gsm48_cc_tx_release},
3344 /* special */
3345 {ALL_STATES,
3346 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3347};
3348
3349#define DOWNSLLEN \
3350 (sizeof(downstatelist) / sizeof(struct downstate))
3351
3352
3353int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3354{
3355 int i, j, k, l, rc = 0;
3356 struct gsm_trans *trans = NULL, *transt;
3357 struct gsm_subscriber *subscr;
3358 struct gsm_lchan *lchan = NULL, *lchant;
3359 struct gsm_bts *bts = NULL;
3360 struct gsm_bts_trx *trx;
3361 struct gsm_bts_trx_ts *ts;
3362 struct gsm_mncc *data = arg, rel;
3363
3364 /* handle special messages */
3365 switch(msg_type) {
3366 case MNCC_BRIDGE:
3367 return tch_bridge(net, arg);
3368 case MNCC_FRAME_DROP:
3369 return tch_recv(net, arg, 0);
3370 case MNCC_FRAME_RECV:
3371 return tch_recv(net, arg, 1);
3372 case GSM_TRAU_FRAME:
3373 return tch_frame(net, arg);
3374 }
3375
3376 memset(&rel, 0, sizeof(struct gsm_mncc));
3377 rel.callref = data->callref;
3378
3379 /* Find callref */
3380 trans = get_trans_ref(net, data->callref);
3381
3382 /* Callref unknown */
3383 if (!trans) {
Andreas Eversbergc079be42009-06-15 23:22:09 +02003384 if (msg_type != MNCC_SETUP_REQ ||
3385 (!data->called.number[0] && !data->imsi[0])) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003386 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3387 "Received '%s' from MNCC with "
3388 "unknown callref %d\n", data->called.number,
3389 get_mncc_name(msg_type), data->callref);
3390 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003391 return mncc_release_ind(net, NULL, data->callref,
3392 GSM48_CAUSE_LOC_PRN_S_LU,
3393 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003394 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003395 if (!data->called.number[0] && !data->imsi[0]) {
3396 DEBUGP(DCC, "(bts - trx - ts - ti) "
3397 "Received '%s' from MNCC with "
3398 "no number or IMSI\n", get_mncc_name(msg_type));
3399 /* Invalid number */
3400 return mncc_release_ind(net, NULL, data->callref,
3401 GSM48_CAUSE_LOC_PRN_S_LU,
3402 GSM48_CC_CAUSE_INV_NR_FORMAT);
3403 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003404 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003405 if (data->called.number[0])
3406 subscr = subscr_get_by_extension(data->called.number);
3407 else
3408 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003409 /* If subscriber is not found */
3410 if (!subscr) {
3411 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3412 "Received '%s' from MNCC with "
3413 "unknown subscriber %s\n", data->called.number,
3414 get_mncc_name(msg_type), data->called.number);
3415 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003416 return mncc_release_ind(net, NULL, data->callref,
3417 GSM48_CAUSE_LOC_PRN_S_LU,
3418 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003419 }
3420 /* If subscriber is not "attached" */
3421 if (!subscr->lac) {
3422 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3423 "Received '%s' from MNCC with "
3424 "detached subscriber %s\n", data->called.number,
3425 get_mncc_name(msg_type), data->called.number);
3426 subscr_put(subscr);
3427 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003428 return mncc_release_ind(net, NULL, data->callref,
3429 GSM48_CAUSE_LOC_PRN_S_LU,
3430 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003431 }
3432 /* Create transaction */
Harald Weltec05677b2009-06-26 20:17:06 +02003433 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003434 DEBUGP(DCC, "No memory for trans.\n");
3435 subscr_put(subscr);
3436 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003437 mncc_release_ind(net, NULL, data->callref,
3438 GSM48_CAUSE_LOC_PRN_S_LU,
3439 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003440 return -ENOMEM;
3441 }
3442 trans->callref = data->callref;
3443 trans->network = net;
3444 trans->transaction_id = 0xff; /* unassigned */
3445 llist_add_tail(&trans->entry, &net->trans_list);
3446 /* Assign subscriber to transaction */
3447 trans->subscr = subscr;
3448 /* Find lchan */
3449 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003450 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003451 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003452 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003453 for (k = 0; k < TRX_NR_TS; k++) {
3454 ts = &trx->ts[k];
3455 for (l = 0; l < TS_MAX_LCHAN; l++) {
3456 lchant = &ts->lchan[l];
3457 if (lchant->subscr == subscr) {
3458 lchan = lchant;
3459 break;
3460 }
3461 }
3462 }
3463 }
3464 }
3465
3466 /* If subscriber has no lchan */
3467 if (!lchan) {
3468 /* find transaction with this subscriber already paging */
3469 llist_for_each_entry(transt, &net->trans_list, entry) {
3470 /* Transaction of our lchan? */
3471 if (transt == trans ||
3472 transt->subscr != subscr)
3473 continue;
3474 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3475 "Received '%s' from MNCC with "
3476 "unallocated channel, paging already "
3477 "started.\n", bts->nr,
3478 data->called.number,
3479 get_mncc_name(msg_type));
3480 return 0;
3481 }
3482 /* store setup informations until paging was successfull */
3483 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3484 /* start paging subscriber on all BTS with her location */
3485 subscr->net = net;
3486 bts = NULL;
3487 do {
3488 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3489 if (!bts)
3490 break;
3491 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3492 "Received '%s' from MNCC with "
3493 "unallocated channel, paging.\n",
3494 bts->nr, data->called.number,
3495 get_mncc_name(msg_type));
3496 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003497 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003498 setup_trig_pag_evt, subscr);
3499 } while (1);
3500 return 0;
3501 }
3502 /* Assign lchan */
3503 trans->lchan = lchan;
3504 use_lchan(lchan);
3505 }
3506 lchan = trans->lchan;
3507
3508 /* if paging did not respond yet */
3509 if (!lchan) {
3510 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3511 "Received '%s' from MNCC in paging state\n",
3512 (trans->subscr)?(trans->subscr->extension):"-",
3513 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003514 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3515 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003516 if (msg_type == MNCC_REL_REQ)
3517 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3518 else
3519 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3520 trans->callref = 0;
3521 free_trans(trans);
3522 return rc;
3523 }
3524
3525 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3526 "Received '%s' from MNCC in state %d (%s)\n",
3527 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3528 trans->transaction_id,
3529 (lchan->subscr)?(lchan->subscr->extension):"-",
3530 get_mncc_name(msg_type), trans->state,
3531 cc_state_names[trans->state]);
3532
3533 /* Find function for current state and message */
3534 for (i = 0; i < DOWNSLLEN; i++)
3535 if ((msg_type == downstatelist[i].type)
3536 && ((1 << trans->state) & downstatelist[i].states))
3537 break;
3538 if (i == DOWNSLLEN) {
3539 DEBUGP(DCC, "Message unhandled at this state.\n");
3540 return 0;
3541 }
3542
3543 rc = downstatelist[i].rout(trans, arg);
3544
3545 return rc;
3546}
3547
3548
3549static struct datastate {
3550 u_int32_t states;
3551 int type;
3552 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3553} datastatelist[] = {
3554 /* mobile originating call establishment */
3555 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3556 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3557 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3558 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3559 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3560 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3561 /* mobile terminating call establishment */
3562 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3563 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3564 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3565 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3566 {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 */
3567 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3568 /* signalling during call */
3569 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3570 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3571 {SBIT(GSM_CSTATE_ACTIVE),
3572 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3573 {ALL_STATES,
3574 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3575 {ALL_STATES,
3576 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3577 {ALL_STATES,
3578 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3579 {SBIT(GSM_CSTATE_ACTIVE),
3580 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3581 {SBIT(GSM_CSTATE_ACTIVE),
3582 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3583 {SBIT(GSM_CSTATE_ACTIVE),
3584 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3585 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3586 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3587 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3588 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3589 {SBIT(GSM_CSTATE_ACTIVE),
3590 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3591 /* clearing */
3592 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3593 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3594 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3595 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3596 {ALL_STATES, /* 5.4.3.4 */
3597 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3598};
3599
3600#define DATASLLEN \
3601 (sizeof(datastatelist) / sizeof(struct datastate))
3602
Harald Welte4bc90a12008-12-27 16:32:52 +00003603static int gsm0408_rcv_cc(struct msgb *msg)
3604{
3605 struct gsm48_hdr *gh = msgb_l3(msg);
3606 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003607 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3608 struct gsm_lchan *lchan = msg->lchan;
3609 struct gsm_trans *trans = NULL, *transt;
3610 struct gsm_network *net = lchan->ts->trx->bts->network;
3611 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003612
Harald Welte4bfdfe72009-06-10 23:11:52 +08003613 if (msg_type & 0x80) {
3614 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3615 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003616 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003617
3618 /* Find transaction */
3619 llist_for_each_entry(transt, &net->trans_list, entry) {
3620 /* Transaction of our lchan? */
3621 if (transt->lchan == lchan
3622 && transt->transaction_id == transaction_id) {
3623 trans = transt;
3624 }
3625 }
3626
3627 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3628 "Received '%s' from MS in state %d (%s)\n",
3629 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3630 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3631 cc_msg_names[msg_type], trans?(trans->state):0,
3632 cc_state_names[trans?(trans->state):0]);
3633
3634 /* Create transaction */
3635 if (!trans) {
3636 DEBUGP(DCC, "Unknown transaction ID %02x, "
3637 "creating new trans.\n", transaction_id);
3638 /* Create transaction */
Harald Welte9b11e872009-06-26 19:42:28 +02003639 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003640 DEBUGP(DCC, "No memory for trans.\n");
3641 rc = gsm48_tx_simple(msg->lchan,
3642 GSM48_PDISC_CC | transaction_id,
3643 GSM48_MT_CC_RELEASE_COMPL);
3644 return -ENOMEM;
3645 }
3646 llist_add_tail(&trans->entry, &net->trans_list);
3647 /* Assign transaction */
3648 trans->callref = new_callref++;
3649 trans->network = net;
3650 trans->transaction_id = transaction_id;
3651 trans->lchan = lchan;
3652 use_lchan(lchan);
3653 if (lchan->subscr) {
3654 trans->subscr = lchan->subscr;
3655 subscr_get(trans->subscr);
3656 }
3657 }
3658
3659 /* find function for current state and message */
3660 for (i = 0; i < DATASLLEN; i++)
3661 if ((msg_type == datastatelist[i].type)
3662 && ((1 << trans->state) & datastatelist[i].states))
3663 break;
3664 if (i == DATASLLEN) {
3665 DEBUGP(DCC, "Message unhandled at this state.\n");
3666 return 0;
3667 }
3668
3669 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003670
3671 return rc;
3672}
3673
Harald Welte52b1f982008-12-23 20:25:15 +00003674/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3675int gsm0408_rcvmsg(struct msgb *msg)
3676{
3677 struct gsm48_hdr *gh = msgb_l3(msg);
3678 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003679 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003680
3681 switch (pdisc) {
3682 case GSM48_PDISC_CC:
3683 rc = gsm0408_rcv_cc(msg);
3684 break;
3685 case GSM48_PDISC_MM:
3686 rc = gsm0408_rcv_mm(msg);
3687 break;
3688 case GSM48_PDISC_RR:
3689 rc = gsm0408_rcv_rr(msg);
3690 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003691 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003692 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003693 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003694 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003695 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003696 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3697 pdisc);
3698 break;
3699 default:
3700 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3701 pdisc);
3702 break;
3703 }
3704
3705 return rc;
3706}
Harald Welte8470bf22008-12-25 23:28:35 +00003707
Harald Welte8470bf22008-12-25 23:28:35 +00003708/* Section 9.1.8 / Table 9.9 */
3709struct chreq {
3710 u_int8_t val;
3711 u_int8_t mask;
3712 enum chreq_type type;
3713};
3714
3715/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3716static const struct chreq chreq_type_neci1[] = {
3717 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3718 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3719 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3720 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3721 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3722 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3723 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3724 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3725 { 0x10, 0xf0, CHREQ_T_SDCCH },
3726 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3727 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3728 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3729};
3730
3731/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3732static const struct chreq chreq_type_neci0[] = {
3733 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3734 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3735 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3736 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3737 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3738 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3739 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3740 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3741};
3742
3743static const enum gsm_chan_t ctype_by_chreq[] = {
3744 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3745 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3746 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3747 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3748 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3749 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3750 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3751 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3752 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3753 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3754 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3755 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3756};
3757
Harald Weltee14a57c2008-12-29 04:08:28 +00003758static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3759 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3760 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3761 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3762 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3763 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3764 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3765 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3766 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3767 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3768 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3769 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3770 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3771};
3772
Harald Welte8470bf22008-12-25 23:28:35 +00003773enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3774{
3775 int i;
3776 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3777
3778 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3779 const struct chreq *chr = &chreq_type_neci0[i];
3780 if ((ra & chr->mask) == chr->val)
3781 return ctype_by_chreq[chr->type];
3782 }
3783 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3784 return GSM_LCHAN_SDCCH;
3785}
Harald Weltee14a57c2008-12-29 04:08:28 +00003786
3787enum gsm_chreq_reason_t get_reason_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 reason_by_chreq[chr->type];
3796 }
3797 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3798 return GSM_CHREQ_REASON_OTHER;
3799}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003800
3801/* dequeue messages to layer 4 */
3802int bsc_upqueue(struct gsm_network *net)
3803{
3804 struct gsm_mncc *mncc;
3805 struct msgb *msg;
3806 int work = 0;
3807
3808 if (net)
3809 while ((msg = msgb_dequeue(&net->upqueue))) {
3810 mncc = (struct gsm_mncc *)msg->data;
3811 if (net->mncc_recv)
3812 net->mncc_recv(net, mncc->msg_type, mncc);
3813 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003814 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003815 }
3816
3817 return work;
3818}