blob: 76d748c058a7a656f019d32fb0966ca36b1f4068 [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{
Harald Welte966636f2009-06-26 19:39:35 +0200978 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
979 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000980}
981
Holger Freyther3e2c3232009-01-04 03:55:31 +0000982int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000983{
Harald Welte65e74cc2008-12-29 01:55:35 +0000984 if (msg->lchan) {
Harald Welte4bfdfe72009-06-10 23:11:52 +0800985 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
Harald Welte8470bf22008-12-25 23:28:35 +0000986 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000987
Harald Welte4bfdfe72009-06-10 23:11:52 +0800988 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
989 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
990 "Sending '%s' to MS.\n", msg->trx->bts->nr,
991 msg->trx->nr, msg->lchan->ts->nr,
992 gh->proto_discr & 0xf0,
993 cc_msg_names[gh->msg_type & 0x3f]);
994 else
995 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
996 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
997 msg->trx->nr, msg->lchan->ts->nr,
998 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +0000999 }
1000
Harald Welte4b634542008-12-27 01:55:51 +00001001 msg->l3h = msg->data;
1002
Harald Welte8470bf22008-12-25 23:28:35 +00001003 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001004}
1005
Holger Freyther429e7762008-12-30 13:28:30 +00001006/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001007int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001008{
Harald Welte8470bf22008-12-25 23:28:35 +00001009 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001010 struct gsm48_hdr *gh;
1011
Harald Welte8470bf22008-12-25 23:28:35 +00001012 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001013
1014 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1015 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001016 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001017 gh->data[0] = cause;
1018
Harald Weltedb253af2008-12-30 17:56:55 +00001019 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1020
Harald Welte65e74cc2008-12-29 01:55:35 +00001021 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001022}
1023
1024/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001025int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001026{
Harald Welte8470bf22008-12-25 23:28:35 +00001027 struct gsm_bts *bts = lchan->ts->trx->bts;
1028 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001029 struct gsm48_hdr *gh;
1030 struct gsm48_loc_area_id *lai;
1031 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001032 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001033
Harald Welte8470bf22008-12-25 23:28:35 +00001034 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001035
1036 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1037 gh->proto_discr = GSM48_PDISC_MM;
1038 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1039
1040 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001041 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001042 bts->network->network_code, bts->location_area_code);
1043
1044 mid = msgb_put(msg, MID_TMSI_LEN);
1045 generate_mid_from_tmsi(mid, tmsi);
1046
1047 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1048
Harald Weltedb253af2008-12-30 17:56:55 +00001049 ret = gsm48_sendmsg(msg);
1050
Harald Weltedb253af2008-12-30 17:56:55 +00001051 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001052
Holger Freyther07cc8d82008-12-29 06:23:46 +00001053 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001054}
1055
Harald Weltefc977a82008-12-27 10:19:37 +00001056static char bcd2char(u_int8_t bcd)
1057{
1058 if (bcd < 0xa)
1059 return '0' + bcd;
1060 else
1061 return 'A' + (bcd - 0xa);
1062}
1063
Harald Weltebf5e8df2009-02-03 12:59:45 +00001064/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001065static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1066{
1067 int i;
1068 u_int8_t mi_type;
1069 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001070 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001071
1072 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1073
1074 switch (mi_type) {
1075 case GSM_MI_TYPE_NONE:
1076 break;
1077 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001078 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1079 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1080 memcpy(&tmsi, &mi[1], 4);
1081 tmsi = ntohl(tmsi);
1082 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001083 }
1084 break;
1085 case GSM_MI_TYPE_IMSI:
1086 case GSM_MI_TYPE_IMEI:
1087 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001088 *str_cur++ = bcd2char(mi[0] >> 4);
1089
1090 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001091 if (str_cur + 2 >= string + str_len)
1092 return str_cur - string;
1093 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001094 /* skip last nibble in last input byte when GSM_EVEN */
1095 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1096 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001097 }
1098 break;
1099 default:
1100 break;
1101 }
Harald Weltefc977a82008-12-27 10:19:37 +00001102 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001103
Harald Weltefc977a82008-12-27 10:19:37 +00001104 return str_cur - string;
1105}
1106
Harald Weltebf5e8df2009-02-03 12:59:45 +00001107/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001108static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1109{
1110 struct msgb *msg = gsm48_msgb_alloc();
1111 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001112
Harald Welte231ad4f2008-12-27 11:15:38 +00001113 msg->lchan = lchan;
1114
1115 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1116 gh->proto_discr = GSM48_PDISC_MM;
1117 gh->msg_type = GSM48_MT_MM_ID_REQ;
1118 gh->data[0] = id_type;
1119
Harald Welte65e74cc2008-12-29 01:55:35 +00001120 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001121}
1122
1123#define MI_SIZE 32
1124
Harald Weltebf5e8df2009-02-03 12:59:45 +00001125/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001126static int mm_rx_id_resp(struct msgb *msg)
1127{
1128 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001129 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +00001130 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1131 char mi_string[MI_SIZE];
1132
1133 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001134 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001135 mi_type, mi_string);
1136
Harald Welte75a983f2008-12-27 21:34:06 +00001137 switch (mi_type) {
1138 case GSM_MI_TYPE_IMSI:
1139 if (!lchan->subscr)
1140 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001141 if (lchan->loc_operation)
1142 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001143 break;
1144 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001145 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001146 /* update subscribe <-> IMEI mapping */
1147 if (lchan->subscr)
1148 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001149 if (lchan->loc_operation)
1150 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001151 break;
1152 }
Holger Freyther73487a22008-12-31 18:53:57 +00001153
1154 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001155 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001156}
1157
Harald Welte255539c2008-12-28 02:26:27 +00001158
1159static void loc_upd_rej_cb(void *data)
1160{
1161 struct gsm_lchan *lchan = data;
1162
Holger Freyther73487a22008-12-31 18:53:57 +00001163 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001164 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001165 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001166}
1167
Holger Freytherb7193e42008-12-29 17:44:08 +00001168static void schedule_reject(struct gsm_lchan *lchan)
1169{
Holger Freyther73487a22008-12-31 18:53:57 +00001170 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1171 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001172 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001173}
1174
Harald Welte2a139372009-02-22 21:14:55 +00001175static const char *lupd_name(u_int8_t type)
1176{
1177 switch (type) {
1178 case GSM48_LUPD_NORMAL:
1179 return "NORMAL";
1180 case GSM48_LUPD_PERIODIC:
1181 return "PEROIDOC";
1182 case GSM48_LUPD_IMSI_ATT:
1183 return "IMSI ATTACH";
1184 default:
1185 return "UNKNOWN";
1186 }
1187}
1188
Harald Welte231ad4f2008-12-27 11:15:38 +00001189#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001190/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001191static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001192{
Harald Welte8470bf22008-12-25 23:28:35 +00001193 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001194 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001195 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001196 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +00001197 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001198 char mi_string[MI_SIZE];
1199 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001200
Harald Welte8470bf22008-12-25 23:28:35 +00001201 lu = (struct gsm48_loc_upd_req *) gh->data;
1202
1203 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001204
Harald Weltefc977a82008-12-27 10:19:37 +00001205 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1206
Holger Freyther79f4ae62009-06-02 03:25:04 +00001207 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001208 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001209
Holger Freythereaf04692009-06-06 13:54:44 +00001210 /*
1211 * Pseudo Spoof detection: Just drop a second/concurrent
1212 * location updating request.
1213 */
1214 if (lchan->loc_operation) {
1215 DEBUGP(DMM, "LUPDREQ: ignoring request due an existing one: %p.\n",
1216 lchan->loc_operation);
1217 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1218 return 0;
1219 }
1220
Holger Freyther73487a22008-12-31 18:53:57 +00001221 allocate_loc_updating_req(lchan);
1222
Harald Welte52b1f982008-12-23 20:25:15 +00001223 switch (mi_type) {
1224 case GSM_MI_TYPE_IMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001225 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001226 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001227 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001228 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001229
Harald Welte52b1f982008-12-23 20:25:15 +00001230 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +00001231 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +00001232 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001233 case GSM_MI_TYPE_TMSI:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001234 DEBUGP(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001235 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001236 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001237 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001238
Harald Welte52b1f982008-12-23 20:25:15 +00001239 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welteba4cf162009-01-10 01:49:35 +00001240 subscr = subscr_get_by_tmsi(mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001241 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001242 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001243 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001244 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001245 }
1246 break;
1247 case GSM_MI_TYPE_IMEI:
1248 case GSM_MI_TYPE_IMEISV:
1249 /* no sim card... FIXME: what to do ? */
Harald Welte2a139372009-02-22 21:14:55 +00001250 DEBUGP(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001251 break;
1252 default:
Harald Welte2a139372009-02-22 21:14:55 +00001253 DEBUGP(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001254 break;
1255 }
1256
Harald Welte4bfdfe72009-06-10 23:11:52 +08001257 if (!subscr) {
1258 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
1259 /* FIXME: request id? close channel? */
1260 return -EINVAL;
1261 }
1262
Harald Welte255539c2008-12-28 02:26:27 +00001263 lchan->subscr = subscr;
1264
Holger Freyther73487a22008-12-31 18:53:57 +00001265 /*
1266 * Schedule the reject timer and check if we can let the
1267 * subscriber into our network immediately or if we need to wait
1268 * for identity responses.
1269 */
1270 schedule_reject(lchan);
Holger Freytherd51524f2009-06-09 08:27:07 +00001271 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001272}
1273
Harald Welte7584aea2009-02-11 11:44:12 +00001274/* 9.1.5 Channel mode modify */
1275int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1276{
1277 struct msgb *msg = gsm48_msgb_alloc();
1278 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1279 struct gsm48_chan_mode_modify *cmm =
1280 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001281 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001282
Harald Welte4a543e82009-02-28 13:17:55 +00001283 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001284
Harald Welte45b407a2009-05-23 15:51:12 +00001285 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001286 msg->lchan = lchan;
1287 gh->proto_discr = GSM48_PDISC_RR;
1288 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1289
1290 /* fill the channel information element, this code
1291 * should probably be shared with rsl_rx_chan_rqd() */
1292 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001293 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001294 cmm->chan_desc.h0.h = 0;
1295 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1296 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1297 cmm->mode = mode;
1298
1299 return gsm48_sendmsg(msg);
1300}
1301
Harald Welte4bfdfe72009-06-10 23:11:52 +08001302#if 0
1303static u_int8_t to_bcd8(u_int8_t val)
1304{
1305 return ((val / 10) << 4) | (val % 10);
1306}
1307#endif
1308
Harald Weltedb253af2008-12-30 17:56:55 +00001309/* Section 9.2.15a */
1310int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1311{
1312 struct msgb *msg = gsm48_msgb_alloc();
1313 struct gsm48_hdr *gh;
1314 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001315 u_int8_t *ptr8;
1316 u_int16_t *ptr16;
1317 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001318 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001319#if 0
1320 time_t cur_t;
1321 struct tm* cur_time;
1322 int tz15min;
1323#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001324
1325 msg->lchan = lchan;
1326
1327 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1328 gh->proto_discr = GSM48_PDISC_MM;
1329 gh->msg_type = GSM48_MT_MM_INFO;
1330
1331 if (net->name_long) {
1332 name_len = strlen(net->name_long);
1333 /* 10.5.3.5a */
1334 ptr8 = msgb_put(msg, 3);
1335 ptr8[0] = GSM48_IE_NAME_LONG;
1336 ptr8[1] = name_len*2 +1;
1337 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1338
1339 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1340 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001341 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001342
1343 /* FIXME: Use Cell Broadcast, not UCS-2, since
1344 * UCS-2 is only supported by later revisions of the spec */
1345 }
1346
1347 if (net->name_short) {
1348 name_len = strlen(net->name_short);
1349 /* 10.5.3.5a */
1350 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1351 ptr8[0] = GSM48_IE_NAME_LONG;
1352 ptr8[1] = name_len*2 + 1;
1353 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1354
Harald Weltee872cb12009-01-01 00:33:37 +00001355 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001356 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001357 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001358 }
1359
1360#if 0
1361 /* Section 10.5.3.9 */
1362 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001363 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001364 ptr8 = msgb_put(msg, 8);
1365 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1366 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1367 ptr8[2] = to_bcd8(cur_time->tm_mon);
1368 ptr8[3] = to_bcd8(cur_time->tm_mday);
1369 ptr8[4] = to_bcd8(cur_time->tm_hour);
1370 ptr8[5] = to_bcd8(cur_time->tm_min);
1371 ptr8[6] = to_bcd8(cur_time->tm_sec);
1372 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1373 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001374 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001375 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001376 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001377#endif
1378
1379 return gsm48_sendmsg(msg);
1380}
1381
Harald Welte4b634542008-12-27 01:55:51 +00001382static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1383{
Harald Welte4b634542008-12-27 01:55:51 +00001384 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001385 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001386}
Harald Welteba4cf162009-01-10 01:49:35 +00001387
1388/* 9.2.6 CM service reject */
1389static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1390 enum gsm48_reject_value value)
1391{
1392 struct msgb *msg = gsm48_msgb_alloc();
1393 struct gsm48_hdr *gh;
1394
1395 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1396
1397 msg->lchan = lchan;
1398 use_lchan(lchan);
1399
1400 gh->proto_discr = GSM48_PDISC_MM;
1401 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1402 gh->data[0] = value;
1403 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1404
1405 return gsm48_sendmsg(msg);
1406}
1407
Harald Welte4ed0e922009-01-10 03:17:30 +00001408
1409/*
1410 * Handle CM Service Requests
1411 * a) Verify that the packet is long enough to contain the information
1412 * we require otherwsie reject with INCORRECT_MESSAGE
1413 * b) Try to parse the TMSI. If we do not have one reject
1414 * c) Check that we know the subscriber with the TMSI otherwise reject
1415 * with a HLR cause
1416 * d) Set the subscriber on the gsm_lchan and accept
1417 */
Harald Welte4b634542008-12-27 01:55:51 +00001418static int gsm48_rx_mm_serv_req(struct msgb *msg)
1419{
Harald Welteba4cf162009-01-10 01:49:35 +00001420 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001421 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001422
Harald Welteba4cf162009-01-10 01:49:35 +00001423 struct gsm_subscriber *subscr;
1424 struct gsm48_hdr *gh = msgb_l3(msg);
1425 struct gsm48_service_request *req =
1426 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001427 /* unfortunately in Phase1 the classmar2 length is variable */
1428 u_int8_t classmark2_len = gh->data[1];
1429 u_int8_t *classmark2 = gh->data+2;
1430 u_int8_t mi_len = *(classmark2 + classmark2_len);
1431 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001432
Harald Weltec9e02182009-05-01 19:07:53 +00001433 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001434 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001435 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001436 return gsm48_tx_mm_serv_rej(msg->lchan,
1437 GSM48_REJECT_INCORRECT_MESSAGE);
1438 }
1439
1440 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001441 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001442 return gsm48_tx_mm_serv_rej(msg->lchan,
1443 GSM48_REJECT_INCORRECT_MESSAGE);
1444 }
1445
Harald Weltec9e02182009-05-01 19:07:53 +00001446 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001447 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001448 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001449 return gsm48_tx_mm_serv_rej(msg->lchan,
1450 GSM48_REJECT_INCORRECT_MESSAGE);
1451 }
1452
Harald Weltec9e02182009-05-01 19:07:53 +00001453 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001454 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001455 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001456
Holger Freythereb443982009-06-04 13:58:42 +00001457 subscr = subscr_get_by_tmsi(mi_string);
1458
Harald Welte2a139372009-02-22 21:14:55 +00001459 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001460 if (!subscr)
1461 return gsm48_tx_mm_serv_rej(msg->lchan,
1462 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1463
1464 if (!msg->lchan->subscr)
1465 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001466 else if (msg->lchan->subscr != subscr) {
1467 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1468 subscr_put(subscr);
1469 }
1470
Harald Weltef7c43522009-06-09 20:24:21 +00001471 subscr->classmark2_len = classmark2_len;
1472 memcpy(subscr->classmark2, classmark2, classmark2_len);
1473
Harald Welte4b634542008-12-27 01:55:51 +00001474 return gsm48_tx_mm_serv_ack(msg->lchan);
1475}
1476
Harald Welte2a139372009-02-22 21:14:55 +00001477static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1478{
1479 struct gsm48_hdr *gh = msgb_l3(msg);
1480 struct gsm48_imsi_detach_ind *idi =
1481 (struct gsm48_imsi_detach_ind *) gh->data;
1482 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1483 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001484 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001485
1486 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1487 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1488 mi_type, mi_string);
1489
1490 switch (mi_type) {
1491 case GSM_MI_TYPE_TMSI:
1492 subscr = subscr_get_by_tmsi(mi_string);
1493 break;
1494 case GSM_MI_TYPE_IMSI:
1495 subscr = subscr_get_by_imsi(mi_string);
1496 break;
1497 case GSM_MI_TYPE_IMEI:
1498 case GSM_MI_TYPE_IMEISV:
1499 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001500 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001501 break;
1502 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001503 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001504 break;
1505 }
1506
Holger Freyther4a49e772009-04-12 05:37:29 +00001507 if (subscr) {
1508 subscr_update(subscr, msg->trx->bts,
1509 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001510 DEBUGP(DMM, "Subscriber: %s\n",
1511 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001512 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001513 } else
Harald Welte2a139372009-02-22 21:14:55 +00001514 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1515
Harald Welte2a139372009-02-22 21:14:55 +00001516 return 0;
1517}
1518
Harald Welted2a7f5a2009-06-05 20:08:20 +00001519static int gsm48_rx_mm_status(struct msgb *msg)
1520{
1521 struct gsm48_hdr *gh = msgb_l3(msg);
1522
1523 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1524
1525 return 0;
1526}
1527
Harald Weltebf5e8df2009-02-03 12:59:45 +00001528/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001529static int gsm0408_rcv_mm(struct msgb *msg)
1530{
1531 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001532 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001533
1534 switch (gh->msg_type & 0xbf) {
1535 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +00001536 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001537 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001538 break;
1539 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001540 rc = mm_rx_id_resp(msg);
1541 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001542 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001543 rc = gsm48_rx_mm_serv_req(msg);
1544 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001545 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001546 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001547 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001548 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001549 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1550 msg->lchan->subscr ?
1551 msg->lchan->subscr->imsi :
1552 "unknown subscriber");
1553 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001554 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001555 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1556 break;
1557 case GSM48_MT_MM_CM_REEST_REQ:
1558 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1559 break;
1560 case GSM48_MT_MM_AUTH_RESP:
1561 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001562 break;
1563 default:
1564 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1565 gh->msg_type);
1566 break;
1567 }
1568
1569 return rc;
1570}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001571
Harald Welte2d35ae62009-02-06 12:02:13 +00001572/* Receive a PAGING RESPONSE message from the MS */
1573static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1574{
1575 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001576 u_int8_t *classmark2_lv = gh->data + 1;
1577 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1578 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001579 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001580 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001581 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001582 int rc = 0;
1583
Harald Welte61548982009-02-22 21:26:29 +00001584 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001585 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1586 mi_type, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001587 switch (mi_type) {
1588 case GSM_MI_TYPE_TMSI:
1589 subscr = subscr_get_by_tmsi(mi_string);
1590 break;
1591 case GSM_MI_TYPE_IMSI:
1592 subscr = subscr_get_by_imsi(mi_string);
1593 break;
1594 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001595
1596 if (!subscr) {
1597 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001598 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001599 return -EINVAL;
1600 }
1601 DEBUGP(DRR, "<- Channel was requested by %s\n",
1602 subscr->name ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001603
Harald Weltef7c43522009-06-09 20:24:21 +00001604 subscr->classmark2_len = *classmark2_lv;
1605 memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv);
1606
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001607 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001608 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001609 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001610 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1611 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001612 return -EINVAL;
1613 } else {
1614 DEBUGP(DRR, "<- Channel already owned by us\n");
1615 subscr_put(subscr);
1616 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001617 }
1618
Harald Welte595ad7b2009-02-16 22:05:44 +00001619 sig_data.subscr = subscr;
1620 sig_data.bts = msg->lchan->ts->trx->bts;
1621 sig_data.lchan = msg->lchan;
1622
1623 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001624
1625 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001626 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001627
Harald Welte7584aea2009-02-11 11:44:12 +00001628 /* FIXME: somehow signal the completion of the PAGING to
1629 * the entity that requested the paging */
1630
Harald Welte2d35ae62009-02-06 12:02:13 +00001631 return rc;
1632}
1633
Harald Weltef7c43522009-06-09 20:24:21 +00001634static int gsm48_rx_rr_classmark(struct msgb *msg)
1635{
1636 struct gsm48_hdr *gh = msgb_l3(msg);
1637 struct gsm_subscriber *subscr = msg->lchan->subscr;
1638 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1639 u_int8_t cm2_len, cm3_len = 0;
1640 u_int8_t *cm2, *cm3 = NULL;
1641
1642 DEBUGP(DRR, "CLASSMARK CHANGE ");
1643
1644 /* classmark 2 */
1645 cm2_len = gh->data[0];
1646 cm2 = &gh->data[1];
1647 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1648
1649 if (payload_len > cm2_len + 1) {
1650 /* we must have a classmark3 */
1651 if (gh->data[cm2_len+1] != 0x20) {
1652 DEBUGPC(DRR, "ERR CM3 TAG\n");
1653 return -EINVAL;
1654 }
1655 if (cm2_len > 3) {
1656 DEBUGPC(DRR, "CM2 too long!\n");
1657 return -EINVAL;
1658 }
1659
1660 cm3_len = gh->data[cm2_len+2];
1661 cm3 = &gh->data[cm2_len+3];
1662 if (cm3_len > 14) {
1663 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1664 return -EINVAL;
1665 }
1666 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1667 }
1668 if (subscr) {
1669 subscr->classmark2_len = cm2_len;
1670 memcpy(subscr->classmark2, cm2, cm2_len);
1671 if (cm3) {
1672 subscr->classmark3_len = cm3_len;
1673 memcpy(subscr->classmark3, cm3, cm3_len);
1674 }
1675 }
1676
1677 /* FIXME: store the classmark2/3 values with the equipment register */
1678
1679 return 0;
1680}
1681
Harald Weltecf5b3592009-05-01 18:28:42 +00001682static int gsm48_rx_rr_status(struct msgb *msg)
1683{
1684 struct gsm48_hdr *gh = msgb_l3(msg);
1685
1686 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1687 rr_cause_name(gh->data[0]));
1688
1689 return 0;
1690}
1691
Harald Weltef7c43522009-06-09 20:24:21 +00001692static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1693{
1694 struct gsm48_hdr *gh = msgb_l3(msg);
1695 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1696 static struct gsm_meas_rep meas_rep;
1697
1698 DEBUGP(DRR, "MEASUREMENT REPORT ");
1699 parse_meas_rep(&meas_rep, gh->data, payload_len);
1700 if (meas_rep.flags & MEAS_REP_F_DTX)
1701 DEBUGPC(DRR, "DTX ");
1702 if (meas_rep.flags & MEAS_REP_F_BA1)
1703 DEBUGPC(DRR, "BA1 ");
1704 if (!(meas_rep.flags & MEAS_REP_F_VALID))
1705 DEBUGPC(DRR, "NOT VALID ");
1706 else
1707 DEBUGPC(DRR, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
1708 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1709 meas_rep.rxqual_sub);
1710
1711 DEBUGPC(DRR, "NUM_NEIGH=%u\n", meas_rep.num_cell);
1712
1713 /* FIXME: put the results somwhere */
1714
1715 return 0;
1716}
1717
Harald Weltebf5e8df2009-02-03 12:59:45 +00001718/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001719static int gsm0408_rcv_rr(struct msgb *msg)
1720{
1721 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001722 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001723
1724 switch (gh->msg_type) {
1725 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001726 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001727 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001728 case GSM48_MT_RR_GPRS_SUSP_REQ:
1729 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1730 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001731 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001732 rc = gsm48_rr_rx_pag_resp(msg);
1733 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001734 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1735 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte2c38aa82009-02-18 03:44:24 +00001736 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001737 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001738 case GSM48_MT_RR_STATUS:
1739 rc = gsm48_rx_rr_status(msg);
1740 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001741 case GSM48_MT_RR_MEAS_REP:
1742 rc = gsm48_rx_rr_meas_rep(msg);
1743 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001744 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001745 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001746 gh->msg_type);
1747 break;
1748 }
1749
Harald Welte2d35ae62009-02-06 12:02:13 +00001750 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001751}
1752
Holger Freythere64a7a32009-02-06 21:55:37 +00001753/* 7.1.7 and 9.1.7 Channel release*/
1754int gsm48_send_rr_release(struct gsm_lchan *lchan)
1755{
1756 struct msgb *msg = gsm48_msgb_alloc();
1757 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1758 u_int8_t *cause;
1759
1760 msg->lchan = lchan;
1761 gh->proto_discr = GSM48_PDISC_RR;
1762 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1763
1764 cause = msgb_put(msg, 1);
1765 cause[0] = GSM48_RR_CAUSE_NORMAL;
1766
1767 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1768 lchan->nr, lchan->type);
1769
1770 return gsm48_sendmsg(msg);
1771}
1772
Harald Welte4bc90a12008-12-27 16:32:52 +00001773/* Call Control */
1774
Harald Welte7584aea2009-02-11 11:44:12 +00001775/* The entire call control code is written in accordance with Figure 7.10c
1776 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1777 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1778 * it for voice */
1779
Harald Welte4bfdfe72009-06-10 23:11:52 +08001780static void new_cc_state(struct gsm_trans *trans, int state)
1781{
1782 if (state > 31 || state < 0)
1783 return;
1784
1785 DEBUGP(DCC, "new state %s -> %s\n",
1786 cc_state_names[trans->state], cc_state_names[state]);
1787
1788 trans->state = state;
1789}
1790
1791static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001792{
1793 struct msgb *msg = gsm48_msgb_alloc();
1794 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1795 u_int8_t *cause, *call_state;
1796
Harald Welte4bfdfe72009-06-10 23:11:52 +08001797 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
1798 msg->lchan = trans->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001799 gh->msg_type = GSM48_MT_CC_STATUS;
1800
1801 cause = msgb_put(msg, 3);
1802 cause[0] = 2;
1803 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1804 cause[2] = 0x80 | 30; /* response to status inquiry */
1805
1806 call_state = msgb_put(msg, 1);
1807 call_state[0] = 0xc0 | 0x00;
1808
Harald Welte65e74cc2008-12-29 01:55:35 +00001809 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001810}
1811
Harald Welte6f4b7532008-12-29 00:39:37 +00001812static int gsm48_tx_simple(struct gsm_lchan *lchan,
1813 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001814{
1815 struct msgb *msg = gsm48_msgb_alloc();
1816 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1817
1818 msg->lchan = lchan;
1819
Harald Welte6f4b7532008-12-29 00:39:37 +00001820 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001821 gh->msg_type = msg_type;
1822
Harald Welte65e74cc2008-12-29 01:55:35 +00001823 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00001824}
1825
Harald Welte4bfdfe72009-06-10 23:11:52 +08001826static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1827{
1828 if (bsc_timer_pending(&trans->cc_timer)) {
1829 DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
1830 bsc_del_timer(&trans->cc_timer);
1831 trans->Tcurrent = 0;
1832 }
1833}
1834
1835static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1836 int msg_type, struct gsm_mncc *mncc)
1837{
1838 struct msgb *msg;
1839
1840 if (trans)
1841 if (trans->lchan)
1842 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
1843 "Sending '%s' to MNCC.\n",
1844 trans->lchan->ts->trx->bts->nr,
1845 trans->lchan->ts->trx->nr,
1846 trans->lchan->ts->nr, trans->transaction_id,
1847 (trans->subscr)?(trans->subscr->extension):"-",
1848 get_mncc_name(msg_type));
1849 else
1850 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1851 "Sending '%s' to MNCC.\n",
1852 (trans->subscr)?(trans->subscr->extension):"-",
1853 get_mncc_name(msg_type));
1854 else
1855 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1856 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1857
1858 mncc->msg_type = msg_type;
1859
Harald Welte966636f2009-06-26 19:39:35 +02001860 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001861 if (!msg)
1862 return -ENOMEM;
1863 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1864 msgb_enqueue(&net->upqueue, msg);
1865
1866 return 0;
1867}
1868
1869int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1870 u_int32_t callref, int location, int value)
1871{
1872 struct gsm_mncc rel;
1873
Harald Welte92f70c52009-06-12 01:54:08 +08001874 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001875 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001876 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001877 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1878}
1879
1880void free_trans(struct gsm_trans *trans)
1881{
1882 struct gsm_bts *bts;
1883
1884 gsm48_stop_cc_timer(trans);
1885
1886 /* send release to L4, if callref still exists */
1887 if (trans->callref) {
1888 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001889 mncc_release_ind(trans->network, trans, trans->callref,
1890 GSM48_CAUSE_LOC_PRN_S_LU,
1891 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001892 if (trans->state != GSM_CSTATE_NULL)
1893 new_cc_state(trans, GSM_CSTATE_NULL);
1894 }
1895
1896 if (!trans->lchan && trans->subscr && trans->subscr->net) {
1897 /* Stop paging on all bts' */
1898 bts = NULL;
1899 do {
1900 bts = gsm_bts_by_lac(trans->subscr->net,
1901 trans->subscr->lac, bts);
1902 if (!bts)
1903 break;
1904 /* Stop paging */
1905 paging_request_stop(bts, trans->subscr, NULL);
1906 } while (1);
1907 }
1908
1909 if (trans->lchan) {
1910 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
1911 put_lchan(trans->lchan);
1912 }
1913
1914 if (trans->subscr)
1915 subscr_put(trans->subscr);
1916
1917 if (trans->state != GSM_CSTATE_NULL)
1918 new_cc_state(trans, GSM_CSTATE_NULL);
1919
1920 llist_del(&trans->entry);
1921
Harald Welte2cf161b2009-06-20 22:36:41 +02001922 talloc_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001923}
1924
1925static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1926
Harald Welte09e38af2009-02-16 22:52:23 +00001927/* call-back from paging the B-end of the connection */
1928static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001929 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001930{
Harald Welte7ccf7782009-02-17 01:43:01 +00001931 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001932 struct gsm_subscriber *subscr = param;
1933 struct gsm_trans *transt, *tmp;
1934 struct gsm_network *net;
1935
Harald Welte09e38af2009-02-16 22:52:23 +00001936 if (hooknum != GSM_HOOK_RR_PAGING)
1937 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001938
1939 if (!subscr)
1940 return -EINVAL;
1941 net = subscr->net;
1942 if (!net) {
1943 DEBUGP(DCC, "Error Network not set!\n");
1944 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001945 }
Harald Welte7584aea2009-02-11 11:44:12 +00001946
Harald Welte4bfdfe72009-06-10 23:11:52 +08001947 /* check all tranactions (without lchan) for subscriber */
1948 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1949 if (transt->subscr != subscr || transt->lchan)
1950 continue;
1951 switch (event) {
1952 case GSM_PAGING_SUCCEEDED:
1953 if (!lchan) // paranoid
1954 break;
1955 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1956 subscr->extension);
1957 /* Assign lchan */
1958 if (!transt->lchan) {
1959 transt->lchan = lchan;
1960 use_lchan(lchan);
1961 }
1962 /* send SETUP request to called party */
1963 gsm48_cc_tx_setup(transt, &transt->cc_msg);
1964 if (is_ipaccess_bts(lchan->ts->trx->bts))
1965 rsl_ipacc_bind(lchan);
1966 break;
1967 case GSM_PAGING_EXPIRED:
1968 DEBUGP(DCC, "Paging subscr %s expired!\n",
1969 subscr->extension);
1970 /* Temporarily out of order */
1971 mncc_release_ind(transt->network, transt, transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001972 GSM48_CAUSE_LOC_PRN_S_LU,
1973 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001974 transt->callref = 0;
1975 free_trans(transt);
1976 break;
1977 }
1978 }
Harald Welte09e38af2009-02-16 22:52:23 +00001979 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001980}
Harald Welte7584aea2009-02-11 11:44:12 +00001981
Harald Welte49f48b82009-02-17 15:29:33 +00001982/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001983static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001984{
Harald Welte11fa29c2009-02-19 17:24:39 +00001985 struct gsm_bts *bts = lchan->ts->trx->bts;
1986 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00001987 struct gsm_bts_trx_ts *ts;
1988
Harald Welte11fa29c2009-02-19 17:24:39 +00001989 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1990 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1991 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1992
1993 if (bts->type != remote_bts->type) {
1994 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
1995 return -EINVAL;
1996 }
Harald Welte49f48b82009-02-17 15:29:33 +00001997
Harald Welte11fa29c2009-02-19 17:24:39 +00001998 switch (bts->type) {
1999 case GSM_BTS_TYPE_NANOBTS_900:
2000 case GSM_BTS_TYPE_NANOBTS_1800:
2001 ts = remote_lchan->ts;
2002 rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2003 lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2004
2005 ts = lchan->ts;
2006 rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip, ts->abis_ip.bound_port,
2007 remote_lchan->ts->abis_ip.attr_f8, ts->abis_ip.attr_fc);
2008 break;
2009 case GSM_BTS_TYPE_BS11:
2010 trau_mux_map_lchan(lchan, remote_lchan);
2011 break;
2012 default:
2013 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
2014 break;
2015 }
Harald Welte49f48b82009-02-17 15:29:33 +00002016
2017 return 0;
2018}
2019
Harald Welte4bfdfe72009-06-10 23:11:52 +08002020static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
Harald Welte7ccf7782009-02-17 01:43:01 +00002021{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022 struct gsm_trans *trans;
2023 llist_for_each_entry(trans, &net->trans_list, entry) {
2024 if (trans->callref == callref)
2025 return trans;
2026 }
2027 return NULL;
Harald Welte7ccf7782009-02-17 01:43:01 +00002028}
2029
Harald Welte4bfdfe72009-06-10 23:11:52 +08002030/* bridge channels of two transactions */
2031static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002032{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002033 struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
2034 struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002035
Harald Welte4bfdfe72009-06-10 23:11:52 +08002036 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002037 return -EIO;
2038
Harald Welte4bfdfe72009-06-10 23:11:52 +08002039 if (!trans1->lchan || !trans2->lchan)
2040 return -EIO;
2041
2042 /* through-connect channel */
2043 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002044}
2045
Harald Welte4bfdfe72009-06-10 23:11:52 +08002046/* enable receive of channels to upqueue */
2047static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2048{
2049 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002050
Harald Welte4bfdfe72009-06-10 23:11:52 +08002051 /* Find callref */
2052 trans = get_trans_ref(net, data->callref);
2053 if (!trans)
2054 return -EIO;
2055 if (!trans->lchan)
2056 return 0;
2057
2058 // todo IPACCESS
2059 if (enable)
2060 return trau_recv_lchan(trans->lchan, data->callref);
2061 return trau_mux_unmap(NULL, data->callref);
2062}
2063
2064/* send a frame to channel */
2065static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2066{
2067 struct gsm_trans *trans;
2068
2069 /* Find callref */
2070 trans = get_trans_ref(net, frame->callref);
2071 if (!trans)
2072 return -EIO;
2073 if (!trans->lchan)
2074 return 0;
2075 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2076 trans->lchan->type != GSM_LCHAN_TCH_H)
2077 return 0;
2078
2079 // todo IPACCESS
2080 return trau_send_lchan(trans->lchan,
2081 (struct decoded_trau_frame *)frame->data);
2082}
2083
2084
2085static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2086{
2087 DEBUGP(DCC, "-> STATUS ENQ\n");
2088 return gsm48_cc_tx_status(trans, msg);
2089}
2090
2091static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2092static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2093
2094static void gsm48_cc_timeout(void *arg)
2095{
2096 struct gsm_trans *trans = arg;
2097 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002098 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2099 int mo_location = GSM48_CAUSE_LOC_USER;
2100 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2101 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002102 struct gsm_mncc mo_rel, l4_rel;
2103
2104 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2105 mo_rel.callref = trans->callref;
2106 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2107 l4_rel.callref = trans->callref;
2108
2109 switch(trans->Tcurrent) {
2110 case 0x303:
2111 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002112 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002113 break;
2114 case 0x310:
2115 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002116 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002117 break;
2118 case 0x313:
2119 disconnect = 1;
2120 /* unknown, did not find it in the specs */
2121 break;
2122 case 0x301:
2123 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002124 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002125 break;
2126 case 0x308:
2127 if (!trans->T308_second) {
2128 /* restart T308 a second time */
2129 gsm48_cc_tx_release(trans, &trans->cc_msg);
2130 trans->T308_second = 1;
2131 break; /* stay in release state */
2132 }
2133 free_trans(trans);
2134 return;
2135// release = 1;
2136// l4_cause = 14;
2137// break;
2138 case 0x306:
2139 release = 1;
2140 mo_cause = trans->cc_msg.cause.value;
2141 mo_location = trans->cc_msg.cause.location;
2142 break;
2143 case 0x323:
2144 disconnect = 1;
2145 break;
2146 default:
2147 release = 1;
2148 }
2149
2150 if (release && trans->callref) {
2151 /* process release towards layer 4 */
2152 mncc_release_ind(trans->network, trans, trans->callref,
2153 l4_location, l4_cause);
2154 trans->callref = 0;
2155 }
2156
2157 if (disconnect && trans->callref) {
2158 /* process disconnect towards layer 4 */
2159 mncc_set_cause(&l4_rel, l4_location, l4_cause);
2160 mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
2161 }
2162
2163 /* process disconnect towards mobile station */
2164 if (disconnect || release) {
2165 mncc_set_cause(&mo_rel, mo_location, mo_cause);
2166 mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
2167 mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
2168 mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
2169 mo_rel.cause.diag_len = 3;
2170
2171 if (disconnect)
2172 gsm48_cc_tx_disconnect(trans, &mo_rel);
2173 if (release)
2174 gsm48_cc_tx_release(trans, &mo_rel);
2175 }
2176
2177}
2178
2179static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2180 int sec, int micro)
2181{
2182 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
2183 trans->cc_timer.cb = gsm48_cc_timeout;
2184 trans->cc_timer.data = trans;
2185 bsc_schedule_timer(&trans->cc_timer, sec, micro);
2186 trans->Tcurrent = current;
2187}
2188
2189static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2190{
2191 struct gsm48_hdr *gh = msgb_l3(msg);
2192 u_int8_t msg_type = gh->msg_type & 0xbf;
2193 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2194 struct tlv_parsed tp;
2195 struct gsm_mncc setup;
2196
2197 memset(&setup, 0, sizeof(struct gsm_mncc));
2198 setup.callref = trans->callref;
2199 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2200 /* emergency setup is identified by msg_type */
2201 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2202 setup.emergency = 1;
2203
2204 /* use subscriber as calling party number */
2205 if (trans->subscr) {
2206 setup.fields |= MNCC_F_CALLING;
2207 strncpy(setup.calling.number, trans->subscr->extension,
2208 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002209 strncpy(setup.imsi, trans->subscr->imsi,
2210 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002211 }
2212 /* bearer capability */
2213 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2214 setup.fields |= MNCC_F_BEARER_CAP;
2215 decode_bearer_cap(&setup.bearer_cap,
2216 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2217 }
2218 /* facility */
2219 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2220 setup.fields |= MNCC_F_FACILITY;
2221 decode_facility(&setup.facility,
2222 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2223 }
2224 /* called party bcd number */
2225 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2226 setup.fields |= MNCC_F_CALLED;
2227 decode_called(&setup.called,
2228 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2229 }
2230 /* user-user */
2231 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2232 setup.fields |= MNCC_F_USERUSER;
2233 decode_useruser(&setup.useruser,
2234 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2235 }
2236 /* ss-version */
2237 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2238 setup.fields |= MNCC_F_SSVERSION;
2239 decode_ssversion(&setup.ssversion,
2240 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2241 }
2242 /* CLIR suppression */
2243 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2244 setup.clir.sup = 1;
2245 /* CLIR invocation */
2246 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2247 setup.clir.inv = 1;
2248 /* cc cap */
2249 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2250 setup.fields |= MNCC_F_CCCAP;
2251 decode_cccap(&setup.cccap,
2252 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2253 }
2254
2255 if (is_ipaccess_bts(msg->trx->bts))
2256 rsl_ipacc_bind(msg->lchan);
2257
2258 new_cc_state(trans, GSM_CSTATE_INITIATED);
2259
2260 /* indicate setup to MNCC */
2261 mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
2262
2263 return 0;
2264}
2265
2266static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002267{
2268 struct msgb *msg = gsm48_msgb_alloc();
2269 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002270 struct gsm_mncc *setup = arg;
2271 struct gsm_trans *transt;
2272 u_int16_t trans_id_mask = 0;
2273 int rc, i;
Harald Welte65e74cc2008-12-29 01:55:35 +00002274
Harald Welte7ccf7782009-02-17 01:43:01 +00002275 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002276
Harald Welte4bfdfe72009-06-10 23:11:52 +08002277 /* transaction id must not be assigned */
2278 if (trans->transaction_id != 0xff) { /* unasssigned */
2279 DEBUGP(DCC, "TX Setup with assigned transaction. "
2280 "This is not allowed!\n");
2281 /* Temporarily out of order */
2282 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002283 GSM48_CAUSE_LOC_PRN_S_LU,
2284 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002285 trans->callref = 0;
2286 free_trans(trans);
2287 return rc;
2288 }
2289
2290 /* Get free transaction_id */
2291 llist_for_each_entry(transt, &trans->network->trans_list, entry) {
2292 /* Transaction of our lchan? */
2293 if (transt->lchan == trans->lchan &&
2294 transt->transaction_id != 0xff)
2295 trans_id_mask |= (1 << (transt->transaction_id >> 4));
2296 }
2297 /* Assign free transaction ID */
2298 if ((trans_id_mask & 0x007f) == 0x7f) {
2299 /* no free transaction ID */
2300 rc = mncc_release_ind(trans->network, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002301 GSM48_CAUSE_LOC_PRN_S_LU,
2302 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002303 trans->callref = 0;
2304 free_trans(trans);
2305 return rc;
2306 }
2307 for (i = 0; i < 7; i++) {
2308 if ((trans_id_mask & (1 << i)) == 0) {
2309 trans->transaction_id = i << 4; /* flag = 0 */
2310 break;
2311 }
2312 }
Harald Welte49f48b82009-02-17 15:29:33 +00002313
Harald Welte4bfdfe72009-06-10 23:11:52 +08002314 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2315 msg->lchan = trans->lchan;
Harald Welte65e74cc2008-12-29 01:55:35 +00002316 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002317
Harald Welte4bfdfe72009-06-10 23:11:52 +08002318 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002319
Harald Welte4bfdfe72009-06-10 23:11:52 +08002320 /* bearer capability */
2321 if (setup->fields & MNCC_F_BEARER_CAP)
2322 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2323 /* facility */
2324 if (setup->fields & MNCC_F_FACILITY)
2325 encode_facility(msg, 0, &setup->facility);
2326 /* progress */
2327 if (setup->fields & MNCC_F_PROGRESS)
2328 encode_progress(msg, 0, &setup->progress);
2329 /* calling party BCD number */
2330 if (setup->fields & MNCC_F_CALLING)
2331 encode_calling(msg, &setup->calling);
2332 /* called party BCD number */
2333 if (setup->fields & MNCC_F_CALLED)
2334 encode_called(msg, &setup->called);
2335 /* user-user */
2336 if (setup->fields & MNCC_F_USERUSER)
2337 encode_useruser(msg, 0, &setup->useruser);
2338 /* redirecting party BCD number */
2339 if (setup->fields & MNCC_F_REDIRECTING)
2340 encode_redirecting(msg, &setup->redirecting);
2341 /* signal */
2342 if (setup->fields & MNCC_F_SIGNAL)
2343 encode_signal(msg, setup->signal);
2344
2345 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002346
2347 return gsm48_sendmsg(msg);
2348}
2349
Harald Welte4bfdfe72009-06-10 23:11:52 +08002350static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2351{
2352 struct gsm48_hdr *gh = msgb_l3(msg);
2353 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2354 struct tlv_parsed tp;
2355 struct gsm_mncc call_conf;
2356
2357 gsm48_stop_cc_timer(trans);
2358 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2359
2360 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2361 call_conf.callref = trans->callref;
2362 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2363#if 0
2364 /* repeat */
2365 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2366 call_conf.repeat = 1;
2367 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2368 call_conf.repeat = 2;
2369#endif
2370 /* bearer capability */
2371 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2372 call_conf.fields |= MNCC_F_BEARER_CAP;
2373 decode_bearer_cap(&call_conf.bearer_cap,
2374 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2375 }
2376 /* cause */
2377 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2378 call_conf.fields |= MNCC_F_CAUSE;
2379 decode_cause(&call_conf.cause,
2380 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2381 }
2382 /* cc cap */
2383 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2384 call_conf.fields |= MNCC_F_CCCAP;
2385 decode_cccap(&call_conf.cccap,
2386 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2387 }
2388
2389 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2390
2391 return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
2392}
2393
2394static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2395{
2396 struct gsm_mncc *proceeding = arg;
2397 struct msgb *msg = gsm48_msgb_alloc();
2398 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2399
2400 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2401 msg->lchan = trans->lchan;
2402 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2403
2404 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2405
2406 /* bearer capability */
2407 if (proceeding->fields & MNCC_F_BEARER_CAP)
2408 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2409 /* facility */
2410 if (proceeding->fields & MNCC_F_FACILITY)
2411 encode_facility(msg, 0, &proceeding->facility);
2412 /* progress */
2413 if (proceeding->fields & MNCC_F_PROGRESS)
2414 encode_progress(msg, 0, &proceeding->progress);
2415
2416 return gsm48_sendmsg(msg);
2417}
2418
2419static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2420{
2421 struct gsm48_hdr *gh = msgb_l3(msg);
2422 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2423 struct tlv_parsed tp;
2424 struct gsm_mncc alerting;
2425
2426 gsm48_stop_cc_timer(trans);
2427 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2428
2429 memset(&alerting, 0, sizeof(struct gsm_mncc));
2430 alerting.callref = trans->callref;
2431 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2432 /* facility */
2433 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2434 alerting.fields |= MNCC_F_FACILITY;
2435 decode_facility(&alerting.facility,
2436 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2437 }
2438
2439 /* progress */
2440 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2441 alerting.fields |= MNCC_F_PROGRESS;
2442 decode_progress(&alerting.progress,
2443 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2444 }
2445 /* ss-version */
2446 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2447 alerting.fields |= MNCC_F_SSVERSION;
2448 decode_ssversion(&alerting.ssversion,
2449 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2450 }
2451
2452 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2453
2454 return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
2455}
2456
2457static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2458{
2459 struct gsm_mncc *alerting = arg;
2460 struct msgb *msg = gsm48_msgb_alloc();
2461 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2462
2463 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2464 msg->lchan = trans->lchan;
2465 gh->msg_type = GSM48_MT_CC_ALERTING;
2466
2467 /* facility */
2468 if (alerting->fields & MNCC_F_FACILITY)
2469 encode_facility(msg, 0, &alerting->facility);
2470 /* progress */
2471 if (alerting->fields & MNCC_F_PROGRESS)
2472 encode_progress(msg, 0, &alerting->progress);
2473 /* user-user */
2474 if (alerting->fields & MNCC_F_USERUSER)
2475 encode_useruser(msg, 0, &alerting->useruser);
2476
2477 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2478
2479 return gsm48_sendmsg(msg);
2480}
2481
2482static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2483{
2484 struct gsm_mncc *progress = arg;
2485 struct msgb *msg = gsm48_msgb_alloc();
2486 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2487
2488 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2489 msg->lchan = trans->lchan;
2490 gh->msg_type = GSM48_MT_CC_PROGRESS;
2491
2492 /* progress */
2493 encode_progress(msg, 1, &progress->progress);
2494 /* user-user */
2495 if (progress->fields & MNCC_F_USERUSER)
2496 encode_useruser(msg, 0, &progress->useruser);
2497
2498 return gsm48_sendmsg(msg);
2499}
2500
2501static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2502{
2503 struct gsm_mncc *connect = arg;
2504 struct msgb *msg = gsm48_msgb_alloc();
2505 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2506
2507 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2508 msg->lchan = trans->lchan;
2509 gh->msg_type = GSM48_MT_CC_CONNECT;
2510
2511 gsm48_stop_cc_timer(trans);
2512 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2513
2514 /* facility */
2515 if (connect->fields & MNCC_F_FACILITY)
2516 encode_facility(msg, 0, &connect->facility);
2517 /* progress */
2518 if (connect->fields & MNCC_F_PROGRESS)
2519 encode_progress(msg, 0, &connect->progress);
2520 /* connected number */
2521 if (connect->fields & MNCC_F_CONNECTED)
2522 encode_connected(msg, &connect->connected);
2523 /* user-user */
2524 if (connect->fields & MNCC_F_USERUSER)
2525 encode_useruser(msg, 0, &connect->useruser);
2526
2527 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2528
2529 return gsm48_sendmsg(msg);
2530}
2531
2532static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2533{
2534 struct gsm48_hdr *gh = msgb_l3(msg);
2535 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2536 struct tlv_parsed tp;
2537 struct gsm_mncc connect;
2538
2539 gsm48_stop_cc_timer(trans);
2540
2541 memset(&connect, 0, sizeof(struct gsm_mncc));
2542 connect.callref = trans->callref;
2543 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2544 /* use subscriber as connected party number */
2545 if (trans->subscr) {
2546 connect.fields |= MNCC_F_CONNECTED;
2547 strncpy(connect.connected.number, trans->subscr->extension,
2548 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002549 strncpy(connect.imsi, trans->subscr->imsi,
2550 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002551 }
2552 /* facility */
2553 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2554 connect.fields |= MNCC_F_FACILITY;
2555 decode_facility(&connect.facility,
2556 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2557 }
2558 /* user-user */
2559 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2560 connect.fields |= MNCC_F_USERUSER;
2561 decode_useruser(&connect.useruser,
2562 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2563 }
2564 /* ss-version */
2565 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2566 connect.fields |= MNCC_F_SSVERSION;
2567 decode_ssversion(&connect.ssversion,
2568 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2569 }
2570
2571 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2572
2573 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
2574}
2575
2576
2577static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2578{
2579 struct gsm_mncc connect_ack;
2580
2581 gsm48_stop_cc_timer(trans);
2582
2583 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2584
2585 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2586 connect_ack.callref = trans->callref;
2587 return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
2588 &connect_ack);
2589}
2590
2591static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2592{
2593 struct msgb *msg = gsm48_msgb_alloc();
2594 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2595
2596 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2597 msg->lchan = trans->lchan;
2598 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2599
2600 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2601
2602 return gsm48_sendmsg(msg);
2603}
2604
2605static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2606{
2607 struct gsm48_hdr *gh = msgb_l3(msg);
2608 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2609 struct tlv_parsed tp;
2610 struct gsm_mncc disc;
2611
2612 gsm48_stop_cc_timer(trans);
2613
2614 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2615
2616 memset(&disc, 0, sizeof(struct gsm_mncc));
2617 disc.callref = trans->callref;
2618 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2619 /* cause */
2620 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2621 disc.fields |= MNCC_F_CAUSE;
2622 decode_cause(&disc.cause,
2623 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2624 }
2625 /* facility */
2626 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2627 disc.fields |= MNCC_F_FACILITY;
2628 decode_facility(&disc.facility,
2629 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2630 }
2631 /* user-user */
2632 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2633 disc.fields |= MNCC_F_USERUSER;
2634 decode_useruser(&disc.useruser,
2635 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2636 }
2637 /* ss-version */
2638 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2639 disc.fields |= MNCC_F_SSVERSION;
2640 decode_ssversion(&disc.ssversion,
2641 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2642 }
2643
2644 return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
2645
2646}
2647
Harald Weltec66b71c2009-06-11 14:23:20 +08002648static struct gsm_mncc_cause default_cause = {
2649 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2650 .coding = 0,
2651 .rec = 0,
2652 .rec_val = 0,
2653 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2654 .diag_len = 0,
2655 .diag = { 0 },
2656};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002657
2658static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2659{
2660 struct gsm_mncc *disc = arg;
2661 struct msgb *msg = gsm48_msgb_alloc();
2662 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2663
2664 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2665 msg->lchan = trans->lchan;
2666 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2667
2668 gsm48_stop_cc_timer(trans);
2669 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2670
2671 /* cause */
2672 if (disc->fields & MNCC_F_CAUSE)
2673 encode_cause(msg, 1, &disc->cause);
2674 else
2675 encode_cause(msg, 1, &default_cause);
2676
2677 /* facility */
2678 if (disc->fields & MNCC_F_FACILITY)
2679 encode_facility(msg, 0, &disc->facility);
2680 /* progress */
2681 if (disc->fields & MNCC_F_PROGRESS)
2682 encode_progress(msg, 0, &disc->progress);
2683 /* user-user */
2684 if (disc->fields & MNCC_F_USERUSER)
2685 encode_useruser(msg, 0, &disc->useruser);
2686
2687 /* store disconnect cause for T306 expiry */
2688 memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
2689
2690 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2691
2692 return gsm48_sendmsg(msg);
2693}
2694
2695static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2696{
2697 struct gsm48_hdr *gh = msgb_l3(msg);
2698 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2699 struct tlv_parsed tp;
2700 struct gsm_mncc rel;
2701 int rc;
2702
2703 gsm48_stop_cc_timer(trans);
2704
2705 memset(&rel, 0, sizeof(struct gsm_mncc));
2706 rel.callref = trans->callref;
2707 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2708 /* cause */
2709 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2710 rel.fields |= MNCC_F_CAUSE;
2711 decode_cause(&rel.cause,
2712 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2713 }
2714 /* facility */
2715 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2716 rel.fields |= MNCC_F_FACILITY;
2717 decode_facility(&rel.facility,
2718 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2719 }
2720 /* user-user */
2721 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2722 rel.fields |= MNCC_F_USERUSER;
2723 decode_useruser(&rel.useruser,
2724 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2725 }
2726 /* ss-version */
2727 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2728 rel.fields |= MNCC_F_SSVERSION;
2729 decode_ssversion(&rel.ssversion,
2730 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2731 }
2732
2733 if (trans->state == GSM_CSTATE_RELEASE_REQ) {
2734 /* release collision 5.4.5 */
2735 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
2736 } else {
2737 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
2738 GSM48_MT_CC_RELEASE_COMPL);
2739 rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
2740 }
2741
2742 new_cc_state(trans, GSM_CSTATE_NULL);
2743
2744 trans->callref = 0;
2745 free_trans(trans);
2746
2747 return rc;
2748}
2749
2750static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2751{
2752 struct gsm_mncc *rel = arg;
2753 struct msgb *msg = gsm48_msgb_alloc();
2754 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2755
2756 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2757 msg->lchan = trans->lchan;
2758 gh->msg_type = GSM48_MT_CC_RELEASE;
2759
2760 trans->callref = 0;
2761
2762 gsm48_stop_cc_timer(trans);
2763 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2764
2765 /* cause */
2766 if (rel->fields & MNCC_F_CAUSE)
2767 encode_cause(msg, 0, &rel->cause);
2768 /* facility */
2769 if (rel->fields & MNCC_F_FACILITY)
2770 encode_facility(msg, 0, &rel->facility);
2771 /* user-user */
2772 if (rel->fields & MNCC_F_USERUSER)
2773 encode_useruser(msg, 0, &rel->useruser);
2774
2775 trans->T308_second = 0;
2776 memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
2777
2778 if (trans->state != GSM_CSTATE_RELEASE_REQ)
2779 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2780
2781 return gsm48_sendmsg(msg);
2782}
2783
2784static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2785{
2786 struct gsm48_hdr *gh = msgb_l3(msg);
2787 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2788 struct tlv_parsed tp;
2789 struct gsm_mncc rel;
2790 int rc = 0;
2791
2792 gsm48_stop_cc_timer(trans);
2793
2794 memset(&rel, 0, sizeof(struct gsm_mncc));
2795 rel.callref = trans->callref;
2796 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2797 /* cause */
2798 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2799 rel.fields |= MNCC_F_CAUSE;
2800 decode_cause(&rel.cause,
2801 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2802 }
2803 /* facility */
2804 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2805 rel.fields |= MNCC_F_FACILITY;
2806 decode_facility(&rel.facility,
2807 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2808 }
2809 /* user-user */
2810 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2811 rel.fields |= MNCC_F_USERUSER;
2812 decode_useruser(&rel.useruser,
2813 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2814 }
2815 /* ss-version */
2816 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2817 rel.fields |= MNCC_F_SSVERSION;
2818 decode_ssversion(&rel.ssversion,
2819 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2820 }
2821
2822 if (trans->callref) {
2823 switch (trans->state) {
2824 case GSM_CSTATE_CALL_PRESENT:
2825 rc = mncc_recvmsg(trans->network, trans,
2826 MNCC_REJ_IND, &rel);
2827 break;
2828 case GSM_CSTATE_RELEASE_REQ:
2829 rc = mncc_recvmsg(trans->network, trans,
2830 MNCC_REL_CNF, &rel);
2831 break;
2832 default:
2833 rc = mncc_recvmsg(trans->network, trans,
2834 MNCC_REL_IND, &rel);
2835 }
2836 }
2837
2838 trans->callref = 0;
2839 free_trans(trans);
2840
2841 return rc;
2842}
2843
2844static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2845{
2846 struct gsm_mncc *rel = arg;
2847 struct msgb *msg = gsm48_msgb_alloc();
2848 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2849
2850 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2851 msg->lchan = trans->lchan;
2852 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2853
2854 trans->callref = 0;
2855
2856 gsm48_stop_cc_timer(trans);
2857
2858 /* cause */
2859 if (rel->fields & MNCC_F_CAUSE)
2860 encode_cause(msg, 0, &rel->cause);
2861 /* facility */
2862 if (rel->fields & MNCC_F_FACILITY)
2863 encode_facility(msg, 0, &rel->facility);
2864 /* user-user */
2865 if (rel->fields & MNCC_F_USERUSER)
2866 encode_useruser(msg, 0, &rel->useruser);
2867
2868 free_trans(trans);
2869
2870 return gsm48_sendmsg(msg);
2871}
2872
2873static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2874{
2875 struct gsm48_hdr *gh = msgb_l3(msg);
2876 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2877 struct tlv_parsed tp;
2878 struct gsm_mncc fac;
2879
2880 memset(&fac, 0, sizeof(struct gsm_mncc));
2881 fac.callref = trans->callref;
2882 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2883 /* facility */
2884 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2885 fac.fields |= MNCC_F_FACILITY;
2886 decode_facility(&fac.facility,
2887 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2888 }
2889 /* ss-version */
2890 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2891 fac.fields |= MNCC_F_SSVERSION;
2892 decode_ssversion(&fac.ssversion,
2893 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2894 }
2895
2896 return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
2897}
2898
2899static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2900{
2901 struct gsm_mncc *fac = arg;
2902 struct msgb *msg = gsm48_msgb_alloc();
2903 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2904
2905 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2906 msg->lchan = trans->lchan;
2907 gh->msg_type = GSM48_MT_CC_FACILITY;
2908
2909 /* facility */
2910 encode_facility(msg, 1, &fac->facility);
2911
2912 return gsm48_sendmsg(msg);
2913}
2914
2915static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2916{
2917 struct gsm_mncc hold;
2918
2919 memset(&hold, 0, sizeof(struct gsm_mncc));
2920 hold.callref = trans->callref;
2921 return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
2922}
2923
2924static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2925{
2926 struct msgb *msg = gsm48_msgb_alloc();
2927 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2928
2929 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2930 msg->lchan = trans->lchan;
2931 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2932
2933 return gsm48_sendmsg(msg);
2934}
2935
2936static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2937{
2938 struct gsm_mncc *hold_rej = arg;
2939 struct msgb *msg = gsm48_msgb_alloc();
2940 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2941
2942 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2943 msg->lchan = trans->lchan;
2944 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2945
2946 /* cause */
2947 if (hold_rej->fields & MNCC_F_CAUSE)
2948 encode_cause(msg, 1, &hold_rej->cause);
2949 else
2950 encode_cause(msg, 1, &default_cause);
2951
2952 return gsm48_sendmsg(msg);
2953}
2954
2955static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2956{
2957 struct gsm_mncc retrieve;
2958
2959 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2960 retrieve.callref = trans->callref;
2961 return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
2962}
2963
2964static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2965{
2966 struct msgb *msg = gsm48_msgb_alloc();
2967 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2968
2969 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2970 msg->lchan = trans->lchan;
2971 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2972
2973 return gsm48_sendmsg(msg);
2974}
2975
2976static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2977{
2978 struct gsm_mncc *retrieve_rej = arg;
2979 struct msgb *msg = gsm48_msgb_alloc();
2980 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2981
2982 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
2983 msg->lchan = trans->lchan;
2984 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2985
2986 /* cause */
2987 if (retrieve_rej->fields & MNCC_F_CAUSE)
2988 encode_cause(msg, 1, &retrieve_rej->cause);
2989 else
2990 encode_cause(msg, 1, &default_cause);
2991
2992 return gsm48_sendmsg(msg);
2993}
2994
2995static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2996{
2997 struct gsm48_hdr *gh = msgb_l3(msg);
2998 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2999 struct tlv_parsed tp;
3000 struct gsm_mncc dtmf;
3001
3002 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3003 dtmf.callref = trans->callref;
3004 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3005 /* keypad facility */
3006 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3007 dtmf.fields |= MNCC_F_KEYPAD;
3008 decode_keypad(&dtmf.keypad,
3009 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3010 }
3011
3012 return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
3013}
3014
3015static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3016{
3017 struct gsm_mncc *dtmf = arg;
3018 struct msgb *msg = gsm48_msgb_alloc();
3019 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3020
3021 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3022 msg->lchan = trans->lchan;
3023 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3024
3025 /* keypad */
3026 if (dtmf->fields & MNCC_F_KEYPAD)
3027 encode_keypad(msg, dtmf->keypad);
3028
3029 return gsm48_sendmsg(msg);
3030}
3031
3032static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3033{
3034 struct gsm_mncc *dtmf = arg;
3035 struct msgb *msg = gsm48_msgb_alloc();
3036 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3037
3038 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3039 msg->lchan = trans->lchan;
3040 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3041
3042 /* cause */
3043 if (dtmf->fields & MNCC_F_CAUSE)
3044 encode_cause(msg, 1, &dtmf->cause);
3045 else
3046 encode_cause(msg, 1, &default_cause);
3047
3048 return gsm48_sendmsg(msg);
3049}
3050
3051static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3052{
3053 struct msgb *msg = gsm48_msgb_alloc();
3054 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3055
3056 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3057 msg->lchan = trans->lchan;
3058 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3059
3060 return gsm48_sendmsg(msg);
3061}
3062
3063static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3064{
3065 struct gsm_mncc dtmf;
3066
3067 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3068 dtmf.callref = trans->callref;
3069
3070 return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
3071}
3072
3073static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3074{
3075 struct gsm48_hdr *gh = msgb_l3(msg);
3076 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3077 struct tlv_parsed tp;
3078 struct gsm_mncc modify;
3079
3080 memset(&modify, 0, sizeof(struct gsm_mncc));
3081 modify.callref = trans->callref;
3082 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3083 /* bearer capability */
3084 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3085 modify.fields |= MNCC_F_BEARER_CAP;
3086 decode_bearer_cap(&modify.bearer_cap,
3087 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3088 }
3089
3090 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3091
3092 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
3093}
3094
3095static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3096{
3097 struct gsm_mncc *modify = arg;
3098 struct msgb *msg = gsm48_msgb_alloc();
3099 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3100
3101 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3102 msg->lchan = trans->lchan;
3103 gh->msg_type = GSM48_MT_CC_MODIFY;
3104
3105 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3106
3107 /* bearer capability */
3108 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3109
3110 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3111
3112 return gsm48_sendmsg(msg);
3113}
3114
3115static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3116{
3117 struct gsm48_hdr *gh = msgb_l3(msg);
3118 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3119 struct tlv_parsed tp;
3120 struct gsm_mncc modify;
3121
3122 gsm48_stop_cc_timer(trans);
3123
3124 memset(&modify, 0, sizeof(struct gsm_mncc));
3125 modify.callref = trans->callref;
3126 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3127 /* bearer capability */
3128 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3129 modify.fields |= MNCC_F_BEARER_CAP;
3130 decode_bearer_cap(&modify.bearer_cap,
3131 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3132 }
3133
3134 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3135
3136 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
3137}
3138
3139static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3140{
3141 struct gsm_mncc *modify = arg;
3142 struct msgb *msg = gsm48_msgb_alloc();
3143 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3144
3145 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3146 msg->lchan = trans->lchan;
3147 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3148
3149 /* bearer capability */
3150 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3151
3152 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3153
3154 return gsm48_sendmsg(msg);
3155}
3156
3157static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3158{
3159 struct gsm48_hdr *gh = msgb_l3(msg);
3160 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3161 struct tlv_parsed tp;
3162 struct gsm_mncc modify;
3163
3164 gsm48_stop_cc_timer(trans);
3165
3166 memset(&modify, 0, sizeof(struct gsm_mncc));
3167 modify.callref = trans->callref;
3168 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3169 /* bearer capability */
3170 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3171 modify.fields |= GSM48_IE_BEARER_CAP;
3172 decode_bearer_cap(&modify.bearer_cap,
3173 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3174 }
3175 /* cause */
3176 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3177 modify.fields |= MNCC_F_CAUSE;
3178 decode_cause(&modify.cause,
3179 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3180 }
3181
3182 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3183
3184 return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
3185}
3186
3187static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3188{
3189 struct gsm_mncc *modify = arg;
3190 struct msgb *msg = gsm48_msgb_alloc();
3191 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3192
3193 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3194 msg->lchan = trans->lchan;
3195 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3196
3197 /* bearer capability */
3198 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3199 /* cause */
3200 encode_cause(msg, 1, &modify->cause);
3201
3202 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3203
3204 return gsm48_sendmsg(msg);
3205}
3206
3207static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3208{
3209 struct gsm_mncc *notify = arg;
3210 struct msgb *msg = gsm48_msgb_alloc();
3211 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3212
3213 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3214 msg->lchan = trans->lchan;
3215 gh->msg_type = GSM48_MT_CC_NOTIFY;
3216
3217 /* notify */
3218 encode_notify(msg, notify->notify);
3219
3220 return gsm48_sendmsg(msg);
3221}
3222
3223static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3224{
3225 struct gsm48_hdr *gh = msgb_l3(msg);
3226 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3227// struct tlv_parsed tp;
3228 struct gsm_mncc notify;
3229
3230 memset(&notify, 0, sizeof(struct gsm_mncc));
3231 notify.callref = trans->callref;
3232// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3233 if (payload_len >= 1)
3234 decode_notify(&notify.notify, gh->data);
3235
3236 return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
3237}
3238
3239static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3240{
3241 struct gsm_mncc *user = arg;
3242 struct msgb *msg = gsm48_msgb_alloc();
3243 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3244
3245 gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
3246 msg->lchan = trans->lchan;
3247 gh->msg_type = GSM48_MT_CC_USER_INFO;
3248
3249 /* user-user */
3250 if (user->fields & MNCC_F_USERUSER)
3251 encode_useruser(msg, 1, &user->useruser);
3252 /* more data */
3253 if (user->more)
3254 encode_more(msg);
3255
3256 return gsm48_sendmsg(msg);
3257}
3258
3259static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3260{
3261 struct gsm48_hdr *gh = msgb_l3(msg);
3262 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3263 struct tlv_parsed tp;
3264 struct gsm_mncc user;
3265
3266 memset(&user, 0, sizeof(struct gsm_mncc));
3267 user.callref = trans->callref;
3268 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3269 /* user-user */
3270 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3271 user.fields |= MNCC_F_USERUSER;
3272 decode_useruser(&user.useruser,
3273 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3274 }
3275 /* more data */
3276 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3277 user.more = 1;
3278
3279 return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
3280}
3281
3282static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3283{
3284 struct gsm_mncc *mode = arg;
3285
3286 return gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3287}
3288
3289static struct downstate {
3290 u_int32_t states;
3291 int type;
3292 int (*rout) (struct gsm_trans *trans, void *arg);
3293} downstatelist[] = {
3294 /* mobile originating call establishment */
3295 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3296 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3297 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3298 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3299 {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 */
3300 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3301 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3302 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3303 /* mobile terminating call establishment */
3304 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3305 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3306 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3307 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3308 /* signalling during call */
3309 {SBIT(GSM_CSTATE_ACTIVE),
3310 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3311 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3312 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3313 {ALL_STATES,
3314 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3315 {ALL_STATES,
3316 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3317 {ALL_STATES,
3318 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3319 {SBIT(GSM_CSTATE_ACTIVE),
3320 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3321 {SBIT(GSM_CSTATE_ACTIVE),
3322 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3323 {SBIT(GSM_CSTATE_ACTIVE),
3324 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3325 {SBIT(GSM_CSTATE_ACTIVE),
3326 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3327 {SBIT(GSM_CSTATE_ACTIVE),
3328 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3329 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3330 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3331 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3332 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3333 {SBIT(GSM_CSTATE_ACTIVE),
3334 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3335 /* clearing */
3336 {SBIT(GSM_CSTATE_INITIATED),
3337 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3338 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3339 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3340 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3341 MNCC_REL_REQ, gsm48_cc_tx_release},
3342 /* special */
3343 {ALL_STATES,
3344 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3345};
3346
3347#define DOWNSLLEN \
3348 (sizeof(downstatelist) / sizeof(struct downstate))
3349
3350
3351int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3352{
3353 int i, j, k, l, rc = 0;
3354 struct gsm_trans *trans = NULL, *transt;
3355 struct gsm_subscriber *subscr;
3356 struct gsm_lchan *lchan = NULL, *lchant;
3357 struct gsm_bts *bts = NULL;
3358 struct gsm_bts_trx *trx;
3359 struct gsm_bts_trx_ts *ts;
3360 struct gsm_mncc *data = arg, rel;
3361
3362 /* handle special messages */
3363 switch(msg_type) {
3364 case MNCC_BRIDGE:
3365 return tch_bridge(net, arg);
3366 case MNCC_FRAME_DROP:
3367 return tch_recv(net, arg, 0);
3368 case MNCC_FRAME_RECV:
3369 return tch_recv(net, arg, 1);
3370 case GSM_TRAU_FRAME:
3371 return tch_frame(net, arg);
3372 }
3373
3374 memset(&rel, 0, sizeof(struct gsm_mncc));
3375 rel.callref = data->callref;
3376
3377 /* Find callref */
3378 trans = get_trans_ref(net, data->callref);
3379
3380 /* Callref unknown */
3381 if (!trans) {
Andreas Eversbergc079be42009-06-15 23:22:09 +02003382 if (msg_type != MNCC_SETUP_REQ ||
3383 (!data->called.number[0] && !data->imsi[0])) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003384 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3385 "Received '%s' from MNCC with "
3386 "unknown callref %d\n", data->called.number,
3387 get_mncc_name(msg_type), data->callref);
3388 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003389 return mncc_release_ind(net, NULL, data->callref,
3390 GSM48_CAUSE_LOC_PRN_S_LU,
3391 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003392 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003393 if (!data->called.number[0] && !data->imsi[0]) {
3394 DEBUGP(DCC, "(bts - trx - ts - ti) "
3395 "Received '%s' from MNCC with "
3396 "no number or IMSI\n", get_mncc_name(msg_type));
3397 /* Invalid number */
3398 return mncc_release_ind(net, NULL, data->callref,
3399 GSM48_CAUSE_LOC_PRN_S_LU,
3400 GSM48_CC_CAUSE_INV_NR_FORMAT);
3401 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003402 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003403 if (data->called.number[0])
3404 subscr = subscr_get_by_extension(data->called.number);
3405 else
3406 subscr = subscr_get_by_imsi(data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003407 /* If subscriber is not found */
3408 if (!subscr) {
3409 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3410 "Received '%s' from MNCC with "
3411 "unknown subscriber %s\n", data->called.number,
3412 get_mncc_name(msg_type), data->called.number);
3413 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003414 return mncc_release_ind(net, NULL, data->callref,
3415 GSM48_CAUSE_LOC_PRN_S_LU,
3416 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003417 }
3418 /* If subscriber is not "attached" */
3419 if (!subscr->lac) {
3420 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3421 "Received '%s' from MNCC with "
3422 "detached subscriber %s\n", data->called.number,
3423 get_mncc_name(msg_type), data->called.number);
3424 subscr_put(subscr);
3425 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003426 return mncc_release_ind(net, NULL, data->callref,
3427 GSM48_CAUSE_LOC_PRN_S_LU,
3428 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003429 }
3430 /* Create transaction */
Harald Welte2cf161b2009-06-20 22:36:41 +02003431 if (!(trans = talloc(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003432 DEBUGP(DCC, "No memory for trans.\n");
3433 subscr_put(subscr);
3434 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003435 mncc_release_ind(net, NULL, data->callref,
3436 GSM48_CAUSE_LOC_PRN_S_LU,
3437 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003438 return -ENOMEM;
3439 }
3440 trans->callref = data->callref;
3441 trans->network = net;
3442 trans->transaction_id = 0xff; /* unassigned */
3443 llist_add_tail(&trans->entry, &net->trans_list);
3444 /* Assign subscriber to transaction */
3445 trans->subscr = subscr;
3446 /* Find lchan */
3447 for (i = 0; i < net->num_bts; i++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003448 bts = gsm_bts_num(net, i);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003449 for (j = 0; j < bts->num_trx; j++) {
Harald Weltee441d9c2009-06-21 16:17:15 +02003450 trx = gsm_bts_trx_num(bts, j);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003451 for (k = 0; k < TRX_NR_TS; k++) {
3452 ts = &trx->ts[k];
3453 for (l = 0; l < TS_MAX_LCHAN; l++) {
3454 lchant = &ts->lchan[l];
3455 if (lchant->subscr == subscr) {
3456 lchan = lchant;
3457 break;
3458 }
3459 }
3460 }
3461 }
3462 }
3463
3464 /* If subscriber has no lchan */
3465 if (!lchan) {
3466 /* find transaction with this subscriber already paging */
3467 llist_for_each_entry(transt, &net->trans_list, entry) {
3468 /* Transaction of our lchan? */
3469 if (transt == trans ||
3470 transt->subscr != subscr)
3471 continue;
3472 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3473 "Received '%s' from MNCC with "
3474 "unallocated channel, paging already "
3475 "started.\n", bts->nr,
3476 data->called.number,
3477 get_mncc_name(msg_type));
3478 return 0;
3479 }
3480 /* store setup informations until paging was successfull */
3481 memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
3482 /* start paging subscriber on all BTS with her location */
3483 subscr->net = net;
3484 bts = NULL;
3485 do {
3486 bts = gsm_bts_by_lac(net, subscr->lac, bts);
3487 if (!bts)
3488 break;
3489 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3490 "Received '%s' from MNCC with "
3491 "unallocated channel, paging.\n",
3492 bts->nr, data->called.number,
3493 get_mncc_name(msg_type));
3494 /* Trigger paging */
Harald Welte92f70c52009-06-12 01:54:08 +08003495 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003496 setup_trig_pag_evt, subscr);
3497 } while (1);
3498 return 0;
3499 }
3500 /* Assign lchan */
3501 trans->lchan = lchan;
3502 use_lchan(lchan);
3503 }
3504 lchan = trans->lchan;
3505
3506 /* if paging did not respond yet */
3507 if (!lchan) {
3508 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3509 "Received '%s' from MNCC in paging state\n",
3510 (trans->subscr)?(trans->subscr->extension):"-",
3511 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003512 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3513 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003514 if (msg_type == MNCC_REL_REQ)
3515 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3516 else
3517 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3518 trans->callref = 0;
3519 free_trans(trans);
3520 return rc;
3521 }
3522
3523 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3524 "Received '%s' from MNCC in state %d (%s)\n",
3525 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3526 trans->transaction_id,
3527 (lchan->subscr)?(lchan->subscr->extension):"-",
3528 get_mncc_name(msg_type), trans->state,
3529 cc_state_names[trans->state]);
3530
3531 /* Find function for current state and message */
3532 for (i = 0; i < DOWNSLLEN; i++)
3533 if ((msg_type == downstatelist[i].type)
3534 && ((1 << trans->state) & downstatelist[i].states))
3535 break;
3536 if (i == DOWNSLLEN) {
3537 DEBUGP(DCC, "Message unhandled at this state.\n");
3538 return 0;
3539 }
3540
3541 rc = downstatelist[i].rout(trans, arg);
3542
3543 return rc;
3544}
3545
3546
3547static struct datastate {
3548 u_int32_t states;
3549 int type;
3550 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3551} datastatelist[] = {
3552 /* mobile originating call establishment */
3553 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3554 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3555 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3556 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3557 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3558 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3559 /* mobile terminating call establishment */
3560 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3561 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3562 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3563 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3564 {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 */
3565 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3566 /* signalling during call */
3567 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3568 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3569 {SBIT(GSM_CSTATE_ACTIVE),
3570 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3571 {ALL_STATES,
3572 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3573 {ALL_STATES,
3574 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3575 {ALL_STATES,
3576 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3577 {SBIT(GSM_CSTATE_ACTIVE),
3578 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3579 {SBIT(GSM_CSTATE_ACTIVE),
3580 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3581 {SBIT(GSM_CSTATE_ACTIVE),
3582 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3583 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3584 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3585 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3586 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3587 {SBIT(GSM_CSTATE_ACTIVE),
3588 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3589 /* clearing */
3590 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3591 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3592 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3593 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3594 {ALL_STATES, /* 5.4.3.4 */
3595 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3596};
3597
3598#define DATASLLEN \
3599 (sizeof(datastatelist) / sizeof(struct datastate))
3600
Harald Welte4bc90a12008-12-27 16:32:52 +00003601static int gsm0408_rcv_cc(struct msgb *msg)
3602{
3603 struct gsm48_hdr *gh = msgb_l3(msg);
3604 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003605 u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
3606 struct gsm_lchan *lchan = msg->lchan;
3607 struct gsm_trans *trans = NULL, *transt;
3608 struct gsm_network *net = lchan->ts->trx->bts->network;
3609 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003610
Harald Welte4bfdfe72009-06-10 23:11:52 +08003611 if (msg_type & 0x80) {
3612 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3613 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003614 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003615
3616 /* Find transaction */
3617 llist_for_each_entry(transt, &net->trans_list, entry) {
3618 /* Transaction of our lchan? */
3619 if (transt->lchan == lchan
3620 && transt->transaction_id == transaction_id) {
3621 trans = transt;
3622 }
3623 }
3624
3625 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3626 "Received '%s' from MS in state %d (%s)\n",
3627 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3628 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
3629 cc_msg_names[msg_type], trans?(trans->state):0,
3630 cc_state_names[trans?(trans->state):0]);
3631
3632 /* Create transaction */
3633 if (!trans) {
3634 DEBUGP(DCC, "Unknown transaction ID %02x, "
3635 "creating new trans.\n", transaction_id);
3636 /* Create transaction */
Harald Welte9b11e872009-06-26 19:42:28 +02003637 if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003638 DEBUGP(DCC, "No memory for trans.\n");
3639 rc = gsm48_tx_simple(msg->lchan,
3640 GSM48_PDISC_CC | transaction_id,
3641 GSM48_MT_CC_RELEASE_COMPL);
3642 return -ENOMEM;
3643 }
3644 llist_add_tail(&trans->entry, &net->trans_list);
3645 /* Assign transaction */
3646 trans->callref = new_callref++;
3647 trans->network = net;
3648 trans->transaction_id = transaction_id;
3649 trans->lchan = lchan;
3650 use_lchan(lchan);
3651 if (lchan->subscr) {
3652 trans->subscr = lchan->subscr;
3653 subscr_get(trans->subscr);
3654 }
3655 }
3656
3657 /* find function for current state and message */
3658 for (i = 0; i < DATASLLEN; i++)
3659 if ((msg_type == datastatelist[i].type)
3660 && ((1 << trans->state) & datastatelist[i].states))
3661 break;
3662 if (i == DATASLLEN) {
3663 DEBUGP(DCC, "Message unhandled at this state.\n");
3664 return 0;
3665 }
3666
3667 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003668
3669 return rc;
3670}
3671
Harald Welte52b1f982008-12-23 20:25:15 +00003672/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3673int gsm0408_rcvmsg(struct msgb *msg)
3674{
3675 struct gsm48_hdr *gh = msgb_l3(msg);
3676 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003677 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003678
3679 switch (pdisc) {
3680 case GSM48_PDISC_CC:
3681 rc = gsm0408_rcv_cc(msg);
3682 break;
3683 case GSM48_PDISC_MM:
3684 rc = gsm0408_rcv_mm(msg);
3685 break;
3686 case GSM48_PDISC_RR:
3687 rc = gsm0408_rcv_rr(msg);
3688 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003689 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003690 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003691 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003692 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003693 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003694 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3695 pdisc);
3696 break;
3697 default:
3698 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3699 pdisc);
3700 break;
3701 }
3702
3703 return rc;
3704}
Harald Welte8470bf22008-12-25 23:28:35 +00003705
Harald Welte8470bf22008-12-25 23:28:35 +00003706/* Section 9.1.8 / Table 9.9 */
3707struct chreq {
3708 u_int8_t val;
3709 u_int8_t mask;
3710 enum chreq_type type;
3711};
3712
3713/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3714static const struct chreq chreq_type_neci1[] = {
3715 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3716 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3717 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3718 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3719 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3720 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3721 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3722 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3723 { 0x10, 0xf0, CHREQ_T_SDCCH },
3724 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3725 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3726 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3727};
3728
3729/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3730static const struct chreq chreq_type_neci0[] = {
3731 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3732 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3733 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3734 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3735 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3736 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3737 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3738 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3739};
3740
3741static const enum gsm_chan_t ctype_by_chreq[] = {
3742 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3743 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3744 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3745 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3746 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3747 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3748 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3749 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3750 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3751 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3752 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3753 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3754};
3755
Harald Weltee14a57c2008-12-29 04:08:28 +00003756static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3757 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3758 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3759 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3760 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3761 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3762 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3763 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3764 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3765 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3766 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3767 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3768 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3769};
3770
Harald Welte8470bf22008-12-25 23:28:35 +00003771enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3772{
3773 int i;
3774 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3775
3776 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3777 const struct chreq *chr = &chreq_type_neci0[i];
3778 if ((ra & chr->mask) == chr->val)
3779 return ctype_by_chreq[chr->type];
3780 }
3781 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3782 return GSM_LCHAN_SDCCH;
3783}
Harald Weltee14a57c2008-12-29 04:08:28 +00003784
3785enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3786{
3787 int i;
3788 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
3789
3790 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3791 const struct chreq *chr = &chreq_type_neci0[i];
3792 if ((ra & chr->mask) == chr->val)
3793 return reason_by_chreq[chr->type];
3794 }
3795 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3796 return GSM_CHREQ_REASON_OTHER;
3797}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003798
3799/* dequeue messages to layer 4 */
3800int bsc_upqueue(struct gsm_network *net)
3801{
3802 struct gsm_mncc *mncc;
3803 struct msgb *msg;
3804 int work = 0;
3805
3806 if (net)
3807 while ((msg = msgb_dequeue(&net->upqueue))) {
3808 mncc = (struct gsm_mncc *)msg->data;
3809 if (net->mncc_recv)
3810 net->mncc_recv(net, mncc->msg_type, mncc);
3811 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003812 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003813 }
3814
3815 return work;
3816}