blob: c081b45c2d4412e7350d7aa17e4392009d6c02c6 [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
Harald Weltebf5e8df2009-02-03 12:59:45 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte498b0bb2009-01-09 21:27:43 +00005 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
Harald Welte7584aea2009-02-11 11:44:12 +000035#include <openbsc/tlv.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000040#include <openbsc/gsm_04_08.h>
41#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000042#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000043#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000044#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000045#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000046#include <openbsc/trau_mux.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020047#include <openbsc/talloc.h>
Harald Welte52b1f982008-12-23 20:25:15 +000048
Harald Welte8470bf22008-12-25 23:28:35 +000049#define GSM48_ALLOC_SIZE 1024
50#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000051
Harald Welte0c389302009-06-10 12:08:54 +080052#define GSM_MAX_FACILITY 128
53#define GSM_MAX_SSVERSION 128
54#define GSM_MAX_USERUSER 128
55
Harald Welte2cf161b2009-06-20 22:36:41 +020056static void *tall_locop_ctx;
57static void *tall_trans_ctx;
58
Harald Welte09e38af2009-02-16 22:52:23 +000059static const struct tlv_definition rsl_att_tlvdef = {
60 .def = {
61 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
62 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
63 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
64 [GSM48_IE_UTC] = { TLV_TYPE_TV },
65 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
66 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
67
68 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
69 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
70 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
71 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
72 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
73 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
74 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080075 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000076 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
77 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080078 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
79 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000080 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
81 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
82 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
83 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
84 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
86 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
87 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
88 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
89 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
90 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
91 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
92 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
93 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080094 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
95 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +000096 /* FIXME: more elements */
97 },
98};
Harald Weltecf5b3592009-05-01 18:28:42 +000099
100static const char *rr_cause_names[] = {
101 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
102 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
103 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
104 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
105 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
106 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
107 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
108 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
109 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
110 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
111 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
112 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
113 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
114 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
115 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
116 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
117 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
118};
119
Harald Welte4bfdfe72009-06-10 23:11:52 +0800120static const char *cc_state_names[] = {
121 "NULL",
122 "INITIATED",
123 "illegal state 2",
124 "MO_CALL_PROC",
125 "CALL_DELIVERED",
126 "illegal state 5",
127 "CALL_PRESENT",
128 "CALL_RECEIVED",
129 "CONNECT_REQUEST",
130 "MO_TERM_CALL_CONF",
131 "ACTIVE",
132 "DISCONNECT_REQ",
133 "DISCONNECT_IND",
134 "illegal state 13",
135 "illegal state 14",
136 "illegal state 15",
137 "illegal state 16",
138 "illegal state 17",
139 "illegal state 18",
140 "RELEASE_REQ",
141 "illegal state 20",
142 "illegal state 21",
143 "illegal state 22",
144 "illegal state 23",
145 "illegal state 24",
146 "illegal state 25",
147 "MO_ORIG_MODIFY",
148 "MO_TERM_MODIFY",
149 "CONNECT_IND",
150 "illegal state 29",
151 "illegal state 30",
152 "illegal state 31",
153};
154
155static const char *cc_msg_names[] = {
156 "unknown 0x00",
157 "ALERTING",
158 "CALL_PROC",
159 "PROGRESS",
160 "ESTAB",
161 "SETUP",
162 "ESTAB_CONF",
163 "CONNECT",
164 "CALL_CONF",
165 "START_CC",
166 "unknown 0x0a",
167 "RECALL",
168 "unknown 0x0c",
169 "unknown 0x0d",
170 "EMERG_SETUP",
171 "CONNECT_ACK",
172 "USER_INFO",
173 "unknown 0x11",
174 "unknown 0x12",
175 "MODIFY_REJECT",
176 "unknown 0x14",
177 "unknown 0x15",
178 "unknown 0x16",
179 "MODIFY",
180 "HOLD",
181 "HOLD_ACK",
182 "HOLD_REJ",
183 "unknown 0x1b",
184 "RETR",
185 "RETR_ACK",
186 "RETR_REJ",
187 "MODIFY_COMPL",
188 "unknown 0x20",
189 "unknown 0x21",
190 "unknown 0x22",
191 "unknown 0x23",
192 "unknown 0x24",
193 "DISCONNECT",
194 "unknown 0x26",
195 "unknown 0x27",
196 "unknown 0x28",
197 "unknown 0x29",
198 "RELEASE_COMPL",
199 "unknown 0x2b",
200 "unknown 0x2c",
201 "RELEASE",
202 "unknown 0x2e",
203 "unknown 0x2f",
204 "unknown 0x30",
205 "STOP_DTMF",
206 "STOP_DTMF_ACK",
207 "unknown 0x33",
208 "STATUS_ENQ",
209 "START_DTMF",
210 "START_DTMF_ACK",
211 "START_DTMF_REJ",
212 "unknown 0x38",
213 "CONG_CTRL",
214 "FACILITY",
215 "unknown 0x3b",
216 "STATUS",
217 "unknown 0x3c",
218 "NOTIFY",
219 "unknown 0x3f",
220};
221
Harald Weltecf5b3592009-05-01 18:28:42 +0000222static char strbuf[64];
223
224static const char *rr_cause_name(u_int8_t cause)
225{
226 if (cause < ARRAY_SIZE(rr_cause_names) &&
227 rr_cause_names[cause])
228 return rr_cause_names[cause];
229
230 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
231 return strbuf;
232}
233
Harald Weltef7c43522009-06-09 20:24:21 +0000234static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
235 int len)
236{
237 memset(rep, 0, sizeof(*rep));
238
239 if (data[0] & 0x80)
240 rep->flags |= MEAS_REP_F_BA1;
241 if (data[0] & 0x40)
242 rep->flags |= MEAS_REP_F_DTX;
243 if (data[1] & 0x40)
244 rep->flags |= MEAS_REP_F_VALID;
245
246 rep->rxlev_full = data[0] & 0x3f;
247 rep->rxlev_sub = data[1] & 0x3f;
248 rep->rxqual_full = (data[3] >> 4) & 0x7;
249 rep->rxqual_sub = (data[3] >> 1) & 0x7;
250 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
251 if (rep->num_cell < 1)
252 return;
253
254 /* an encoding nightmare in perfection */
255
256 rep->cell[0].rxlev = data[4] & 0x3f;
257 rep->cell[0].bcch_freq = data[5] >> 2;
258 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
259 if (rep->num_cell < 2)
260 return;
261
262 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
263 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
264 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
265 if (rep->num_cell < 3)
266 return;
267
268 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
269 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
270 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
271 if (rep->num_cell < 4)
272 return;
273
274 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
275 rep->cell[3].bcch_freq = data[11] & 0x1f;
276 rep->cell[3].bsic = data[12] >> 2;
277 if (rep->num_cell < 5)
278 return;
279
280 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
281 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
282 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
283 if (rep->num_cell < 6)
284 return;
285
286 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
287 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
288 rep->cell[5].bsic = data[16] & 0x3f;
289}
290
Holger Freytherd51524f2009-06-09 08:27:07 +0000291int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000292static int gsm48_tx_simple(struct gsm_lchan *lchan,
293 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000294static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800295void free_trans(struct gsm_trans *trans);
Harald Welte65e74cc2008-12-29 01:55:35 +0000296
Harald Welte52b1f982008-12-23 20:25:15 +0000297struct gsm_lai {
298 u_int16_t mcc;
299 u_int16_t mnc;
300 u_int16_t lac;
301};
302
Holger Freyther89824fc2008-12-30 16:18:18 +0000303static int authorize_everonye = 0;
304void gsm0408_allow_everyone(int everyone)
305{
306 printf("Allowing everyone?\n");
307 authorize_everonye = everyone;
308}
309
Holger Freythere97f7fb2008-12-31 18:52:11 +0000310static int reject_cause = 0;
311void gsm0408_set_reject_cause(int cause)
312{
313 reject_cause = cause;
314}
315
Harald Welte4bfdfe72009-06-10 23:11:52 +0800316static u_int32_t new_callref = 0x80000001;
317
Holger Freyther73487a22008-12-31 18:53:57 +0000318static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
319 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000320{
321 if (!subscriber)
322 return 0;
323
Holger Freyther73487a22008-12-31 18:53:57 +0000324 /*
325 * Do not send accept yet as more information should arrive. Some
326 * phones will not send us the information and we will have to check
327 * what we want to do with that.
328 */
329 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
330 return 0;
331
Holger Freyther89824fc2008-12-30 16:18:18 +0000332 if (authorize_everonye)
333 return 1;
334
335 return subscriber->authorized;
336}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000337
Holger Freyther73487a22008-12-31 18:53:57 +0000338static void release_loc_updating_req(struct gsm_lchan *lchan)
339{
Harald Welte179f0642008-12-31 23:59:18 +0000340 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000341 return;
342
Harald Welteff117a82009-05-23 05:22:08 +0000343 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200344 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000345 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000346 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000347}
348
349static void allocate_loc_updating_req(struct gsm_lchan *lchan)
350{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000351 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000352 release_loc_updating_req(lchan);
353
Harald Welte2cf161b2009-06-20 22:36:41 +0200354 if (!tall_locop_ctx)
355 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
356 "loc_updating_oper");
357 lchan->loc_operation = talloc(tall_locop_ctx,
358 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000359 memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
360}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000361
Holger Freytherd51524f2009-06-09 08:27:07 +0000362static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
363{
364 u_int32_t tmsi;
365
366 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
367 db_subscriber_alloc_tmsi(lchan->subscr);
368 subscr_update(lchan->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED);
369 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
370 release_loc_updating_req(lchan);
371 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
372 }
373
374 return 0;
375}
376
Holger Freyther7c19f742009-06-06 13:54:35 +0000377static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
378 void *handler_data, void *signal_data)
379{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800380 struct gsm_trans *trans, *temp;
381
Holger Freyther7c19f742009-06-06 13:54:35 +0000382 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
383 return 0;
384
385 /*
386 * Cancel any outstanding location updating request
387 * operation taking place on the lchan.
388 */
389 struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
390 release_loc_updating_req(lchan);
391
Harald Welte4bfdfe72009-06-10 23:11:52 +0800392 /* Free all transactions that are associated with the released lchan */
393 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
394 if (trans->lchan == lchan)
395 free_trans(trans);
396 }
397
Holger Freyther7c19f742009-06-06 13:54:35 +0000398 return 0;
399}
400
401/*
402 * This will be ran by the linker when loading the DSO. We use it to
403 * do system initialization, e.g. registration of signal handlers.
404 */
405static __attribute__((constructor)) void on_dso_load_0408(void)
406{
407 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
408}
409
Harald Welte52b1f982008-12-23 20:25:15 +0000410static void to_bcd(u_int8_t *bcd, u_int16_t val)
411{
Harald Welte4b634542008-12-27 01:55:51 +0000412 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000413 val = val / 10;
414 bcd[1] = val % 10;
415 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000416 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000417 val = val / 10;
418}
419
Holger Freyther17746612008-12-28 16:32:44 +0000420void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000421 u_int16_t mnc, u_int16_t lac)
422{
423 u_int8_t bcd[3];
424
425 to_bcd(bcd, mcc);
426 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
427 lai48->digits[1] = bcd[2];
428
429 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000430 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
431#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000432 lai48->digits[1] |= bcd[2] << 4;
433 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000434#else
435 lai48->digits[1] |= 0xf << 4;
436 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
437#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000438
Harald Welte4b634542008-12-27 01:55:51 +0000439 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000440}
441
Harald Welte255539c2008-12-28 02:26:27 +0000442#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000443#define MID_TMSI_LEN (TMSI_LEN + 2)
444
Harald Welte255539c2008-12-28 02:26:27 +0000445int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000446{
Harald Welte65e74cc2008-12-29 01:55:35 +0000447 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000448
Harald Welte4b634542008-12-27 01:55:51 +0000449 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000450 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000451 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000452 *tptr = htonl(tmsi);
453
454 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000455}
456
Harald Welte09e38af2009-02-16 22:52:23 +0000457static const char bcd_num_digits[] = {
458 '0', '1', '2', '3', '4', '5', '6', '7',
459 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
460};
461
Harald Welte0c389302009-06-10 12:08:54 +0800462/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
463int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
464 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000465{
466 u_int8_t in_len = bcd_lv[0];
467 int i;
468
Harald Welte0c389302009-06-10 12:08:54 +0800469 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000470 /* lower nibble */
471 output_len--;
472 if (output_len <= 1)
473 break;
474 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
475
476 /* higher nibble */
477 output_len--;
478 if (output_len <= 1)
479 break;
480 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
481 }
482 if (output_len >= 1)
483 *output++ = '\0';
484
Harald Welte0c389302009-06-10 12:08:54 +0800485 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000486}
487
488/* convert a single ASCII character to call-control BCD */
489static int asc_to_bcd(const char asc)
490{
491 int i;
492
493 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
494 if (bcd_num_digits[i] == asc)
495 return i;
496 }
497 return -EINVAL;
498}
499
Harald Welte0c389302009-06-10 12:08:54 +0800500/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000501int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800502 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000503{
504 int in_len = strlen(input);
505 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800506 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000507
508 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800509 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000510 if (in_len % 2)
511 bcd_lv[0]++;
512
Harald Welte0c389302009-06-10 12:08:54 +0800513 if (bcd_lv[0] > max_len)
514 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000515
516 for (i = 0; i < in_len; i++) {
517 int rc = asc_to_bcd(input[i]);
518 if (rc < 0)
519 return rc;
520 if (i % 2 == 0)
521 *bcd_cur = rc;
522 else
523 *bcd_cur++ |= (rc << 4);
524 }
525 /* append padding nibble in case of odd length */
526 if (i % 2)
527 *bcd_cur++ |= 0xf0;
528
529 /* return how many bytes we used */
530 return (bcd_cur - bcd_lv);
531}
532
Harald Welte0c389302009-06-10 12:08:54 +0800533/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800534static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800535 const u_int8_t *lv)
536{
537 u_int8_t in_len = lv[0];
538 int i, s;
539
540 if (in_len < 1)
541 return -EINVAL;
542
Harald Welte4bfdfe72009-06-10 23:11:52 +0800543 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800544
545 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800546 bcap->transfer = lv[1] & 0x07;
547 bcap->mode = (lv[1] & 0x08) >> 3;
548 bcap->coding = (lv[1] & 0x10) >> 4;
549 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800550
551 i = 1;
552 s = 0;
553 while(!(lv[i] & 0x80)) {
554 i++; /* octet 3a etc */
555 if (in_len < i)
556 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800557 bcap->speech_ver[s++] = lv[i] & 0x0f;
558 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800559 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800560 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800561 if (s == 7) /* maximum speech versions + end of list */
562 return 0;
563 }
564
565 return 0;
566}
567
568/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800569static int encode_bearer_cap(struct msgb *msg, int lv_only,
570 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800571{
572 u_int8_t lv[32 + 1];
573 int i, s;
574
Harald Welte4bfdfe72009-06-10 23:11:52 +0800575 lv[1] = bcap->transfer;
576 lv[1] |= bcap->mode << 3;
577 lv[1] |= bcap->coding << 4;
578 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800579
580 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800581 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800582 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800583 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800584 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800586 }
587 lv[i] |= 0x80; /* last IE of octet 3 etc */
588
589 lv[0] = i;
590 if (lv_only)
591 msgb_lv_put(msg, lv[0], lv+1);
592 else
593 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
594
595 return 0;
596}
597
598/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800599static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800600{
601 u_int8_t in_len = lv[0];
602
603 if (in_len < 1)
604 return -EINVAL;
605
606 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800607 ccap->dtmf = lv[1] & 0x01;
608 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800609
610 return 0;
611}
612
613/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800614static int decode_called(struct gsm_mncc_number *called,
615 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800616{
617 u_int8_t in_len = lv[0];
618
619 if (in_len < 1)
620 return -EINVAL;
621
622 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800623 called->plan = lv[1] & 0x0f;
624 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800625
626 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800627 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800628
629 return 0;
630}
631
632/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800633static int encode_called(struct msgb *msg,
634 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800635{
636 u_int8_t lv[18];
637 int ret;
638
639 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800640 lv[1] = called->plan;
641 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800642
643 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800644 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800645 if (ret < 0)
646 return ret;
647
648 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
649
650 return 0;
651}
652
653/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800654static int encode_callerid(struct msgb *msg, int ie,
655 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800656{
657 u_int8_t lv[13];
658 int h_len = 1;
659 int ret;
660
661 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800662 lv[1] = callerid->plan;
663 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800664
Harald Welte4bfdfe72009-06-10 23:11:52 +0800665 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800666 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800667 lv[2] = callerid->screen;
668 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800669 lv[2] |= 0x80;
670 h_len++;
671 } else
672 lv[1] |= 0x80;
673
674 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800675 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800676 if (ret < 0)
677 return ret;
678
679 msgb_tlv_put(msg, ie, lv[0], lv+1);
680
681 return 0;
682}
683
684/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800685static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800686 const u_int8_t *lv)
687{
688 u_int8_t in_len = lv[0];
689 int i;
690
691 if (in_len < 2)
692 return -EINVAL;
693
Harald Welte4bfdfe72009-06-10 23:11:52 +0800694 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800695
696 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800697 cause->location = lv[1] & 0x0f;
698 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800699
700 i = 1;
701 if (!(lv[i] & 0x80)) {
702 i++; /* octet 3a */
703 if (in_len < i+1)
704 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800705 cause->rec = 1;
706 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800707
708 }
709 i++;
710
711 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800712 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800713 i++;
714
715 if (in_len < i) /* no diag */
716 return 0;
717
718 if (in_len - (i-1) > 32) /* maximum 32 octets */
719 return 0;
720
721 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800722 memcpy(cause->diag, lv + i, in_len - (i-1));
723 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800724
725 return 0;
726}
727
728/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800729static int encode_cause(struct msgb *msg, int lv_only,
730 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800731{
732 u_int8_t lv[32+4];
733 int i;
734
Harald Welte4bfdfe72009-06-10 23:11:52 +0800735 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800736 return -EINVAL;
737
738 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800739 lv[1] = cause->location;
740 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800741
742 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800743 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800744 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800746 }
747 lv[i] |= 0x80; /* end of octet 3 */
748
749 /* octet 4 */
750 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800751 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800752
753 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800754 if (cause->diag_len) {
755 memcpy(lv + i, cause->diag, cause->diag_len);
756 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800757 }
758
759 lv[0] = i;
760 if (lv_only)
761 msgb_lv_put(msg, lv[0], lv+1);
762 else
763 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
764
765 return 0;
766}
767
768/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800769static int encode_calling(struct msgb *msg,
770 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800771{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800772 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800773}
774
775/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800776static int encode_connected(struct msgb *msg,
777 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800778{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800779 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800780}
781
782/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800783static int encode_redirecting(struct msgb *msg,
784 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800785{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800786 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800787}
788
789/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800790static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800791 const u_int8_t *lv)
792{
793 u_int8_t in_len = lv[0];
794
795 if (in_len < 1)
796 return -EINVAL;
797
Harald Welte4bfdfe72009-06-10 23:11:52 +0800798 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800799 return -EINVAL;
800
Harald Welte4bfdfe72009-06-10 23:11:52 +0800801 memcpy(facility->info, lv+1, in_len);
802 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800803
804 return 0;
805}
806
807/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800808static int encode_facility(struct msgb *msg, int lv_only,
809 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800810{
811 u_int8_t lv[GSM_MAX_FACILITY + 1];
812
Harald Welte4bfdfe72009-06-10 23:11:52 +0800813 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800814 return -EINVAL;
815
Harald Welte4bfdfe72009-06-10 23:11:52 +0800816 memcpy(lv+1, facility->info, facility->len);
817 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800818 if (lv_only)
819 msgb_lv_put(msg, lv[0], lv+1);
820 else
821 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
822
823 return 0;
824}
825
826/* decode 'notify' */
827static int decode_notify(int *notify, const u_int8_t *v)
828{
829 *notify = v[0] & 0x7f;
830
831 return 0;
832}
833
834/* encode 'notify' */
835static int encode_notify(struct msgb *msg, int notify)
836{
837 msgb_v_put(msg, notify | 0x80);
838
839 return 0;
840}
841
842/* encode 'signal' */
843static int encode_signal(struct msgb *msg, int signal)
844{
845 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
846
847 return 0;
848}
849
850/* decode 'keypad' */
851static int decode_keypad(int *keypad, const u_int8_t *lv)
852{
853 u_int8_t in_len = lv[0];
854
855 if (in_len < 1)
856 return -EINVAL;
857
858 *keypad = lv[1] & 0x7f;
859
860 return 0;
861}
862
863/* encode 'keypad' */
864static int encode_keypad(struct msgb *msg, int keypad)
865{
866 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
867
868 return 0;
869}
870
871/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800872static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800873 const u_int8_t *lv)
874{
875 u_int8_t in_len = lv[0];
876
877 if (in_len < 2)
878 return -EINVAL;
879
Harald Welte4bfdfe72009-06-10 23:11:52 +0800880 progress->coding = (lv[1] & 0x60) >> 5;
881 progress->location = lv[1] & 0x0f;
882 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800883
884 return 0;
885}
886
887/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800888static int encode_progress(struct msgb *msg, int lv_only,
889 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800890{
891 u_int8_t lv[3];
892
893 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800894 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
895 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800896 if (lv_only)
897 msgb_lv_put(msg, lv[0], lv+1);
898 else
899 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
900
901 return 0;
902}
903
904/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800905static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800906 const u_int8_t *lv)
907{
908 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800909 char *info = uu->info;
910 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800911 int i;
912
913 if (in_len < 1)
914 return -EINVAL;
915
Harald Welte4bfdfe72009-06-10 23:11:52 +0800916 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800917
918 for (i = 2; i <= in_len; i++) {
919 info_len--;
920 if (info_len <= 1)
921 break;
922 *info++ = lv[i];
923 }
924 if (info_len >= 1)
925 *info++ = '\0';
926
927 return 0;
928}
929
930/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800931static int encode_useruser(struct msgb *msg, int lv_only,
932 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800933{
934 u_int8_t lv[GSM_MAX_USERUSER + 2];
935
Harald Welte4bfdfe72009-06-10 23:11:52 +0800936 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800937 return -EINVAL;
938
Harald Welte4bfdfe72009-06-10 23:11:52 +0800939 lv[0] = 1 + strlen(uu->info);
940 lv[1] = uu->proto;
941 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800942 if (lv_only)
943 msgb_lv_put(msg, lv[0], lv+1);
944 else
945 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
946
947 return 0;
948}
949
950/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800951static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800952 const u_int8_t *lv)
953{
954 u_int8_t in_len = lv[0];
955
Harald Welte4bfdfe72009-06-10 23:11:52 +0800956 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800957 return -EINVAL;
958
Harald Welte4bfdfe72009-06-10 23:11:52 +0800959 memcpy(ssv->info, lv + 1, in_len);
960 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800961
962 return 0;
963}
964
965/* encode 'more data' */
966static int encode_more(struct msgb *msg)
967{
968 u_int8_t *ie;
969
970 ie = msgb_put(msg, 1);
971 ie[0] = GSM48_IE_MORE_DATA;
972
973 return 0;
974}
975
Holger Freyther819dd202009-01-04 03:52:50 +0000976struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000977{
978 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM);
979}
980
Holger Freyther3e2c3232009-01-04 03:55:31 +0000981int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000982{
Harald Welte65e74cc2008-12-29 01:55:35 +0000983 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800984 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000985 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000986
Harald Welte4bfdfe72009-06-10 23:11:52 +0800987 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
988 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
989 "Sending '%s' to MS.\n", msg->trx->bts->nr,
990 msg->trx->nr, msg->lchan->ts->nr,
991 gh->proto_discr & 0xf0,
992 cc_msg_names[gh->msg_type & 0x3f]);
993 else
994 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
995 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
996 msg->trx->nr, msg->lchan->ts->nr,
997 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +0000998 }
999
Harald Welte4b634542008-12-27 01:55:51 +00001000 msg->l3h = msg->data;
1001
Harald Welte8470bf22008-12-25 23:28:35 +00001002 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001003}
1004
Holger Freyther429e7762008-12-30 13:28:30 +00001005/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001006int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001007{
Harald Welte8470bf22008-12-25 23:28:35 +00001008 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001009 struct gsm48_hdr *gh;
1010
Harald Welte8470bf22008-12-25 23:28:35 +00001011 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001012
1013 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1014 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001015 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001016 gh->data[0] = cause;
1017
Harald Weltedb253af2008-12-30 17:56:55 +00001018 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1019
Harald Welte65e74cc2008-12-29 01:55:35 +00001020 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001021}
1022
1023/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001024int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001025{
Harald Welte8470bf22008-12-25 23:28:35 +00001026 struct gsm_bts *bts = lchan->ts->trx->bts;
1027 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001028 struct gsm48_hdr *gh;
1029 struct gsm48_loc_area_id *lai;
1030 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001031 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001032
Harald Welte8470bf22008-12-25 23:28:35 +00001033 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001034
1035 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1036 gh->proto_discr = GSM48_PDISC_MM;
1037 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1038
1039 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001040 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001041 bts->network->network_code, bts->location_area_code);
1042
1043 mid = msgb_put(msg, MID_TMSI_LEN);
1044 generate_mid_from_tmsi(mid, tmsi);
1045
1046 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1047
Harald Weltedb253af2008-12-30 17:56:55 +00001048 ret = gsm48_sendmsg(msg);
1049
Harald Weltedb253af2008-12-30 17:56:55 +00001050 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001051
Holger Freyther07cc8d82008-12-29 06:23:46 +00001052 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001053}
1054
Harald Weltefc977a82008-12-27 10:19:37 +00001055static char bcd2char(u_int8_t bcd)
1056{
1057 if (bcd < 0xa)
1058 return '0' + bcd;
1059 else
1060 return 'A' + (bcd - 0xa);
1061}
1062
Harald Weltebf5e8df2009-02-03 12:59:45 +00001063/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001064static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1065{
1066 int i;
1067 u_int8_t mi_type;
1068 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001069 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001070
1071 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1072
1073 switch (mi_type) {
1074 case GSM_MI_TYPE_NONE:
1075 break;
1076 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001077 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1078 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1079 memcpy(&tmsi, &mi[1], 4);
1080 tmsi = ntohl(tmsi);
1081 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001082 }
1083 break;
1084 case GSM_MI_TYPE_IMSI:
1085 case GSM_MI_TYPE_IMEI:
1086 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001087 *str_cur++ = bcd2char(mi[0] >> 4);
1088
1089 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001090 if (str_cur + 2 >= string + str_len)
1091 return str_cur - string;
1092 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001093 /* skip last nibble in last input byte when GSM_EVEN */
1094 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1095 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001096 }
1097 break;
1098 default:
1099 break;
1100 }
Harald Weltefc977a82008-12-27 10:19:37 +00001101 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001102
Harald Weltefc977a82008-12-27 10:19:37 +00001103 return str_cur - string;
1104}
1105
Harald Weltebf5e8df2009-02-03 12:59:45 +00001106/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001107static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1108{
1109 struct msgb *msg = gsm48_msgb_alloc();
1110 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001111
Harald Welte231ad4f2008-12-27 11:15:38 +00001112 msg->lchan = lchan;
1113
1114 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1115 gh->proto_discr = GSM48_PDISC_MM;
1116 gh->msg_type = GSM48_MT_MM_ID_REQ;
1117 gh->data[0] = id_type;
1118
Harald Welte65e74cc2008-12-29 01:55:35 +00001119 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001120}
1121
1122#define MI_SIZE 32
1123
Harald Weltebf5e8df2009-02-03 12:59:45 +00001124/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001125static int mm_rx_id_resp(struct msgb *msg)
1126{
1127 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001128 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001129 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1130 char mi_string[MI_SIZE];
1131
1132 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001133 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001134 mi_type, mi_string);
1135
Harald Welte75a983f2008-12-27 21:34:06 +00001136 switch (mi_type) {
1137 case GSM_MI_TYPE_IMSI:
1138 if (!lchan->subscr)
1139 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001140 if (lchan->loc_operation)
1141 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001142 break;
1143 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001144 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001145 /* update subscribe <-> IMEI mapping */
1146 if (lchan->subscr)
1147 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001148 if (lchan->loc_operation)
1149 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001150 break;
1151 }
Holger Freyther73487a22008-12-31 18:53:57 +00001152
1153 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001154 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001155}
1156
Harald Welte255539c2008-12-28 02:26:27 +00001157
1158static void loc_upd_rej_cb(void *data)
1159{
1160 struct gsm_lchan *lchan = data;
1161
Holger Freyther73487a22008-12-31 18:53:57 +00001162 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001163 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001164 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001165}
1166
Holger Freytherb7193e42008-12-29 17:44:08 +00001167static void schedule_reject(struct gsm_lchan *lchan)
1168{
Holger Freyther73487a22008-12-31 18:53:57 +00001169 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1170 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001171 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001172}
1173
Harald Welte2a139372009-02-22 21:14:55 +00001174static const char *lupd_name(u_int8_t type)
1175{
1176 switch (type) {
1177 case GSM48_LUPD_NORMAL:
1178 return "NORMAL";
1179 case GSM48_LUPD_PERIODIC:
1180 return "PEROIDOC";
1181 case GSM48_LUPD_IMSI_ATT:
1182 return "IMSI ATTACH";
1183 default:
1184 return "UNKNOWN";
1185 }
1186}
1187
Harald Welte231ad4f2008-12-27 11:15:38 +00001188#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001189/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001190static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001191{
Harald Welte8470bf22008-12-25 23:28:35 +00001192 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001193 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001194 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001195 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001196 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001197 char mi_string[MI_SIZE];
1198 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001199
Harald Welte8470bf22008-12-25 23:28:35 +00001200 lu = (struct gsm48_loc_upd_req *) gh->data;
1201
1202 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001203
Harald Weltefc977a82008-12-27 10:19:37 +00001204 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1205
Holger Freyther79f4ae62009-06-02 03:25:04 +00001206 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001207 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001208
Holger Freythereaf04692009-06-06 13:54:44 +00001209 /*
1210 * Pseudo Spoof detection: Just drop a second/concurrent
1211 * location updating request.
1212 */
1213 if (lchan->loc_operation) {
1214 DEBUGP(DMM, "LUPDREQ: ignoring request due an existing one: %p.\n",
1215 lchan->loc_operation);
1216 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1217 return 0;
1218 }
1219
Holger Freyther73487a22008-12-31 18:53:57 +00001220 allocate_loc_updating_req(lchan);
1221
Harald Welte52b1f982008-12-23 20:25:15 +00001222 switch (mi_type) {
1223 case GSM_MI_TYPE_IMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001224 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001225 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001226 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001227 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001228
Harald Welte52b1f982008-12-23 20:25:15 +00001229 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001230 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001231 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001232 case GSM_MI_TYPE_TMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001233 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001234 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001235 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001236 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001237
Harald Welte52b1f982008-12-23 20:25:15 +00001238 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001239 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001240 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001241 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001242 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001243 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001244 }
1245 break;
1246 case GSM_MI_TYPE_IMEI:
1247 case GSM_MI_TYPE_IMEISV:
1248 /* no sim card... FIXME: what to do ? */
Harald Welte2a139372009-02-22 21:14:55 +00001249 DEBUGP(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001250 break;
1251 default:
Harald Welte2a139372009-02-22 21:14:55 +00001252 DEBUGP(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001253 break;
1254 }
1255
Harald Welte4bfdfe72009-06-10 23:11:52 +08001256 if (!subscr) {
1257 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1258 /* FIXME: request id? close channel? */
1259 return -EINVAL;
1260 }
1261
Harald Welte255539c2008-12-28 02:26:27 +00001262 lchan->subscr = subscr;
1263
Holger Freyther73487a22008-12-31 18:53:57 +00001264 /*
1265 * Schedule the reject timer and check if we can let the
1266 * subscriber into our network immediately or if we need to wait
1267 * for identity responses.
1268 */
1269 schedule_reject(lchan);
Holger Freytherd51524f2009-06-09 08:27:07 +00001270 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001271}
1272
Harald Welte7584aea2009-02-11 11:44:12 +00001273/* 9.1.5 Channel mode modify */
1274int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1275{
1276 struct msgb *msg = gsm48_msgb_alloc();
1277 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1278 struct gsm48_chan_mode_modify *cmm =
1279 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001280 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001281
Harald Welte4a543e82009-02-28 13:17:55 +00001282 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001283
Harald Welte45b407a2009-05-23 15:51:12 +00001284 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001285 msg->lchan = lchan;
1286 gh->proto_discr = GSM48_PDISC_RR;
1287 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1288
1289 /* fill the channel information element, this code
1290 * should probably be shared with rsl_rx_chan_rqd() */
1291 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001292 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001293 cmm->chan_desc.h0.h = 0;
1294 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1295 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1296 cmm->mode = mode;
1297
1298 return gsm48_sendmsg(msg);
1299}
1300
Harald Welte4bfdfe72009-06-10 23:11:52 +08001301#if 0
1302static u_int8_t to_bcd8(u_int8_t val)
1303{
1304 return ((val / 10) << 4) | (val % 10);
1305}
1306#endif
1307
Harald Weltedb253af2008-12-30 17:56:55 +00001308/* Section 9.2.15a */
1309int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1310{
1311 struct msgb *msg = gsm48_msgb_alloc();
1312 struct gsm48_hdr *gh;
1313 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001314 u_int8_t *ptr8;
1315 u_int16_t *ptr16;
1316 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001317 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001318#if 0
1319 time_t cur_t;
1320 struct tm* cur_time;
1321 int tz15min;
1322#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001323
1324 msg->lchan = lchan;
1325
1326 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1327 gh->proto_discr = GSM48_PDISC_MM;
1328 gh->msg_type = GSM48_MT_MM_INFO;
1329
1330 if (net->name_long) {
1331 name_len = strlen(net->name_long);
1332 /* 10.5.3.5a */
1333 ptr8 = msgb_put(msg, 3);
1334 ptr8[0] = GSM48_IE_NAME_LONG;
1335 ptr8[1] = name_len*2 +1;
1336 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1337
1338 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1339 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001340 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001341
1342 /* FIXME: Use Cell Broadcast, not UCS-2, since
1343 * UCS-2 is only supported by later revisions of the spec */
1344 }
1345
1346 if (net->name_short) {
1347 name_len = strlen(net->name_short);
1348 /* 10.5.3.5a */
1349 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1350 ptr8[0] = GSM48_IE_NAME_LONG;
1351 ptr8[1] = name_len*2 + 1;
1352 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1353
Harald Weltee872cb12009-01-01 00:33:37 +00001354 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001355 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001356 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001357 }
1358
1359#if 0
1360 /* Section 10.5.3.9 */
1361 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001362 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001363 ptr8 = msgb_put(msg, 8);
1364 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1365 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1366 ptr8[2] = to_bcd8(cur_time->tm_mon);
1367 ptr8[3] = to_bcd8(cur_time->tm_mday);
1368 ptr8[4] = to_bcd8(cur_time->tm_hour);
1369 ptr8[5] = to_bcd8(cur_time->tm_min);
1370 ptr8[6] = to_bcd8(cur_time->tm_sec);
1371 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1372 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001373 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001374 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001375 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001376#endif
1377
1378 return gsm48_sendmsg(msg);
1379}
1380
Harald Welte4b634542008-12-27 01:55:51 +00001381static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1382{
Harald Welte4b634542008-12-27 01:55:51 +00001383 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001384 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001385}
Harald Welteba4cf162009-01-10 01:49:35 +00001386
1387/* 9.2.6 CM service reject */
1388static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1389 enum gsm48_reject_value value)
1390{
1391 struct msgb *msg = gsm48_msgb_alloc();
1392 struct gsm48_hdr *gh;
1393
1394 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1395
1396 msg->lchan = lchan;
1397 use_lchan(lchan);
1398
1399 gh->proto_discr = GSM48_PDISC_MM;
1400 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1401 gh->data[0] = value;
1402 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1403
1404 return gsm48_sendmsg(msg);
1405}
1406
Harald Welte4ed0e922009-01-10 03:17:30 +00001407
1408/*
1409 * Handle CM Service Requests
1410 * a) Verify that the packet is long enough to contain the information
1411 * we require otherwsie reject with INCORRECT_MESSAGE
1412 * b) Try to parse the TMSI. If we do not have one reject
1413 * c) Check that we know the subscriber with the TMSI otherwise reject
1414 * with a HLR cause
1415 * d) Set the subscriber on the gsm_lchan and accept
1416 */
Harald Welte4b634542008-12-27 01:55:51 +00001417static int gsm48_rx_mm_serv_req(struct msgb *msg)
1418{
Harald Welteba4cf162009-01-10 01:49:35 +00001419 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001420 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001421
Harald Welteba4cf162009-01-10 01:49:35 +00001422 struct gsm_subscriber *subscr;
1423 struct gsm48_hdr *gh = msgb_l3(msg);
1424 struct gsm48_service_request *req =
1425 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001426 /* unfortunately in Phase1 the classmar2 length is variable */
1427 u_int8_t classmark2_len = gh->data[1];
1428 u_int8_t *classmark2 = gh->data+2;
1429 u_int8_t mi_len = *(classmark2 + classmark2_len);
1430 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001431
Harald Weltec9e02182009-05-01 19:07:53 +00001432 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001433 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001434 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001435 return gsm48_tx_mm_serv_rej(msg->lchan,
1436 GSM48_REJECT_INCORRECT_MESSAGE);
1437 }
1438
1439 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001440 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001441 return gsm48_tx_mm_serv_rej(msg->lchan,
1442 GSM48_REJECT_INCORRECT_MESSAGE);
1443 }
1444
Harald Weltec9e02182009-05-01 19:07:53 +00001445 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001446 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001447 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001448 return gsm48_tx_mm_serv_rej(msg->lchan,
1449 GSM48_REJECT_INCORRECT_MESSAGE);
1450 }
1451
Harald Weltec9e02182009-05-01 19:07:53 +00001452 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001453 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001454 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001455
Holger Freythereb443982009-06-04 13:58:42 +00001456 subscr = subscr_get_by_tmsi(mi_string);
1457
Harald Welte2a139372009-02-22 21:14:55 +00001458 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001459 if (!subscr)
1460 return gsm48_tx_mm_serv_rej(msg->lchan,
1461 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1462
1463 if (!msg->lchan->subscr)
1464 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001465 else if (msg->lchan->subscr != subscr) {
1466 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1467 subscr_put(subscr);
1468 }
1469
Harald Weltef7c43522009-06-09 20:24:21 +00001470 subscr->classmark2_len = classmark2_len;
1471 memcpy(subscr->classmark2, classmark2, classmark2_len);
1472
Harald Welte4b634542008-12-27 01:55:51 +00001473 return gsm48_tx_mm_serv_ack(msg->lchan);
1474}
1475
Harald Welte2a139372009-02-22 21:14:55 +00001476static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1477{
1478 struct gsm48_hdr *gh = msgb_l3(msg);
1479 struct gsm48_imsi_detach_ind *idi =
1480 (struct gsm48_imsi_detach_ind *) gh->data;
1481 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1482 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001483 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001484
1485 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1486 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1487 mi_type, mi_string);
1488
1489 switch (mi_type) {
1490 case GSM_MI_TYPE_TMSI:
1491 subscr = subscr_get_by_tmsi(mi_string);
1492 break;
1493 case GSM_MI_TYPE_IMSI:
1494 subscr = subscr_get_by_imsi(mi_string);
1495 break;
1496 case GSM_MI_TYPE_IMEI:
1497 case GSM_MI_TYPE_IMEISV:
1498 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001499 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001500 break;
1501 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001502 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001503 break;
1504 }
1505
Holger Freyther4a49e772009-04-12 05:37:29 +00001506 if (subscr) {
1507 subscr_update(subscr, msg->trx->bts,
1508 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001509 DEBUGP(DMM, "Subscriber: %s\n",
1510 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001511 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001512 } else
Harald Welte2a139372009-02-22 21:14:55 +00001513 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1514
Harald Welte2a139372009-02-22 21:14:55 +00001515 return 0;
1516}
1517
Harald Welted2a7f5a2009-06-05 20:08:20 +00001518static int gsm48_rx_mm_status(struct msgb *msg)
1519{
1520 struct gsm48_hdr *gh = msgb_l3(msg);
1521
1522 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1523
1524 return 0;
1525}
1526
Harald Weltebf5e8df2009-02-03 12:59:45 +00001527/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001528static int gsm0408_rcv_mm(struct msgb *msg)
1529{
1530 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001531 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001532
1533 switch (gh->msg_type & 0xbf) {
1534 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +00001535 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001536 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001537 break;
1538 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001539 rc = mm_rx_id_resp(msg);
1540 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001541 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001542 rc = gsm48_rx_mm_serv_req(msg);
1543 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001544 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001545 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001546 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001547 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001548 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1549 msg->lchan->subscr ?
1550 msg->lchan->subscr->imsi :
1551 "unknown subscriber");
1552 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001553 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001554 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1555 break;
1556 case GSM48_MT_MM_CM_REEST_REQ:
1557 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1558 break;
1559 case GSM48_MT_MM_AUTH_RESP:
1560 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001561 break;
1562 default:
1563 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1564 gh->msg_type);
1565 break;
1566 }
1567
1568 return rc;
1569}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001570
Harald Welte2d35ae62009-02-06 12:02:13 +00001571/* Receive a PAGING RESPONSE message from the MS */
1572static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1573{
1574 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001575 u_int8_t *classmark2_lv = gh->data + 1;
1576 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1577 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001578 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001579 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001580 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001581 int rc = 0;
1582
Harald Welte61548982009-02-22 21:26:29 +00001583 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001584 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1585 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001586 switch (mi_type) {
1587 case GSM_MI_TYPE_TMSI:
1588 subscr = subscr_get_by_tmsi(mi_string);
1589 break;
1590 case GSM_MI_TYPE_IMSI:
1591 subscr = subscr_get_by_imsi(mi_string);
1592 break;
1593 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001594
1595 if (!subscr) {
1596 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001597 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001598 return -EINVAL;
1599 }
1600 DEBUGP(DRR, "<- Channel was requested by %s\n",
1601 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001602
Harald Weltef7c43522009-06-09 20:24:21 +00001603 subscr->classmark2_len = *classmark2_lv;
1604 memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv);
1605
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001606 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001607 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001608 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001609 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1610 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001611 return -EINVAL;
1612 } else {
1613 DEBUGP(DRR, "<- Channel already owned by us\n");
1614 subscr_put(subscr);
1615 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001616 }
1617
Harald Welte595ad7b2009-02-16 22:05:44 +00001618 sig_data.subscr = subscr;
1619 sig_data.bts = msg->lchan->ts->trx->bts;
1620 sig_data.lchan = msg->lchan;
1621
1622 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001623
1624 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001625 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001626
Harald Welte7584aea2009-02-11 11:44:12 +00001627 /* FIXME: somehow signal the completion of the PAGING to
1628 * the entity that requested the paging */
1629
Harald Welte2d35ae62009-02-06 12:02:13 +00001630 return rc;
1631}
1632
Harald Weltef7c43522009-06-09 20:24:21 +00001633static int gsm48_rx_rr_classmark(struct msgb *msg)
1634{
1635 struct gsm48_hdr *gh = msgb_l3(msg);
1636 struct gsm_subscriber *subscr = msg->lchan->subscr;
1637 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1638 u_int8_t cm2_len, cm3_len = 0;
1639 u_int8_t *cm2, *cm3 = NULL;
1640
1641 DEBUGP(DRR, "CLASSMARK CHANGE ");
1642
1643 /* classmark 2 */
1644 cm2_len = gh->data[0];
1645 cm2 = &gh->data[1];
1646 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1647
1648 if (payload_len > cm2_len + 1) {
1649 /* we must have a classmark3 */
1650 if (gh->data[cm2_len+1] != 0x20) {
1651 DEBUGPC(DRR, "ERR CM3 TAG\n");
1652 return -EINVAL;
1653 }
1654 if (cm2_len > 3) {
1655 DEBUGPC(DRR, "CM2 too long!\n");
1656 return -EINVAL;
1657 }
1658
1659 cm3_len = gh->data[cm2_len+2];
1660 cm3 = &gh->data[cm2_len+3];
1661 if (cm3_len > 14) {
1662 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1663 return -EINVAL;
1664 }
1665 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1666 }
1667 if (subscr) {
1668 subscr->classmark2_len = cm2_len;
1669 memcpy(subscr->classmark2, cm2, cm2_len);
1670 if (cm3) {
1671 subscr->classmark3_len = cm3_len;
1672 memcpy(subscr->classmark3, cm3, cm3_len);
1673 }
1674 }
1675
1676 /* FIXME: store the classmark2/3 values with the equipment register */
1677
1678 return 0;
1679}
1680
Harald Weltecf5b3592009-05-01 18:28:42 +00001681static int gsm48_rx_rr_status(struct msgb *msg)
1682{
1683 struct gsm48_hdr *gh = msgb_l3(msg);
1684
1685 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1686 rr_cause_name(gh->data[0]));
1687
1688 return 0;
1689}
1690
Harald Weltef7c43522009-06-09 20:24:21 +00001691static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1692{
1693 struct gsm48_hdr *gh = msgb_l3(msg);
1694 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1695 static struct gsm_meas_rep meas_rep;
1696
1697 DEBUGP(DRR, "MEASUREMENT REPORT ");
1698 parse_meas_rep(&meas_rep, gh->data, payload_len);
1699 if (meas_rep.flags & MEAS_REP_F_DTX)
1700 DEBUGPC(DRR, "DTX ");
1701 if (meas_rep.flags & MEAS_REP_F_BA1)
1702 DEBUGPC(DRR, "BA1 ");
1703 if (!(meas_rep.flags & MEAS_REP_F_VALID))
1704 DEBUGPC(DRR, "NOT VALID ");
1705 else
1706 DEBUGPC(DRR, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
1707 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1708 meas_rep.rxqual_sub);
1709
1710 DEBUGPC(DRR, "NUM_NEIGH=%u\n", meas_rep.num_cell);
1711
1712 /* FIXME: put the results somwhere */
1713
1714 return 0;
1715}
1716
Harald Weltebf5e8df2009-02-03 12:59:45 +00001717/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001718static int gsm0408_rcv_rr(struct msgb *msg)
1719{
1720 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001721 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001722
1723 switch (gh->msg_type) {
1724 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001725 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001726 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001727 case GSM48_MT_RR_GPRS_SUSP_REQ:
1728 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1729 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001730 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001731 rc = gsm48_rr_rx_pag_resp(msg);
1732 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001733 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1734 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001735 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001736 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001737 case GSM48_MT_RR_STATUS:
1738 rc = gsm48_rx_rr_status(msg);
1739 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001740 case GSM48_MT_RR_MEAS_REP:
1741 rc = gsm48_rx_rr_meas_rep(msg);
1742 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001743 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001744 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001745 gh->msg_type);
1746 break;
1747 }
1748
Harald Welte2d35ae62009-02-06 12:02:13 +00001749 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001750}
1751
Holger Freythere64a7a32009-02-06 21:55:37 +00001752/* 7.1.7 and 9.1.7 Channel release*/
1753int gsm48_send_rr_release(struct gsm_lchan *lchan)
1754{
1755 struct msgb *msg = gsm48_msgb_alloc();
1756 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1757 u_int8_t *cause;
1758
1759 msg->lchan = lchan;
1760 gh->proto_discr = GSM48_PDISC_RR;
1761 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1762
1763 cause = msgb_put(msg, 1);
1764 cause[0] = GSM48_RR_CAUSE_NORMAL;
1765
1766 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1767 lchan->nr, lchan->type);
1768
1769 return gsm48_sendmsg(msg);
1770}
1771
Harald Welte4bc90a12008-12-27 16:32:52 +00001772/* Call Control */
1773
Harald Welte7584aea2009-02-11 11:44:12 +00001774/* The entire call control code is written in accordance with Figure 7.10c
1775 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1776 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1777 * it for voice */
1778
Harald Welte4bfdfe72009-06-10 23:11:52 +08001779static void new_cc_state(struct gsm_trans *trans, int state)
1780{
1781 if (state > 31 || state < 0)
1782 return;
1783
1784 DEBUGP(DCC, "new state %s -> %s\n",
1785 cc_state_names[trans->state], cc_state_names[state]);
1786
1787 trans->state = state;
1788}
1789
1790static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001791{
1792 struct msgb *msg = gsm48_msgb_alloc();
1793 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1794 u_int8_t *cause, *call_state;
1795
Harald Welte4bfdfe72009-06-10 23:11:52 +08001796 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1797 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001798 gh->msg_type = GSM48_MT_CC_STATUS;
1799
1800 cause = msgb_put(msg, 3);
1801 cause[0] = 2;
1802 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1803 cause[2] = 0x80 | 30; /* response to status inquiry */
1804
1805 call_state = msgb_put(msg, 1);
1806 call_state[0] = 0xc0 | 0x00;
1807
Harald Welte65e74cc2008-12-29 01:55:35 +00001808 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001809}
1810
Harald Welte6f4b7532008-12-29 00:39:37 +00001811static int gsm48_tx_simple(struct gsm_lchan *lchan,
1812 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001813{
1814 struct msgb *msg = gsm48_msgb_alloc();
1815 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1816
1817 msg->lchan = lchan;
1818
Harald Welte6f4b7532008-12-29 00:39:37 +00001819 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001820 gh->msg_type = msg_type;
1821
Harald Welte65e74cc2008-12-29 01:55:35 +00001822 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001823}
1824
Harald Welte4bfdfe72009-06-10 23:11:52 +08001825static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1826{
1827 if (bsc_timer_pending(&trans->cc_timer)) {
1828 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1829 bsc_del_timer(&trans->cc_timer);
1830 trans->Tcurrent = 0;
1831 }
1832}
1833
1834static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1835 int msg_type, struct gsm_mncc *mncc)
1836{
1837 struct msgb *msg;
1838
1839 if (trans)
1840 if (trans->lchan)
1841 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1842 "Sending '%s' to MNCC.\n",
1843 trans->lchan->ts->trx->bts->nr,
1844 trans->lchan->ts->trx->nr,
1845 trans->lchan->ts->nr, trans->transaction_id,
1846 (trans->subscr)?(trans->subscr->extension):"-",
1847 get_mncc_name(msg_type));
1848 else
1849 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1850 "Sending '%s' to MNCC.\n",
1851 (trans->subscr)?(trans->subscr->extension):"-",
1852 get_mncc_name(msg_type));
1853 else
1854 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1855 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1856
1857 mncc->msg_type = msg_type;
1858
1859 msg = msgb_alloc(sizeof(struct gsm_mncc));
1860 if (!msg)
1861 return -ENOMEM;
1862 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1863 msgb_enqueue(&net->upqueue, msg);
1864
1865 return 0;
1866}
1867
1868int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1869 u_int32_t callref, int location, int value)
1870{
1871 struct gsm_mncc rel;
1872
Harald Welte92f70c52009-06-12 01:54:08 +08001873 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001874 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001875 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001876 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1877}
1878
1879void free_trans(struct gsm_trans *trans)
1880{
1881 struct gsm_bts *bts;
1882
1883 gsm48_stop_cc_timer(trans);
1884
1885 /* send release to L4, if callref still exists */
1886 if (trans->callref) {
1887 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001888 mncc_release_ind(trans->network, trans, trans->callref,
1889 GSM48_CAUSE_LOC_PRN_S_LU,
1890 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001891 if (trans->state != GSM_CSTATE_NULL)
1892 new_cc_state(trans, GSM_CSTATE_NULL);
1893 }
1894
1895 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1896 /* Stop paging on all bts' */
1897 bts = NULL;
1898 do {
1899 bts = gsm_bts_by_lac(trans->subscr->net,
1900 trans->subscr->lac, bts);
1901 if (!bts)
1902 break;
1903 /* Stop paging */
1904 paging_request_stop(bts, trans->subscr, NULL);
1905 } while (1);
1906 }
1907
1908 if (trans->lchan) {
1909 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1910 put_lchan(trans->lchan);
1911 }
1912
1913 if (trans->subscr)
1914 subscr_put(trans->subscr);
1915
1916 if (trans->state != GSM_CSTATE_NULL)
1917 new_cc_state(trans, GSM_CSTATE_NULL);
1918
1919 llist_del(&trans->entry);
1920
Harald Welte2cf161b2009-06-20 22:36:41 +02001921 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001922}
1923
1924static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1925
Harald Welte09e38af2009-02-16 22:52:23 +00001926/* call-back from paging the B-end of the connection */
1927static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001928 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001929{
Harald Welte7ccf7782009-02-17 01:43:01 +00001930 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001931 struct gsm_subscriber *subscr = param;
1932 struct gsm_trans *transt, *tmp;
1933 struct gsm_network *net;
1934
Harald Welte09e38af2009-02-16 22:52:23 +00001935 if (hooknum != GSM_HOOK_RR_PAGING)
1936 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001937
1938 if (!subscr)
1939 return -EINVAL;
1940 net = subscr->net;
1941 if (!net) {
1942 DEBUGP(DCC, "Error Network not set!\n");
1943 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001944 }
Harald Welte7584aea2009-02-11 11:44:12 +00001945
Harald Welte4bfdfe72009-06-10 23:11:52 +08001946 /* check all tranactions (without lchan) for subscriber */
1947 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1948 if (transt->subscr != subscr || transt->lchan)
1949 continue;
1950 switch (event) {
1951 case GSM_PAGING_SUCCEEDED:
1952 if (!lchan) // paranoid
1953 break;
1954 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1955 subscr->extension);
1956 /* Assign lchan */
1957 if (!transt->lchan) {
1958 transt->lchan = lchan;
1959 use_lchan(lchan);
1960 }
1961 /* send SETUP request to called party */
1962 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1963 if (is_ipaccess_bts(lchan->ts->trx->bts))
1964 rsl_ipacc_bind(lchan);
1965 break;
1966 case GSM_PAGING_EXPIRED:
1967 DEBUGP(DCC, "Paging subscr %s expired!\n",
1968 subscr->extension);
1969 /* Temporarily out of order */
1970 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001971 GSM48_CAUSE_LOC_PRN_S_LU,
1972 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001973 transt->callref = 0;
1974 free_trans(transt);
1975 break;
1976 }
1977 }
Harald Welte09e38af2009-02-16 22:52:23 +00001978 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001979}
Harald Welte7584aea2009-02-11 11:44:12 +00001980
Harald Welte49f48b82009-02-17 15:29:33 +00001981/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001982static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001983{
Harald Welte11fa29c2009-02-19 17:24:39 +00001984 struct gsm_bts *bts = lchan->ts->trx->bts;
1985 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001986 struct gsm_bts_trx_ts *ts;
1987
Harald Welte11fa29c2009-02-19 17:24:39 +00001988 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1989 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1990 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1991
1992 if (bts->type != remote_bts->type) {
1993 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1994 return -EINVAL;
1995 }
Harald Welte49f48b82009-02-17 15:29:33 +00001996
Harald Welte11fa29c2009-02-19 17:24:39 +00001997 switch (bts->type) {
1998 case GSM_BTS_TYPE_NANOBTS_900:
1999 case GSM_BTS_TYPE_NANOBTS_1800:
2000 ts = remote_lchan->ts;
2001 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2002 lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2003
2004 ts = lchan->ts;
2005 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2006 remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2007 break;
2008 case GSM_BTS_TYPE_BS11:
2009 trau_mux_map_lchan(lchan, remote_lchan);
2010 break;
2011 default:
2012 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2013 break;
2014 }
Harald Welte49f48b82009-02-17 15:29:33 +00002015
2016 return 0;
2017}
2018
Harald Welte4bfdfe72009-06-10 23:11:52 +08002019static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002020{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002021 struct gsm_trans *trans;
2022 llist_for_each_entry(trans, &net->trans_list, entry) {
2023 if (trans->callref == callref)
2024 return trans;
2025 }
2026 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002027}
2028
Harald Welte4bfdfe72009-06-10 23:11:52 +08002029/* bridge channels of two transactions */
2030static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002031{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002032 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2033 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002034
Harald Welte4bfdfe72009-06-10 23:11:52 +08002035 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002036 return -EIO;
2037
Harald Welte4bfdfe72009-06-10 23:11:52 +08002038 if (!trans1->lchan || !trans2->lchan)
2039 return -EIO;
2040
2041 /* through-connect channel */
2042 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002043}
2044
Harald Welte4bfdfe72009-06-10 23:11:52 +08002045/* enable receive of channels to upqueue */
2046static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2047{
2048 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002049
Harald Welte4bfdfe72009-06-10 23:11:52 +08002050 /* Find callref */
2051 trans = get_trans_ref(net, data->callref);
2052 if (!trans)
2053 return -EIO;
2054 if (!trans->lchan)
2055 return 0;
2056
2057 // todo IPACCESS
2058 if (enable)
2059 return trau_recv_lchan(trans->lchan, data->callref);
2060 return trau_mux_unmap(NULL, data->callref);
2061}
2062
2063/* send a frame to channel */
2064static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2065{
2066 struct gsm_trans *trans;
2067
2068 /* Find callref */
2069 trans = get_trans_ref(net, frame->callref);
2070 if (!trans)
2071 return -EIO;
2072 if (!trans->lchan)
2073 return 0;
2074 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2075 trans->lchan->type != GSM_LCHAN_TCH_H)
2076 return 0;
2077
2078 // todo IPACCESS
2079 return trau_send_lchan(trans->lchan,
2080 (struct decoded_trau_frame *)frame->data);
2081}
2082
2083
2084static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2085{
2086 DEBUGP(DCC, "-> STATUS ENQ\n");
2087 return gsm48_cc_tx_status(trans, msg);
2088}
2089
2090static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2091static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2092
2093static void gsm48_cc_timeout(void *arg)
2094{
2095 struct gsm_trans *trans = arg;
2096 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002097 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2098 int mo_location = GSM48_CAUSE_LOC_USER;
2099 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2100 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002101 struct gsm_mncc mo_rel, l4_rel;
2102
2103 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2104 mo_rel.callref = trans->callref;
2105 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2106 l4_rel.callref = trans->callref;
2107
2108 switch(trans->Tcurrent) {
2109 case 0x303:
2110 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002111 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002112 break;
2113 case 0x310:
2114 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002115 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002116 break;
2117 case 0x313:
2118 disconnect = 1;
2119 /* unknown, did not find it in the specs */
2120 break;
2121 case 0x301:
2122 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002123 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002124 break;
2125 case 0x308:
2126 if (!trans->T308_second) {
2127 /* restart T308 a second time */
2128 gsm48_cc_tx_release(trans, &trans->cc_msg);
2129 trans->T308_second = 1;
2130 break; /* stay in release state */
2131 }
2132 free_trans(trans);
2133 return;
2134// release = 1;
2135// l4_cause = 14;
2136// break;
2137 case 0x306:
2138 release = 1;
2139 mo_cause = trans->cc_msg.cause.value;
2140 mo_location = trans->cc_msg.cause.location;
2141 break;
2142 case 0x323:
2143 disconnect = 1;
2144 break;
2145 default:
2146 release = 1;
2147 }
2148
2149 if (release && trans->callref) {
2150 /* process release towards layer 4 */
2151 mncc_release_ind(trans->network, trans, trans->callref,
2152 l4_location, l4_cause);
2153 trans->callref = 0;
2154 }
2155
2156 if (disconnect && trans->callref) {
2157 /* process disconnect towards layer 4 */
2158 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2159 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2160 }
2161
2162 /* process disconnect towards mobile station */
2163 if (disconnect || release) {
2164 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2165 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2166 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2167 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2168 mo_rel.cause.diag_len = 3;
2169
2170 if (disconnect)
2171 gsm48_cc_tx_disconnect(trans, &mo_rel);
2172 if (release)
2173 gsm48_cc_tx_release(trans, &mo_rel);
2174 }
2175
2176}
2177
2178static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2179 int sec, int micro)
2180{
2181 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2182 trans->cc_timer.cb = gsm48_cc_timeout;
2183 trans->cc_timer.data = trans;
2184 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2185 trans->Tcurrent = current;
2186}
2187
2188static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2189{
2190 struct gsm48_hdr *gh = msgb_l3(msg);
2191 u_int8_t msg_type = gh->msg_type & 0xbf;
2192 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2193 struct tlv_parsed tp;
2194 struct gsm_mncc setup;
2195
2196 memset(&setup, 0, sizeof(struct gsm_mncc));
2197 setup.callref = trans->callref;
2198 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2199 /* emergency setup is identified by msg_type */
2200 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2201 setup.emergency = 1;
2202
2203 /* use subscriber as calling party number */
2204 if (trans->subscr) {
2205 setup.fields |= MNCC_F_CALLING;
2206 strncpy(setup.calling.number, trans->subscr->extension,
2207 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002208 strncpy(setup.imsi, trans->subscr->imsi,
2209 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002210 }
2211 /* bearer capability */
2212 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2213 setup.fields |= MNCC_F_BEARER_CAP;
2214 decode_bearer_cap(&setup.bearer_cap,
2215 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2216 }
2217 /* facility */
2218 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2219 setup.fields |= MNCC_F_FACILITY;
2220 decode_facility(&setup.facility,
2221 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2222 }
2223 /* called party bcd number */
2224 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2225 setup.fields |= MNCC_F_CALLED;
2226 decode_called(&setup.called,
2227 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2228 }
2229 /* user-user */
2230 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2231 setup.fields |= MNCC_F_USERUSER;
2232 decode_useruser(&setup.useruser,
2233 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2234 }
2235 /* ss-version */
2236 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2237 setup.fields |= MNCC_F_SSVERSION;
2238 decode_ssversion(&setup.ssversion,
2239 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2240 }
2241 /* CLIR suppression */
2242 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2243 setup.clir.sup = 1;
2244 /* CLIR invocation */
2245 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2246 setup.clir.inv = 1;
2247 /* cc cap */
2248 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2249 setup.fields |= MNCC_F_CCCAP;
2250 decode_cccap(&setup.cccap,
2251 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2252 }
2253
2254 if (is_ipaccess_bts(msg->trx->bts))
2255 rsl_ipacc_bind(msg->lchan);
2256
2257 new_cc_state(trans, GSM_CSTATE_INITIATED);
2258
2259 /* indicate setup to MNCC */
2260 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2261
2262 return 0;
2263}
2264
2265static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002266{
2267 struct msgb *msg = gsm48_msgb_alloc();
2268 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002269 struct gsm_mncc *setup = arg;
2270 struct gsm_trans *transt;
2271 u_int16_t trans_id_mask = 0;
2272 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002273
Harald Welte7ccf7782009-02-17 01:43:01 +00002274 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002275
Harald Welte4bfdfe72009-06-10 23:11:52 +08002276 /* transaction id must not be assigned */
2277 if (trans->transaction_id != 0xff) { /* unasssigned */
2278 DEBUGP(DCC, "TX Setup with assigned transaction. "
2279 "This is not allowed!\n");
2280 /* Temporarily out of order */
2281 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002282 GSM48_CAUSE_LOC_PRN_S_LU,
2283 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002284 trans->callref = 0;
2285 free_trans(trans);
2286 return rc;
2287 }
2288
2289 /* Get free transaction_id */
2290 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2291 /* Transaction of our lchan? */
2292 if (transt->lchan == trans->lchan &&
2293 transt->transaction_id != 0xff)
2294 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2295 }
2296 /* Assign free transaction ID */
2297 if ((trans_id_mask & 0x007f) == 0x7f) {
2298 /* no free transaction ID */
2299 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002300 GSM48_CAUSE_LOC_PRN_S_LU,
2301 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002302 trans->callref = 0;
2303 free_trans(trans);
2304 return rc;
2305 }
2306 for (i = 0; i < 7; i++) {
2307 if ((trans_id_mask & (1 << i)) == 0) {
2308 trans->transaction_id = i << 4; /* flag = 0 */
2309 break;
2310 }
2311 }
Harald Welte49f48b82009-02-17 15:29:33 +00002312
Harald Welte4bfdfe72009-06-10 23:11:52 +08002313 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2314 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002315 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002316
Harald Welte4bfdfe72009-06-10 23:11:52 +08002317 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002318
Harald Welte4bfdfe72009-06-10 23:11:52 +08002319 /* bearer capability */
2320 if (setup->fields & MNCC_F_BEARER_CAP)
2321 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2322 /* facility */
2323 if (setup->fields & MNCC_F_FACILITY)
2324 encode_facility(msg, 0, &setup->facility);
2325 /* progress */
2326 if (setup->fields & MNCC_F_PROGRESS)
2327 encode_progress(msg, 0, &setup->progress);
2328 /* calling party BCD number */
2329 if (setup->fields & MNCC_F_CALLING)
2330 encode_calling(msg, &setup->calling);
2331 /* called party BCD number */
2332 if (setup->fields & MNCC_F_CALLED)
2333 encode_called(msg, &setup->called);
2334 /* user-user */
2335 if (setup->fields & MNCC_F_USERUSER)
2336 encode_useruser(msg, 0, &setup->useruser);
2337 /* redirecting party BCD number */
2338 if (setup->fields & MNCC_F_REDIRECTING)
2339 encode_redirecting(msg, &setup->redirecting);
2340 /* signal */
2341 if (setup->fields & MNCC_F_SIGNAL)
2342 encode_signal(msg, setup->signal);
2343
2344 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002345
2346 return gsm48_sendmsg(msg);
2347}
2348
Harald Welte4bfdfe72009-06-10 23:11:52 +08002349static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2350{
2351 struct gsm48_hdr *gh = msgb_l3(msg);
2352 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2353 struct tlv_parsed tp;
2354 struct gsm_mncc call_conf;
2355
2356 gsm48_stop_cc_timer(trans);
2357 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2358
2359 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2360 call_conf.callref = trans->callref;
2361 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2362#if 0
2363 /* repeat */
2364 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2365 call_conf.repeat = 1;
2366 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2367 call_conf.repeat = 2;
2368#endif
2369 /* bearer capability */
2370 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2371 call_conf.fields |= MNCC_F_BEARER_CAP;
2372 decode_bearer_cap(&call_conf.bearer_cap,
2373 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2374 }
2375 /* cause */
2376 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2377 call_conf.fields |= MNCC_F_CAUSE;
2378 decode_cause(&call_conf.cause,
2379 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2380 }
2381 /* cc cap */
2382 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2383 call_conf.fields |= MNCC_F_CCCAP;
2384 decode_cccap(&call_conf.cccap,
2385 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2386 }
2387
2388 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2389
2390 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2391}
2392
2393static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2394{
2395 struct gsm_mncc *proceeding = arg;
2396 struct msgb *msg = gsm48_msgb_alloc();
2397 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2398
2399 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2400 msg->lchan = trans->lchan;
2401 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2402
2403 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2404
2405 /* bearer capability */
2406 if (proceeding->fields & MNCC_F_BEARER_CAP)
2407 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2408 /* facility */
2409 if (proceeding->fields & MNCC_F_FACILITY)
2410 encode_facility(msg, 0, &proceeding->facility);
2411 /* progress */
2412 if (proceeding->fields & MNCC_F_PROGRESS)
2413 encode_progress(msg, 0, &proceeding->progress);
2414
2415 return gsm48_sendmsg(msg);
2416}
2417
2418static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2419{
2420 struct gsm48_hdr *gh = msgb_l3(msg);
2421 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2422 struct tlv_parsed tp;
2423 struct gsm_mncc alerting;
2424
2425 gsm48_stop_cc_timer(trans);
2426 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2427
2428 memset(&alerting, 0, sizeof(struct gsm_mncc));
2429 alerting.callref = trans->callref;
2430 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2431 /* facility */
2432 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2433 alerting.fields |= MNCC_F_FACILITY;
2434 decode_facility(&alerting.facility,
2435 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2436 }
2437
2438 /* progress */
2439 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2440 alerting.fields |= MNCC_F_PROGRESS;
2441 decode_progress(&alerting.progress,
2442 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2443 }
2444 /* ss-version */
2445 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2446 alerting.fields |= MNCC_F_SSVERSION;
2447 decode_ssversion(&alerting.ssversion,
2448 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2449 }
2450
2451 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2452
2453 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2454}
2455
2456static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2457{
2458 struct gsm_mncc *alerting = arg;
2459 struct msgb *msg = gsm48_msgb_alloc();
2460 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2461
2462 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2463 msg->lchan = trans->lchan;
2464 gh->msg_type = GSM48_MT_CC_ALERTING;
2465
2466 /* facility */
2467 if (alerting->fields & MNCC_F_FACILITY)
2468 encode_facility(msg, 0, &alerting->facility);
2469 /* progress */
2470 if (alerting->fields & MNCC_F_PROGRESS)
2471 encode_progress(msg, 0, &alerting->progress);
2472 /* user-user */
2473 if (alerting->fields & MNCC_F_USERUSER)
2474 encode_useruser(msg, 0, &alerting->useruser);
2475
2476 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2477
2478 return gsm48_sendmsg(msg);
2479}
2480
2481static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2482{
2483 struct gsm_mncc *progress = arg;
2484 struct msgb *msg = gsm48_msgb_alloc();
2485 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2486
2487 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2488 msg->lchan = trans->lchan;
2489 gh->msg_type = GSM48_MT_CC_PROGRESS;
2490
2491 /* progress */
2492 encode_progress(msg, 1, &progress->progress);
2493 /* user-user */
2494 if (progress->fields & MNCC_F_USERUSER)
2495 encode_useruser(msg, 0, &progress->useruser);
2496
2497 return gsm48_sendmsg(msg);
2498}
2499
2500static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2501{
2502 struct gsm_mncc *connect = arg;
2503 struct msgb *msg = gsm48_msgb_alloc();
2504 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2505
2506 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2507 msg->lchan = trans->lchan;
2508 gh->msg_type = GSM48_MT_CC_CONNECT;
2509
2510 gsm48_stop_cc_timer(trans);
2511 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2512
2513 /* facility */
2514 if (connect->fields & MNCC_F_FACILITY)
2515 encode_facility(msg, 0, &connect->facility);
2516 /* progress */
2517 if (connect->fields & MNCC_F_PROGRESS)
2518 encode_progress(msg, 0, &connect->progress);
2519 /* connected number */
2520 if (connect->fields & MNCC_F_CONNECTED)
2521 encode_connected(msg, &connect->connected);
2522 /* user-user */
2523 if (connect->fields & MNCC_F_USERUSER)
2524 encode_useruser(msg, 0, &connect->useruser);
2525
2526 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2527
2528 return gsm48_sendmsg(msg);
2529}
2530
2531static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2532{
2533 struct gsm48_hdr *gh = msgb_l3(msg);
2534 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2535 struct tlv_parsed tp;
2536 struct gsm_mncc connect;
2537
2538 gsm48_stop_cc_timer(trans);
2539
2540 memset(&connect, 0, sizeof(struct gsm_mncc));
2541 connect.callref = trans->callref;
2542 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2543 /* use subscriber as connected party number */
2544 if (trans->subscr) {
2545 connect.fields |= MNCC_F_CONNECTED;
2546 strncpy(connect.connected.number, trans->subscr->extension,
2547 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002548 strncpy(connect.imsi, trans->subscr->imsi,
2549 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002550 }
2551 /* facility */
2552 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2553 connect.fields |= MNCC_F_FACILITY;
2554 decode_facility(&connect.facility,
2555 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2556 }
2557 /* user-user */
2558 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2559 connect.fields |= MNCC_F_USERUSER;
2560 decode_useruser(&connect.useruser,
2561 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2562 }
2563 /* ss-version */
2564 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2565 connect.fields |= MNCC_F_SSVERSION;
2566 decode_ssversion(&connect.ssversion,
2567 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2568 }
2569
2570 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2571
2572 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2573}
2574
2575
2576static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2577{
2578 struct gsm_mncc connect_ack;
2579
2580 gsm48_stop_cc_timer(trans);
2581
2582 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2583
2584 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2585 connect_ack.callref = trans->callref;
2586 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2587 &connect_ack);
2588}
2589
2590static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2591{
2592 struct msgb *msg = gsm48_msgb_alloc();
2593 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2594
2595 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2596 msg->lchan = trans->lchan;
2597 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2598
2599 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2600
2601 return gsm48_sendmsg(msg);
2602}
2603
2604static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2605{
2606 struct gsm48_hdr *gh = msgb_l3(msg);
2607 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2608 struct tlv_parsed tp;
2609 struct gsm_mncc disc;
2610
2611 gsm48_stop_cc_timer(trans);
2612
2613 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2614
2615 memset(&disc, 0, sizeof(struct gsm_mncc));
2616 disc.callref = trans->callref;
2617 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2618 /* cause */
2619 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2620 disc.fields |= MNCC_F_CAUSE;
2621 decode_cause(&disc.cause,
2622 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2623 }
2624 /* facility */
2625 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2626 disc.fields |= MNCC_F_FACILITY;
2627 decode_facility(&disc.facility,
2628 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2629 }
2630 /* user-user */
2631 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2632 disc.fields |= MNCC_F_USERUSER;
2633 decode_useruser(&disc.useruser,
2634 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2635 }
2636 /* ss-version */
2637 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2638 disc.fields |= MNCC_F_SSVERSION;
2639 decode_ssversion(&disc.ssversion,
2640 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2641 }
2642
2643 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2644
2645}
2646
Harald Weltec66b71c2009-06-11 14:23:20 +08002647static struct gsm_mncc_cause default_cause = {
2648 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2649 .coding = 0,
2650 .rec = 0,
2651 .rec_val = 0,
2652 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2653 .diag_len = 0,
2654 .diag = { 0 },
2655};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002656
2657static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2658{
2659 struct gsm_mncc *disc = arg;
2660 struct msgb *msg = gsm48_msgb_alloc();
2661 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2662
2663 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2664 msg->lchan = trans->lchan;
2665 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2666
2667 gsm48_stop_cc_timer(trans);
2668 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2669
2670 /* cause */
2671 if (disc->fields & MNCC_F_CAUSE)
2672 encode_cause(msg, 1, &disc->cause);
2673 else
2674 encode_cause(msg, 1, &default_cause);
2675
2676 /* facility */
2677 if (disc->fields & MNCC_F_FACILITY)
2678 encode_facility(msg, 0, &disc->facility);
2679 /* progress */
2680 if (disc->fields & MNCC_F_PROGRESS)
2681 encode_progress(msg, 0, &disc->progress);
2682 /* user-user */
2683 if (disc->fields & MNCC_F_USERUSER)
2684 encode_useruser(msg, 0, &disc->useruser);
2685
2686 /* store disconnect cause for T306 expiry */
2687 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2688
2689 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2690
2691 return gsm48_sendmsg(msg);
2692}
2693
2694static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2695{
2696 struct gsm48_hdr *gh = msgb_l3(msg);
2697 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2698 struct tlv_parsed tp;
2699 struct gsm_mncc rel;
2700 int rc;
2701
2702 gsm48_stop_cc_timer(trans);
2703
2704 memset(&rel, 0, sizeof(struct gsm_mncc));
2705 rel.callref = trans->callref;
2706 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2707 /* cause */
2708 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2709 rel.fields |= MNCC_F_CAUSE;
2710 decode_cause(&rel.cause,
2711 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2712 }
2713 /* facility */
2714 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2715 rel.fields |= MNCC_F_FACILITY;
2716 decode_facility(&rel.facility,
2717 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2718 }
2719 /* user-user */
2720 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2721 rel.fields |= MNCC_F_USERUSER;
2722 decode_useruser(&rel.useruser,
2723 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2724 }
2725 /* ss-version */
2726 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2727 rel.fields |= MNCC_F_SSVERSION;
2728 decode_ssversion(&rel.ssversion,
2729 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2730 }
2731
2732 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2733 /* release collision 5.4.5 */
2734 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2735 } else {
2736 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2737 GSM48_MT_CC_RELEASE_COMPL);
2738 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2739 }
2740
2741 new_cc_state(trans, GSM_CSTATE_NULL);
2742
2743 trans->callref = 0;
2744 free_trans(trans);
2745
2746 return rc;
2747}
2748
2749static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2750{
2751 struct gsm_mncc *rel = arg;
2752 struct msgb *msg = gsm48_msgb_alloc();
2753 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2754
2755 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2756 msg->lchan = trans->lchan;
2757 gh->msg_type = GSM48_MT_CC_RELEASE;
2758
2759 trans->callref = 0;
2760
2761 gsm48_stop_cc_timer(trans);
2762 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2763
2764 /* cause */
2765 if (rel->fields & MNCC_F_CAUSE)
2766 encode_cause(msg, 0, &rel->cause);
2767 /* facility */
2768 if (rel->fields & MNCC_F_FACILITY)
2769 encode_facility(msg, 0, &rel->facility);
2770 /* user-user */
2771 if (rel->fields & MNCC_F_USERUSER)
2772 encode_useruser(msg, 0, &rel->useruser);
2773
2774 trans->T308_second = 0;
2775 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2776
2777 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2778 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2779
2780 return gsm48_sendmsg(msg);
2781}
2782
2783static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2784{
2785 struct gsm48_hdr *gh = msgb_l3(msg);
2786 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2787 struct tlv_parsed tp;
2788 struct gsm_mncc rel;
2789 int rc = 0;
2790
2791 gsm48_stop_cc_timer(trans);
2792
2793 memset(&rel, 0, sizeof(struct gsm_mncc));
2794 rel.callref = trans->callref;
2795 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2796 /* cause */
2797 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2798 rel.fields |= MNCC_F_CAUSE;
2799 decode_cause(&rel.cause,
2800 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2801 }
2802 /* facility */
2803 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2804 rel.fields |= MNCC_F_FACILITY;
2805 decode_facility(&rel.facility,
2806 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2807 }
2808 /* user-user */
2809 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2810 rel.fields |= MNCC_F_USERUSER;
2811 decode_useruser(&rel.useruser,
2812 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2813 }
2814 /* ss-version */
2815 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2816 rel.fields |= MNCC_F_SSVERSION;
2817 decode_ssversion(&rel.ssversion,
2818 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2819 }
2820
2821 if (trans->callref) {
2822 switch (trans->state) {
2823 case GSM_CSTATE_CALL_PRESENT:
2824 rc = mncc_recvmsg(trans->network, trans,
2825 MNCC_REJ_IND, &rel);
2826 break;
2827 case GSM_CSTATE_RELEASE_REQ:
2828 rc = mncc_recvmsg(trans->network, trans,
2829 MNCC_REL_CNF, &rel);
2830 break;
2831 default:
2832 rc = mncc_recvmsg(trans->network, trans,
2833 MNCC_REL_IND, &rel);
2834 }
2835 }
2836
2837 trans->callref = 0;
2838 free_trans(trans);
2839
2840 return rc;
2841}
2842
2843static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2844{
2845 struct gsm_mncc *rel = arg;
2846 struct msgb *msg = gsm48_msgb_alloc();
2847 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2848
2849 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2850 msg->lchan = trans->lchan;
2851 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2852
2853 trans->callref = 0;
2854
2855 gsm48_stop_cc_timer(trans);
2856
2857 /* cause */
2858 if (rel->fields & MNCC_F_CAUSE)
2859 encode_cause(msg, 0, &rel->cause);
2860 /* facility */
2861 if (rel->fields & MNCC_F_FACILITY)
2862 encode_facility(msg, 0, &rel->facility);
2863 /* user-user */
2864 if (rel->fields & MNCC_F_USERUSER)
2865 encode_useruser(msg, 0, &rel->useruser);
2866
2867 free_trans(trans);
2868
2869 return gsm48_sendmsg(msg);
2870}
2871
2872static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2873{
2874 struct gsm48_hdr *gh = msgb_l3(msg);
2875 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2876 struct tlv_parsed tp;
2877 struct gsm_mncc fac;
2878
2879 memset(&fac, 0, sizeof(struct gsm_mncc));
2880 fac.callref = trans->callref;
2881 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2882 /* facility */
2883 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2884 fac.fields |= MNCC_F_FACILITY;
2885 decode_facility(&fac.facility,
2886 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2887 }
2888 /* ss-version */
2889 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2890 fac.fields |= MNCC_F_SSVERSION;
2891 decode_ssversion(&fac.ssversion,
2892 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2893 }
2894
2895 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2896}
2897
2898static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2899{
2900 struct gsm_mncc *fac = arg;
2901 struct msgb *msg = gsm48_msgb_alloc();
2902 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2903
2904 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2905 msg->lchan = trans->lchan;
2906 gh->msg_type = GSM48_MT_CC_FACILITY;
2907
2908 /* facility */
2909 encode_facility(msg, 1, &fac->facility);
2910
2911 return gsm48_sendmsg(msg);
2912}
2913
2914static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2915{
2916 struct gsm_mncc hold;
2917
2918 memset(&hold, 0, sizeof(struct gsm_mncc));
2919 hold.callref = trans->callref;
2920 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2921}
2922
2923static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2924{
2925 struct msgb *msg = gsm48_msgb_alloc();
2926 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2927
2928 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2929 msg->lchan = trans->lchan;
2930 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2931
2932 return gsm48_sendmsg(msg);
2933}
2934
2935static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2936{
2937 struct gsm_mncc *hold_rej = arg;
2938 struct msgb *msg = gsm48_msgb_alloc();
2939 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2940
2941 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2942 msg->lchan = trans->lchan;
2943 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2944
2945 /* cause */
2946 if (hold_rej->fields & MNCC_F_CAUSE)
2947 encode_cause(msg, 1, &hold_rej->cause);
2948 else
2949 encode_cause(msg, 1, &default_cause);
2950
2951 return gsm48_sendmsg(msg);
2952}
2953
2954static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2955{
2956 struct gsm_mncc retrieve;
2957
2958 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2959 retrieve.callref = trans->callref;
2960 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2961}
2962
2963static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2964{
2965 struct msgb *msg = gsm48_msgb_alloc();
2966 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2967
2968 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2969 msg->lchan = trans->lchan;
2970 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2971
2972 return gsm48_sendmsg(msg);
2973}
2974
2975static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2976{
2977 struct gsm_mncc *retrieve_rej = arg;
2978 struct msgb *msg = gsm48_msgb_alloc();
2979 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2980
2981 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2982 msg->lchan = trans->lchan;
2983 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2984
2985 /* cause */
2986 if (retrieve_rej->fields & MNCC_F_CAUSE)
2987 encode_cause(msg, 1, &retrieve_rej->cause);
2988 else
2989 encode_cause(msg, 1, &default_cause);
2990
2991 return gsm48_sendmsg(msg);
2992}
2993
2994static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2995{
2996 struct gsm48_hdr *gh = msgb_l3(msg);
2997 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2998 struct tlv_parsed tp;
2999 struct gsm_mncc dtmf;
3000
3001 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3002 dtmf.callref = trans->callref;
3003 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3004 /* keypad facility */
3005 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3006 dtmf.fields |= MNCC_F_KEYPAD;
3007 decode_keypad(&dtmf.keypad,
3008 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3009 }
3010
3011 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3012}
3013
3014static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3015{
3016 struct gsm_mncc *dtmf = arg;
3017 struct msgb *msg = gsm48_msgb_alloc();
3018 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3019
3020 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3021 msg->lchan = trans->lchan;
3022 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3023
3024 /* keypad */
3025 if (dtmf->fields & MNCC_F_KEYPAD)
3026 encode_keypad(msg, dtmf->keypad);
3027
3028 return gsm48_sendmsg(msg);
3029}
3030
3031static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3032{
3033 struct gsm_mncc *dtmf = arg;
3034 struct msgb *msg = gsm48_msgb_alloc();
3035 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3036
3037 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3038 msg->lchan = trans->lchan;
3039 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3040
3041 /* cause */
3042 if (dtmf->fields & MNCC_F_CAUSE)
3043 encode_cause(msg, 1, &dtmf->cause);
3044 else
3045 encode_cause(msg, 1, &default_cause);
3046
3047 return gsm48_sendmsg(msg);
3048}
3049
3050static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3051{
3052 struct msgb *msg = gsm48_msgb_alloc();
3053 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3054
3055 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3056 msg->lchan = trans->lchan;
3057 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3058
3059 return gsm48_sendmsg(msg);
3060}
3061
3062static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3063{
3064 struct gsm_mncc dtmf;
3065
3066 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3067 dtmf.callref = trans->callref;
3068
3069 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3070}
3071
3072static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3073{
3074 struct gsm48_hdr *gh = msgb_l3(msg);
3075 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3076 struct tlv_parsed tp;
3077 struct gsm_mncc modify;
3078
3079 memset(&modify, 0, sizeof(struct gsm_mncc));
3080 modify.callref = trans->callref;
3081 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3082 /* bearer capability */
3083 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3084 modify.fields |= MNCC_F_BEARER_CAP;
3085 decode_bearer_cap(&modify.bearer_cap,
3086 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3087 }
3088
3089 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3090
3091 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3092}
3093
3094static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3095{
3096 struct gsm_mncc *modify = arg;
3097 struct msgb *msg = gsm48_msgb_alloc();
3098 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3099
3100 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3101 msg->lchan = trans->lchan;
3102 gh->msg_type = GSM48_MT_CC_MODIFY;
3103
3104 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3105
3106 /* bearer capability */
3107 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3108
3109 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3110
3111 return gsm48_sendmsg(msg);
3112}
3113
3114static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3115{
3116 struct gsm48_hdr *gh = msgb_l3(msg);
3117 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3118 struct tlv_parsed tp;
3119 struct gsm_mncc modify;
3120
3121 gsm48_stop_cc_timer(trans);
3122
3123 memset(&modify, 0, sizeof(struct gsm_mncc));
3124 modify.callref = trans->callref;
3125 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3126 /* bearer capability */
3127 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3128 modify.fields |= MNCC_F_BEARER_CAP;
3129 decode_bearer_cap(&modify.bearer_cap,
3130 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3131 }
3132
3133 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3134
3135 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3136}
3137
3138static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3139{
3140 struct gsm_mncc *modify = arg;
3141 struct msgb *msg = gsm48_msgb_alloc();
3142 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3143
3144 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3145 msg->lchan = trans->lchan;
3146 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3147
3148 /* bearer capability */
3149 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3150
3151 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3152
3153 return gsm48_sendmsg(msg);
3154}
3155
3156static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3157{
3158 struct gsm48_hdr *gh = msgb_l3(msg);
3159 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3160 struct tlv_parsed tp;
3161 struct gsm_mncc modify;
3162
3163 gsm48_stop_cc_timer(trans);
3164
3165 memset(&modify, 0, sizeof(struct gsm_mncc));
3166 modify.callref = trans->callref;
3167 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3168 /* bearer capability */
3169 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3170 modify.fields |= GSM48_IE_BEARER_CAP;
3171 decode_bearer_cap(&modify.bearer_cap,
3172 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3173 }
3174 /* cause */
3175 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3176 modify.fields |= MNCC_F_CAUSE;
3177 decode_cause(&modify.cause,
3178 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3179 }
3180
3181 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3182
3183 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3184}
3185
3186static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3187{
3188 struct gsm_mncc *modify = arg;
3189 struct msgb *msg = gsm48_msgb_alloc();
3190 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3191
3192 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3193 msg->lchan = trans->lchan;
3194 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3195
3196 /* bearer capability */
3197 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3198 /* cause */
3199 encode_cause(msg, 1, &modify->cause);
3200
3201 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3202
3203 return gsm48_sendmsg(msg);
3204}
3205
3206static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3207{
3208 struct gsm_mncc *notify = arg;
3209 struct msgb *msg = gsm48_msgb_alloc();
3210 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3211
3212 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3213 msg->lchan = trans->lchan;
3214 gh->msg_type = GSM48_MT_CC_NOTIFY;
3215
3216 /* notify */
3217 encode_notify(msg, notify->notify);
3218
3219 return gsm48_sendmsg(msg);
3220}
3221
3222static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3223{
3224 struct gsm48_hdr *gh = msgb_l3(msg);
3225 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3226// struct tlv_parsed tp;
3227 struct gsm_mncc notify;
3228
3229 memset(&notify, 0, sizeof(struct gsm_mncc));
3230 notify.callref = trans->callref;
3231// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3232 if (payload_len >= 1)
3233 decode_notify(&notify.notify, gh->data);
3234
3235 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3236}
3237
3238static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3239{
3240 struct gsm_mncc *user = arg;
3241 struct msgb *msg = gsm48_msgb_alloc();
3242 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3243
3244 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3245 msg->lchan = trans->lchan;
3246 gh->msg_type = GSM48_MT_CC_USER_INFO;
3247
3248 /* user-user */
3249 if (user->fields & MNCC_F_USERUSER)
3250 encode_useruser(msg, 1, &user->useruser);
3251 /* more data */
3252 if (user->more)
3253 encode_more(msg);
3254
3255 return gsm48_sendmsg(msg);
3256}
3257
3258static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3259{
3260 struct gsm48_hdr *gh = msgb_l3(msg);
3261 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3262 struct tlv_parsed tp;
3263 struct gsm_mncc user;
3264
3265 memset(&user, 0, sizeof(struct gsm_mncc));
3266 user.callref = trans->callref;
3267 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3268 /* user-user */
3269 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3270 user.fields |= MNCC_F_USERUSER;
3271 decode_useruser(&user.useruser,
3272 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3273 }
3274 /* more data */
3275 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3276 user.more = 1;
3277
3278 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3279}
3280
3281static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3282{
3283 struct gsm_mncc *mode = arg;
3284
3285 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3286}
3287
3288static struct downstate {
3289 u_int32_t states;
3290 int type;
3291 int (*rout) (struct gsm_trans *trans, void *arg);
3292} downstatelist[] = {
3293 /* mobile originating call establishment */
3294 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3295 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3296 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3297 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3298 {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 */
3299 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3300 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3301 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3302 /* mobile terminating call establishment */
3303 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3304 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3305 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3306 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3307 /* signalling during call */
3308 {SBIT(GSM_CSTATE_ACTIVE),
3309 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3310 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3311 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3312 {ALL_STATES,
3313 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3314 {ALL_STATES,
3315 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3316 {ALL_STATES,
3317 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3318 {SBIT(GSM_CSTATE_ACTIVE),
3319 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3320 {SBIT(GSM_CSTATE_ACTIVE),
3321 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3322 {SBIT(GSM_CSTATE_ACTIVE),
3323 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3324 {SBIT(GSM_CSTATE_ACTIVE),
3325 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3326 {SBIT(GSM_CSTATE_ACTIVE),
3327 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3328 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3329 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3330 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3331 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3332 {SBIT(GSM_CSTATE_ACTIVE),
3333 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3334 /* clearing */
3335 {SBIT(GSM_CSTATE_INITIATED),
3336 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3337 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3338 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3339 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3340 MNCC_REL_REQ, gsm48_cc_tx_release},
3341 /* special */
3342 {ALL_STATES,
3343 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3344};
3345
3346#define DOWNSLLEN \
3347 (sizeof(downstatelist) / sizeof(struct downstate))
3348
3349
3350int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3351{
3352 int i, j, k, l, rc = 0;
3353 struct gsm_trans *trans = NULL, *transt;
3354 struct gsm_subscriber *subscr;
3355 struct gsm_lchan *lchan = NULL, *lchant;
3356 struct gsm_bts *bts = NULL;
3357 struct gsm_bts_trx *trx;
3358 struct gsm_bts_trx_ts *ts;
3359 struct gsm_mncc *data = arg, rel;
3360
3361 /* handle special messages */
3362 switch(msg_type) {
3363 case MNCC_BRIDGE:
3364 return tch_bridge(net, arg);
3365 case MNCC_FRAME_DROP:
3366 return tch_recv(net, arg, 0);
3367 case MNCC_FRAME_RECV:
3368 return tch_recv(net, arg, 1);
3369 case GSM_TRAU_FRAME:
3370 return tch_frame(net, arg);
3371 }
3372
3373 memset(&rel, 0, sizeof(struct gsm_mncc));
3374 rel.callref = data->callref;
3375
3376 /* Find callref */
3377 trans = get_trans_ref(net, data->callref);
3378
3379 /* Callref unknown */
3380 if (!trans) {
Andreas Eversbergc079be42009-06-15 23:22:09 +02003381 if (msg_type != MNCC_SETUP_REQ ||
3382 (!data->called.number[0] && !data->imsi[0])) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003383 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3384 "Received '%s' from MNCC with "
3385 "unknown callref %d\n", data->called.number,
3386 get_mncc_name(msg_type), data->callref);
3387 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003388 return mncc_release_ind(net, NULL, data->callref,
3389 GSM48_CAUSE_LOC_PRN_S_LU,
3390 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003391 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003392 if (!data->called.number[0] && !data->imsi[0]) {
3393 DEBUGP(DCC, "(bts - trx - ts - ti) "
3394 "Received '%s' from MNCC with "
3395 "no number or IMSI\n", get_mncc_name(msg_type));
3396 /* Invalid number */
3397 return mncc_release_ind(net, NULL, data->callref,
3398 GSM48_CAUSE_LOC_PRN_S_LU,
3399 GSM48_CC_CAUSE_INV_NR_FORMAT);
3400 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003401 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003402 if (data->called.number[0])
3403 subscr = subscr_get_by_extension(data->called.number);
3404 else
3405 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003406 /* If subscriber is not found */
3407 if (!subscr) {
3408 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3409 "Received '%s' from MNCC with "
3410 "unknown subscriber %s\n", data->called.number,
3411 get_mncc_name(msg_type), data->called.number);
3412 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003413 return mncc_release_ind(net, NULL, data->callref,
3414 GSM48_CAUSE_LOC_PRN_S_LU,
3415 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003416 }
3417 /* If subscriber is not "attached" */
3418 if (!subscr->lac) {
3419 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3420 "Received '%s' from MNCC with "
3421 "detached subscriber %s\n", data->called.number,
3422 get_mncc_name(msg_type), data->called.number);
3423 subscr_put(subscr);
3424 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003425 return mncc_release_ind(net, NULL, data->callref,
3426 GSM48_CAUSE_LOC_PRN_S_LU,
3427 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003428 }
3429 /* Create transaction */
Harald Welte2cf161b2009-06-20 22:36:41 +02003430 if (!(trans = talloc(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003431 DEBUGP(DCC, "No memory for trans.\n");
3432 subscr_put(subscr);
3433 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003434 mncc_release_ind(net, NULL, data->callref,
3435 GSM48_CAUSE_LOC_PRN_S_LU,
3436 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003437 return -ENOMEM;
3438 }
3439 trans->callref = data->callref;
3440 trans->network = net;
3441 trans->transaction_id = 0xff; /* unassigned */
3442 llist_add_tail(&trans->entry, &net->trans_list);
3443 /* Assign subscriber to transaction */
3444 trans->subscr = subscr;
3445 /* Find lchan */
3446 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003447 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003448 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003449 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003450 for (k = 0; k < TRX_NR_TS; k++) {
3451 ts = &trx->ts[k];
3452 for (l = 0; l < TS_MAX_LCHAN; l++) {
3453 lchant = &ts->lchan[l];
3454 if (lchant->subscr == subscr) {
3455 lchan = lchant;
3456 break;
3457 }
3458 }
3459 }
3460 }
3461 }
3462
3463 /* If subscriber has no lchan */
3464 if (!lchan) {
3465 /* find transaction with this subscriber already paging */
3466 llist_for_each_entry(transt, &net->trans_list, entry) {
3467 /* Transaction of our lchan? */
3468 if (transt == trans ||
3469 transt->subscr != subscr)
3470 continue;
3471 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3472 "Received '%s' from MNCC with "
3473 "unallocated channel, paging already "
3474 "started.\n", bts->nr,
3475 data->called.number,
3476 get_mncc_name(msg_type));
3477 return 0;
3478 }
3479 /* store setup informations until paging was successfull */
3480 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3481 /* start paging subscriber on all BTS with her location */
3482 subscr->net = net;
3483 bts = NULL;
3484 do {
3485 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3486 if (!bts)
3487 break;
3488 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3489 "Received '%s' from MNCC with "
3490 "unallocated channel, paging.\n",
3491 bts->nr, data->called.number,
3492 get_mncc_name(msg_type));
3493 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003494 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003495 setup_trig_pag_evt, subscr);
3496 } while (1);
3497 return 0;
3498 }
3499 /* Assign lchan */
3500 trans->lchan = lchan;
3501 use_lchan(lchan);
3502 }
3503 lchan = trans->lchan;
3504
3505 /* if paging did not respond yet */
3506 if (!lchan) {
3507 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3508 "Received '%s' from MNCC in paging state\n",
3509 (trans->subscr)?(trans->subscr->extension):"-",
3510 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003511 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3512 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003513 if (msg_type == MNCC_REL_REQ)
3514 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3515 else
3516 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3517 trans->callref = 0;
3518 free_trans(trans);
3519 return rc;
3520 }
3521
3522 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3523 "Received '%s' from MNCC in state %d (%s)\n",
3524 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3525 trans->transaction_id,
3526 (lchan->subscr)?(lchan->subscr->extension):"-",
3527 get_mncc_name(msg_type), trans->state,
3528 cc_state_names[trans->state]);
3529
3530 /* Find function for current state and message */
3531 for (i = 0; i < DOWNSLLEN; i++)
3532 if ((msg_type == downstatelist[i].type)
3533 && ((1 << trans->state) & downstatelist[i].states))
3534 break;
3535 if (i == DOWNSLLEN) {
3536 DEBUGP(DCC, "Message unhandled at this state.\n");
3537 return 0;
3538 }
3539
3540 rc = downstatelist[i].rout(trans, arg);
3541
3542 return rc;
3543}
3544
3545
3546static struct datastate {
3547 u_int32_t states;
3548 int type;
3549 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3550} datastatelist[] = {
3551 /* mobile originating call establishment */
3552 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3553 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3554 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3555 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3556 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3557 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3558 /* mobile terminating call establishment */
3559 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3560 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3561 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3562 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3563 {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 */
3564 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3565 /* signalling during call */
3566 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3567 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3568 {SBIT(GSM_CSTATE_ACTIVE),
3569 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3570 {ALL_STATES,
3571 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3572 {ALL_STATES,
3573 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3574 {ALL_STATES,
3575 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3576 {SBIT(GSM_CSTATE_ACTIVE),
3577 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3578 {SBIT(GSM_CSTATE_ACTIVE),
3579 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3580 {SBIT(GSM_CSTATE_ACTIVE),
3581 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3582 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3583 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3584 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3585 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3586 {SBIT(GSM_CSTATE_ACTIVE),
3587 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3588 /* clearing */
3589 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3590 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3591 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3592 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3593 {ALL_STATES, /* 5.4.3.4 */
3594 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3595};
3596
3597#define DATASLLEN \
3598 (sizeof(datastatelist) / sizeof(struct datastate))
3599
Harald Welte4bc90a12008-12-27 16:32:52 +00003600static int gsm0408_rcv_cc(struct msgb *msg)
3601{
3602 struct gsm48_hdr *gh = msgb_l3(msg);
3603 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003604 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3605 struct gsm_lchan *lchan = msg->lchan;
3606 struct gsm_trans *trans = NULL, *transt;
3607 struct gsm_network *net = lchan->ts->trx->bts->network;
3608 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003609
Harald Welte4bfdfe72009-06-10 23:11:52 +08003610 if (msg_type & 0x80) {
3611 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3612 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003613 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003614
3615 /* Find transaction */
3616 llist_for_each_entry(transt, &net->trans_list, entry) {
3617 /* Transaction of our lchan? */
3618 if (transt->lchan == lchan
3619 && transt->transaction_id == transaction_id) {
3620 trans = transt;
3621 }
3622 }
3623
3624 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3625 "Received '%s' from MS in state %d (%s)\n",
3626 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3627 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3628 cc_msg_names[msg_type], trans?(trans->state):0,
3629 cc_state_names[trans?(trans->state):0]);
3630
3631 /* Create transaction */
3632 if (!trans) {
3633 DEBUGP(DCC, "Unknown transaction ID %02x, "
3634 "creating new trans.\n", transaction_id);
3635 /* Create transaction */
Harald Welte2cf161b2009-06-20 22:36:41 +02003636 if (!(trans = talloc(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003637 DEBUGP(DCC, "No memory for trans.\n");
3638 rc = gsm48_tx_simple(msg->lchan,
3639 GSM48_PDISC_CC | transaction_id,
3640 GSM48_MT_CC_RELEASE_COMPL);
3641 return -ENOMEM;
3642 }
3643 llist_add_tail(&trans->entry, &net->trans_list);
3644 /* Assign transaction */
3645 trans->callref = new_callref++;
3646 trans->network = net;
3647 trans->transaction_id = transaction_id;
3648 trans->lchan = lchan;
3649 use_lchan(lchan);
3650 if (lchan->subscr) {
3651 trans->subscr = lchan->subscr;
3652 subscr_get(trans->subscr);
3653 }
3654 }
3655
3656 /* find function for current state and message */
3657 for (i = 0; i < DATASLLEN; i++)
3658 if ((msg_type == datastatelist[i].type)
3659 && ((1 << trans->state) & datastatelist[i].states))
3660 break;
3661 if (i == DATASLLEN) {
3662 DEBUGP(DCC, "Message unhandled at this state.\n");
3663 return 0;
3664 }
3665
3666 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003667
3668 return rc;
3669}
3670
Harald Welte52b1f982008-12-23 20:25:15 +00003671/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3672int gsm0408_rcvmsg(struct msgb *msg)
3673{
3674 struct gsm48_hdr *gh = msgb_l3(msg);
3675 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003676 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003677
3678 switch (pdisc) {
3679 case GSM48_PDISC_CC:
3680 rc = gsm0408_rcv_cc(msg);
3681 break;
3682 case GSM48_PDISC_MM:
3683 rc = gsm0408_rcv_mm(msg);
3684 break;
3685 case GSM48_PDISC_RR:
3686 rc = gsm0408_rcv_rr(msg);
3687 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003688 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003689 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003690 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003691 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003692 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003693 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3694 pdisc);
3695 break;
3696 default:
3697 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3698 pdisc);
3699 break;
3700 }
3701
3702 return rc;
3703}
Harald Welte8470bf22008-12-25 23:28:35 +00003704
Harald Welte8470bf22008-12-25 23:28:35 +00003705/* Section 9.1.8 / Table 9.9 */
3706struct chreq {
3707 u_int8_t val;
3708 u_int8_t mask;
3709 enum chreq_type type;
3710};
3711
3712/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3713static const struct chreq chreq_type_neci1[] = {
3714 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3715 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3716 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3717 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3718 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3719 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3720 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3721 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3722 { 0x10, 0xf0, CHREQ_T_SDCCH },
3723 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3724 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3725 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3726};
3727
3728/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3729static const struct chreq chreq_type_neci0[] = {
3730 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3731 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3732 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3733 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3734 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3735 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3736 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3737 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3738};
3739
3740static const enum gsm_chan_t ctype_by_chreq[] = {
3741 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3742 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3743 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3744 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3745 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3746 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3747 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3748 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3749 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3750 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3751 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3752 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3753};
3754
Harald Weltee14a57c2008-12-29 04:08:28 +00003755static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3756 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3757 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3758 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3759 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3760 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3761 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3762 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3763 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3764 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3765 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3766 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3767 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3768};
3769
Harald Welte8470bf22008-12-25 23:28:35 +00003770enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3771{
3772 int i;
3773 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3774
3775 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3776 const struct chreq *chr = &chreq_type_neci0[i];
3777 if ((ra & chr->mask) == chr->val)
3778 return ctype_by_chreq[chr->type];
3779 }
3780 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3781 return GSM_LCHAN_SDCCH;
3782}
Harald Weltee14a57c2008-12-29 04:08:28 +00003783
3784enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3785{
3786 int i;
3787 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3788
3789 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3790 const struct chreq *chr = &chreq_type_neci0[i];
3791 if ((ra & chr->mask) == chr->val)
3792 return reason_by_chreq[chr->type];
3793 }
3794 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3795 return GSM_CHREQ_REASON_OTHER;
3796}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003797
3798/* dequeue messages to layer 4 */
3799int bsc_upqueue(struct gsm_network *net)
3800{
3801 struct gsm_mncc *mncc;
3802 struct msgb *msg;
3803 int work = 0;
3804
3805 if (net)
3806 while ((msg = msgb_dequeue(&net->upqueue))) {
3807 mncc = (struct gsm_mncc *)msg->data;
3808 if (net->mncc_recv)
3809 net->mncc_recv(net, mncc->msg_type, mncc);
3810 work = 1; /* work done */
3811 }
3812
3813 return work;
3814}