blob: 5c4465e3755fcb190340013ddeb289b67478b736 [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 Welte805f6442009-07-28 18:25:29 +020047#include <openbsc/rtp_proxy.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020048#include <openbsc/talloc.h>
Harald Weltedcaf5652009-07-23 18:56:43 +020049#include <openbsc/transaction.h>
Harald Welte52b1f982008-12-23 20:25:15 +000050
Harald Welte8470bf22008-12-25 23:28:35 +000051#define GSM48_ALLOC_SIZE 1024
52#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000053
Harald Welte0c389302009-06-10 12:08:54 +080054#define GSM_MAX_FACILITY 128
55#define GSM_MAX_SSVERSION 128
56#define GSM_MAX_USERUSER 128
57
Harald Welte2cf161b2009-06-20 22:36:41 +020058static void *tall_locop_ctx;
Harald Welte2cf161b2009-06-20 22:36:41 +020059
Harald Welte805f6442009-07-28 18:25:29 +020060/* should ip.access BTS use direct RTP streams between each other (1),
61 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
62int ipacc_rtp_direct = 1;
63
Harald Welte09e38af2009-02-16 22:52:23 +000064static const struct tlv_definition rsl_att_tlvdef = {
65 .def = {
66 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
67 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
69 [GSM48_IE_UTC] = { TLV_TYPE_TV },
70 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
71 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
72
73 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
74 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
75 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
76 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
77 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
78 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
79 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080080 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000081 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
82 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080083 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
84 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000085 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
86 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
89 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
91 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
92 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
94 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
95 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
96 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
98 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +080099 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
100 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +0000101 /* FIXME: more elements */
102 },
103};
Harald Weltecf5b3592009-05-01 18:28:42 +0000104
105static const char *rr_cause_names[] = {
106 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
107 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
108 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
109 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
110 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
111 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
112 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
113 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
114 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
115 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
116 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
117 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
118 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
119 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
120 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
121 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
122 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
123};
124
Harald Welte4bfdfe72009-06-10 23:11:52 +0800125static const char *cc_state_names[] = {
126 "NULL",
127 "INITIATED",
128 "illegal state 2",
129 "MO_CALL_PROC",
130 "CALL_DELIVERED",
131 "illegal state 5",
132 "CALL_PRESENT",
133 "CALL_RECEIVED",
134 "CONNECT_REQUEST",
135 "MO_TERM_CALL_CONF",
136 "ACTIVE",
137 "DISCONNECT_REQ",
138 "DISCONNECT_IND",
139 "illegal state 13",
140 "illegal state 14",
141 "illegal state 15",
142 "illegal state 16",
143 "illegal state 17",
144 "illegal state 18",
145 "RELEASE_REQ",
146 "illegal state 20",
147 "illegal state 21",
148 "illegal state 22",
149 "illegal state 23",
150 "illegal state 24",
151 "illegal state 25",
152 "MO_ORIG_MODIFY",
153 "MO_TERM_MODIFY",
154 "CONNECT_IND",
155 "illegal state 29",
156 "illegal state 30",
157 "illegal state 31",
158};
159
160static const char *cc_msg_names[] = {
161 "unknown 0x00",
162 "ALERTING",
163 "CALL_PROC",
164 "PROGRESS",
165 "ESTAB",
166 "SETUP",
167 "ESTAB_CONF",
168 "CONNECT",
169 "CALL_CONF",
170 "START_CC",
171 "unknown 0x0a",
172 "RECALL",
173 "unknown 0x0c",
174 "unknown 0x0d",
175 "EMERG_SETUP",
176 "CONNECT_ACK",
177 "USER_INFO",
178 "unknown 0x11",
179 "unknown 0x12",
180 "MODIFY_REJECT",
181 "unknown 0x14",
182 "unknown 0x15",
183 "unknown 0x16",
184 "MODIFY",
185 "HOLD",
186 "HOLD_ACK",
187 "HOLD_REJ",
188 "unknown 0x1b",
189 "RETR",
190 "RETR_ACK",
191 "RETR_REJ",
192 "MODIFY_COMPL",
193 "unknown 0x20",
194 "unknown 0x21",
195 "unknown 0x22",
196 "unknown 0x23",
197 "unknown 0x24",
198 "DISCONNECT",
199 "unknown 0x26",
200 "unknown 0x27",
201 "unknown 0x28",
202 "unknown 0x29",
203 "RELEASE_COMPL",
204 "unknown 0x2b",
205 "unknown 0x2c",
206 "RELEASE",
207 "unknown 0x2e",
208 "unknown 0x2f",
209 "unknown 0x30",
210 "STOP_DTMF",
211 "STOP_DTMF_ACK",
212 "unknown 0x33",
213 "STATUS_ENQ",
214 "START_DTMF",
215 "START_DTMF_ACK",
216 "START_DTMF_REJ",
217 "unknown 0x38",
218 "CONG_CTRL",
219 "FACILITY",
220 "unknown 0x3b",
221 "STATUS",
222 "unknown 0x3c",
223 "NOTIFY",
224 "unknown 0x3f",
225};
226
Harald Weltecf5b3592009-05-01 18:28:42 +0000227static char strbuf[64];
228
229static const char *rr_cause_name(u_int8_t cause)
230{
231 if (cause < ARRAY_SIZE(rr_cause_names) &&
232 rr_cause_names[cause])
233 return rr_cause_names[cause];
234
235 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
236 return strbuf;
237}
238
Harald Weltef7c43522009-06-09 20:24:21 +0000239static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
240 int len)
241{
242 memset(rep, 0, sizeof(*rep));
243
244 if (data[0] & 0x80)
245 rep->flags |= MEAS_REP_F_BA1;
246 if (data[0] & 0x40)
247 rep->flags |= MEAS_REP_F_DTX;
Harald Welte5a691b52009-07-05 04:05:44 +0200248 if ((data[1] & 0x40) == 0x00)
Harald Weltef7c43522009-06-09 20:24:21 +0000249 rep->flags |= MEAS_REP_F_VALID;
250
251 rep->rxlev_full = data[0] & 0x3f;
252 rep->rxlev_sub = data[1] & 0x3f;
253 rep->rxqual_full = (data[3] >> 4) & 0x7;
254 rep->rxqual_sub = (data[3] >> 1) & 0x7;
255 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
256 if (rep->num_cell < 1)
257 return;
258
259 /* an encoding nightmare in perfection */
260
261 rep->cell[0].rxlev = data[4] & 0x3f;
262 rep->cell[0].bcch_freq = data[5] >> 2;
263 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
264 if (rep->num_cell < 2)
265 return;
266
267 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
268 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
269 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
270 if (rep->num_cell < 3)
271 return;
272
273 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
274 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
275 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
276 if (rep->num_cell < 4)
277 return;
278
279 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
280 rep->cell[3].bcch_freq = data[11] & 0x1f;
281 rep->cell[3].bsic = data[12] >> 2;
282 if (rep->num_cell < 5)
283 return;
284
285 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
286 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
287 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
288 if (rep->num_cell < 6)
289 return;
290
291 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
292 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
293 rep->cell[5].bsic = data[16] & 0x3f;
294}
295
Holger Freytherd51524f2009-06-09 08:27:07 +0000296int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000297static int gsm48_tx_simple(struct gsm_lchan *lchan,
298 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000299static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte65e74cc2008-12-29 01:55:35 +0000300
Harald Welte52b1f982008-12-23 20:25:15 +0000301struct gsm_lai {
302 u_int16_t mcc;
303 u_int16_t mnc;
304 u_int16_t lac;
305};
306
Holger Freyther89824fc2008-12-30 16:18:18 +0000307static int authorize_everonye = 0;
308void gsm0408_allow_everyone(int everyone)
309{
310 printf("Allowing everyone?\n");
311 authorize_everonye = everyone;
312}
313
Holger Freythere97f7fb2008-12-31 18:52:11 +0000314static int reject_cause = 0;
315void gsm0408_set_reject_cause(int cause)
316{
317 reject_cause = cause;
318}
319
Harald Welte4bfdfe72009-06-10 23:11:52 +0800320static u_int32_t new_callref = 0x80000001;
321
Holger Freyther73487a22008-12-31 18:53:57 +0000322static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
323 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000324{
325 if (!subscriber)
326 return 0;
327
Holger Freyther73487a22008-12-31 18:53:57 +0000328 /*
329 * Do not send accept yet as more information should arrive. Some
330 * phones will not send us the information and we will have to check
331 * what we want to do with that.
332 */
333 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
334 return 0;
335
Holger Freyther89824fc2008-12-30 16:18:18 +0000336 if (authorize_everonye)
337 return 1;
338
339 return subscriber->authorized;
340}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000341
Holger Freyther73487a22008-12-31 18:53:57 +0000342static void release_loc_updating_req(struct gsm_lchan *lchan)
343{
Harald Welte179f0642008-12-31 23:59:18 +0000344 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000345 return;
346
Harald Welteff117a82009-05-23 05:22:08 +0000347 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200348 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000349 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000350 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000351}
352
353static void allocate_loc_updating_req(struct gsm_lchan *lchan)
354{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000355 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000356 release_loc_updating_req(lchan);
357
Harald Welte470ec292009-06-26 20:25:23 +0200358 lchan->loc_operation = talloc_zero(tall_locop_ctx,
359 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000360}
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)) {
Harald Welteee5ad162009-08-09 19:07:00 +0200367 int rc;
368
Holger Freytherd51524f2009-06-09 08:27:07 +0000369 db_subscriber_alloc_tmsi(lchan->subscr);
Holger Freytherd51524f2009-06-09 08:27:07 +0000370 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
371 release_loc_updating_req(lchan);
Harald Welteee5ad162009-08-09 19:07:00 +0200372 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
373 /* call subscr_update after putting the loc_upd_acc
374 * in the transmit queue, since S_SUBSCR_ATTACHED might
375 * trigger further action like SMS delivery */
376 subscr_update(lchan->subscr, msg->trx->bts,
377 GSM_SUBSCRIBER_UPDATE_ATTACHED);
378 return rc;
Holger Freytherd51524f2009-06-09 08:27:07 +0000379 }
380
381 return 0;
382}
383
Holger Freyther7c19f742009-06-06 13:54:35 +0000384static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
385 void *handler_data, void *signal_data)
386{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800387 struct gsm_trans *trans, *temp;
388
Holger Freyther7c19f742009-06-06 13:54:35 +0000389 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
390 return 0;
391
392 /*
393 * Cancel any outstanding location updating request
394 * operation taking place on the lchan.
395 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200396 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200397 if (!lchan)
398 return 0;
399
Holger Freyther7c19f742009-06-06 13:54:35 +0000400 release_loc_updating_req(lchan);
401
Harald Welte4bfdfe72009-06-10 23:11:52 +0800402 /* Free all transactions that are associated with the released lchan */
Harald Weltedcaf5652009-07-23 18:56:43 +0200403 /* FIXME: this is not neccessarily the right thing to do, we should
404 * only set trans->lchan to NULL and wait for another lchan to be
405 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800406 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
407 if (trans->lchan == lchan)
Harald Weltedcaf5652009-07-23 18:56:43 +0200408 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800409 }
410
Holger Freyther7c19f742009-06-06 13:54:35 +0000411 return 0;
412}
413
Harald Welte52b1f982008-12-23 20:25:15 +0000414static void to_bcd(u_int8_t *bcd, u_int16_t val)
415{
Harald Welte4b634542008-12-27 01:55:51 +0000416 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000417 val = val / 10;
418 bcd[1] = val % 10;
419 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000420 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000421 val = val / 10;
422}
423
Holger Freyther17746612008-12-28 16:32:44 +0000424void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000425 u_int16_t mnc, u_int16_t lac)
426{
427 u_int8_t bcd[3];
428
429 to_bcd(bcd, mcc);
430 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
431 lai48->digits[1] = bcd[2];
432
433 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000434 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
435#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000436 lai48->digits[1] |= bcd[2] << 4;
437 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000438#else
439 lai48->digits[1] |= 0xf << 4;
440 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
441#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000442
Harald Welte4b634542008-12-27 01:55:51 +0000443 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000444}
445
Harald Welte255539c2008-12-28 02:26:27 +0000446#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000447#define MID_TMSI_LEN (TMSI_LEN + 2)
448
Harald Welte255539c2008-12-28 02:26:27 +0000449int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000450{
Harald Welte65e74cc2008-12-29 01:55:35 +0000451 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000452
Harald Welte4b634542008-12-27 01:55:51 +0000453 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000454 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000455 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000456 *tptr = htonl(tmsi);
457
458 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000459}
460
Harald Welte09e38af2009-02-16 22:52:23 +0000461static const char bcd_num_digits[] = {
462 '0', '1', '2', '3', '4', '5', '6', '7',
463 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
464};
465
Harald Welte0c389302009-06-10 12:08:54 +0800466/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
467int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
468 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000469{
470 u_int8_t in_len = bcd_lv[0];
471 int i;
472
Harald Welte0c389302009-06-10 12:08:54 +0800473 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000474 /* lower nibble */
475 output_len--;
476 if (output_len <= 1)
477 break;
478 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
479
480 /* higher nibble */
481 output_len--;
482 if (output_len <= 1)
483 break;
484 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
485 }
486 if (output_len >= 1)
487 *output++ = '\0';
488
Harald Welte0c389302009-06-10 12:08:54 +0800489 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000490}
491
492/* convert a single ASCII character to call-control BCD */
493static int asc_to_bcd(const char asc)
494{
495 int i;
496
497 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
498 if (bcd_num_digits[i] == asc)
499 return i;
500 }
501 return -EINVAL;
502}
503
Harald Welte0c389302009-06-10 12:08:54 +0800504/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000505int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800506 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000507{
508 int in_len = strlen(input);
509 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800510 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000511
512 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800513 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000514 if (in_len % 2)
515 bcd_lv[0]++;
516
Harald Welte0c389302009-06-10 12:08:54 +0800517 if (bcd_lv[0] > max_len)
518 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000519
520 for (i = 0; i < in_len; i++) {
521 int rc = asc_to_bcd(input[i]);
522 if (rc < 0)
523 return rc;
524 if (i % 2 == 0)
525 *bcd_cur = rc;
526 else
527 *bcd_cur++ |= (rc << 4);
528 }
529 /* append padding nibble in case of odd length */
530 if (i % 2)
531 *bcd_cur++ |= 0xf0;
532
533 /* return how many bytes we used */
534 return (bcd_cur - bcd_lv);
535}
536
Harald Welte0c389302009-06-10 12:08:54 +0800537/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800538static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800539 const u_int8_t *lv)
540{
541 u_int8_t in_len = lv[0];
542 int i, s;
543
544 if (in_len < 1)
545 return -EINVAL;
546
Harald Welte4bfdfe72009-06-10 23:11:52 +0800547 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800548
549 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800550 bcap->transfer = lv[1] & 0x07;
551 bcap->mode = (lv[1] & 0x08) >> 3;
552 bcap->coding = (lv[1] & 0x10) >> 4;
553 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800554
555 i = 1;
556 s = 0;
557 while(!(lv[i] & 0x80)) {
558 i++; /* octet 3a etc */
559 if (in_len < i)
560 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800561 bcap->speech_ver[s++] = lv[i] & 0x0f;
562 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800563 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800564 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800565 if (s == 7) /* maximum speech versions + end of list */
566 return 0;
567 }
568
569 return 0;
570}
571
572/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800573static int encode_bearer_cap(struct msgb *msg, int lv_only,
574 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800575{
576 u_int8_t lv[32 + 1];
577 int i, s;
578
Harald Welte4bfdfe72009-06-10 23:11:52 +0800579 lv[1] = bcap->transfer;
580 lv[1] |= bcap->mode << 3;
581 lv[1] |= bcap->coding << 4;
582 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800583
584 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800586 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800588 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800589 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800590 }
591 lv[i] |= 0x80; /* last IE of octet 3 etc */
592
593 lv[0] = i;
594 if (lv_only)
595 msgb_lv_put(msg, lv[0], lv+1);
596 else
597 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
598
599 return 0;
600}
601
602/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800603static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800604{
605 u_int8_t in_len = lv[0];
606
607 if (in_len < 1)
608 return -EINVAL;
609
610 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800611 ccap->dtmf = lv[1] & 0x01;
612 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800613
614 return 0;
615}
616
617/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800618static int decode_called(struct gsm_mncc_number *called,
619 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800620{
621 u_int8_t in_len = lv[0];
622
623 if (in_len < 1)
624 return -EINVAL;
625
626 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800627 called->plan = lv[1] & 0x0f;
628 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800629
630 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800631 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800632
633 return 0;
634}
635
636/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800637static int encode_called(struct msgb *msg,
638 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800639{
640 u_int8_t lv[18];
641 int ret;
642
643 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800644 lv[1] = called->plan;
645 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800646
647 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800648 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800649 if (ret < 0)
650 return ret;
651
652 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
653
654 return 0;
655}
656
657/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800658static int encode_callerid(struct msgb *msg, int ie,
659 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800660{
661 u_int8_t lv[13];
662 int h_len = 1;
663 int ret;
664
665 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800666 lv[1] = callerid->plan;
667 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800668
Harald Welte4bfdfe72009-06-10 23:11:52 +0800669 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800670 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800671 lv[2] = callerid->screen;
672 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800673 lv[2] |= 0x80;
674 h_len++;
675 } else
676 lv[1] |= 0x80;
677
678 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800679 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800680 if (ret < 0)
681 return ret;
682
683 msgb_tlv_put(msg, ie, lv[0], lv+1);
684
685 return 0;
686}
687
688/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800689static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800690 const u_int8_t *lv)
691{
692 u_int8_t in_len = lv[0];
693 int i;
694
695 if (in_len < 2)
696 return -EINVAL;
697
Harald Welte4bfdfe72009-06-10 23:11:52 +0800698 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800699
700 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800701 cause->location = lv[1] & 0x0f;
702 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800703
704 i = 1;
705 if (!(lv[i] & 0x80)) {
706 i++; /* octet 3a */
707 if (in_len < i+1)
708 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800709 cause->rec = 1;
710 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800711
712 }
713 i++;
714
715 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800716 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800717 i++;
718
719 if (in_len < i) /* no diag */
720 return 0;
721
722 if (in_len - (i-1) > 32) /* maximum 32 octets */
723 return 0;
724
725 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800726 memcpy(cause->diag, lv + i, in_len - (i-1));
727 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800728
729 return 0;
730}
731
732/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800733static int encode_cause(struct msgb *msg, int lv_only,
734 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800735{
736 u_int8_t lv[32+4];
737 int i;
738
Harald Welte4bfdfe72009-06-10 23:11:52 +0800739 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800740 return -EINVAL;
741
742 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800743 lv[1] = cause->location;
744 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800745
746 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800748 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800749 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800750 }
751 lv[i] |= 0x80; /* end of octet 3 */
752
753 /* octet 4 */
754 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800755 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800756
757 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800758 if (cause->diag_len) {
759 memcpy(lv + i, cause->diag, cause->diag_len);
760 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800761 }
762
763 lv[0] = i;
764 if (lv_only)
765 msgb_lv_put(msg, lv[0], lv+1);
766 else
767 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
768
769 return 0;
770}
771
772/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800773static int encode_calling(struct msgb *msg,
774 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800775{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800776 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800777}
778
779/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800780static int encode_connected(struct msgb *msg,
781 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800782{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800783 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800784}
785
786/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800787static int encode_redirecting(struct msgb *msg,
788 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800789{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800790 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800791}
792
793/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800794static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800795 const u_int8_t *lv)
796{
797 u_int8_t in_len = lv[0];
798
799 if (in_len < 1)
800 return -EINVAL;
801
Harald Welte4bfdfe72009-06-10 23:11:52 +0800802 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800803 return -EINVAL;
804
Harald Welte4bfdfe72009-06-10 23:11:52 +0800805 memcpy(facility->info, lv+1, in_len);
806 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800807
808 return 0;
809}
810
811/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800812static int encode_facility(struct msgb *msg, int lv_only,
813 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800814{
815 u_int8_t lv[GSM_MAX_FACILITY + 1];
816
Harald Welte4bfdfe72009-06-10 23:11:52 +0800817 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800818 return -EINVAL;
819
Harald Welte4bfdfe72009-06-10 23:11:52 +0800820 memcpy(lv+1, facility->info, facility->len);
821 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800822 if (lv_only)
823 msgb_lv_put(msg, lv[0], lv+1);
824 else
825 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
826
827 return 0;
828}
829
830/* decode 'notify' */
831static int decode_notify(int *notify, const u_int8_t *v)
832{
833 *notify = v[0] & 0x7f;
834
835 return 0;
836}
837
838/* encode 'notify' */
839static int encode_notify(struct msgb *msg, int notify)
840{
841 msgb_v_put(msg, notify | 0x80);
842
843 return 0;
844}
845
846/* encode 'signal' */
847static int encode_signal(struct msgb *msg, int signal)
848{
849 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
850
851 return 0;
852}
853
854/* decode 'keypad' */
855static int decode_keypad(int *keypad, const u_int8_t *lv)
856{
857 u_int8_t in_len = lv[0];
858
859 if (in_len < 1)
860 return -EINVAL;
861
862 *keypad = lv[1] & 0x7f;
863
864 return 0;
865}
866
867/* encode 'keypad' */
868static int encode_keypad(struct msgb *msg, int keypad)
869{
870 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
871
872 return 0;
873}
874
875/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800876static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800877 const u_int8_t *lv)
878{
879 u_int8_t in_len = lv[0];
880
881 if (in_len < 2)
882 return -EINVAL;
883
Harald Welte4bfdfe72009-06-10 23:11:52 +0800884 progress->coding = (lv[1] & 0x60) >> 5;
885 progress->location = lv[1] & 0x0f;
886 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800887
888 return 0;
889}
890
891/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800892static int encode_progress(struct msgb *msg, int lv_only,
893 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800894{
895 u_int8_t lv[3];
896
897 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800898 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
899 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800900 if (lv_only)
901 msgb_lv_put(msg, lv[0], lv+1);
902 else
903 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
904
905 return 0;
906}
907
908/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800909static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800910 const u_int8_t *lv)
911{
912 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800913 char *info = uu->info;
914 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800915 int i;
916
917 if (in_len < 1)
918 return -EINVAL;
919
Harald Welte4bfdfe72009-06-10 23:11:52 +0800920 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800921
922 for (i = 2; i <= in_len; i++) {
923 info_len--;
924 if (info_len <= 1)
925 break;
926 *info++ = lv[i];
927 }
928 if (info_len >= 1)
929 *info++ = '\0';
930
931 return 0;
932}
933
934/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800935static int encode_useruser(struct msgb *msg, int lv_only,
936 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800937{
938 u_int8_t lv[GSM_MAX_USERUSER + 2];
939
Harald Welte4bfdfe72009-06-10 23:11:52 +0800940 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800941 return -EINVAL;
942
Harald Welte4bfdfe72009-06-10 23:11:52 +0800943 lv[0] = 1 + strlen(uu->info);
944 lv[1] = uu->proto;
945 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800946 if (lv_only)
947 msgb_lv_put(msg, lv[0], lv+1);
948 else
949 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
950
951 return 0;
952}
953
954/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800955static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800956 const u_int8_t *lv)
957{
958 u_int8_t in_len = lv[0];
959
Harald Welte4bfdfe72009-06-10 23:11:52 +0800960 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800961 return -EINVAL;
962
Harald Welte4bfdfe72009-06-10 23:11:52 +0800963 memcpy(ssv->info, lv + 1, in_len);
964 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800965
966 return 0;
967}
968
969/* encode 'more data' */
970static int encode_more(struct msgb *msg)
971{
972 u_int8_t *ie;
973
974 ie = msgb_put(msg, 1);
975 ie[0] = GSM48_IE_MORE_DATA;
976
977 return 0;
978}
979
Holger Freyther819dd202009-01-04 03:52:50 +0000980struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000981{
Harald Welte966636f2009-06-26 19:39:35 +0200982 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
983 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000984}
985
Harald Welte39e2ead2009-07-23 21:13:03 +0200986int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000987{
Harald Welte39e2ead2009-07-23 21:13:03 +0200988 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
989
990 /* if we get passed a transaction reference, do some common
991 * work that the caller no longer has to do */
992 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200993 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200994 msg->lchan = trans->lchan;
995 }
996
Harald Welte65e74cc2008-12-29 01:55:35 +0000997 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000998 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000999
Harald Welte4bfdfe72009-06-10 23:11:52 +08001000 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1001 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1002 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1003 msg->trx->nr, msg->lchan->ts->nr,
1004 gh->proto_discr & 0xf0,
1005 cc_msg_names[gh->msg_type & 0x3f]);
1006 else
1007 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1008 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1009 msg->trx->nr, msg->lchan->ts->nr,
1010 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001011 }
1012
Harald Welte4b634542008-12-27 01:55:51 +00001013 msg->l3h = msg->data;
1014
Harald Welte8470bf22008-12-25 23:28:35 +00001015 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001016}
1017
Holger Freyther429e7762008-12-30 13:28:30 +00001018/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001019int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001020{
Harald Welte8470bf22008-12-25 23:28:35 +00001021 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001022 struct gsm48_hdr *gh;
1023
Harald Welte8470bf22008-12-25 23:28:35 +00001024 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001025
1026 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1027 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001028 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001029 gh->data[0] = cause;
1030
Harald Weltedb253af2008-12-30 17:56:55 +00001031 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1032
Harald Welte39e2ead2009-07-23 21:13:03 +02001033 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001034}
1035
1036/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001037int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001038{
Harald Welte8470bf22008-12-25 23:28:35 +00001039 struct gsm_bts *bts = lchan->ts->trx->bts;
1040 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001041 struct gsm48_hdr *gh;
1042 struct gsm48_loc_area_id *lai;
1043 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001044 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001045
Harald Welte8470bf22008-12-25 23:28:35 +00001046 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001047
1048 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1049 gh->proto_discr = GSM48_PDISC_MM;
1050 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1051
1052 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001053 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001054 bts->network->network_code, bts->location_area_code);
1055
1056 mid = msgb_put(msg, MID_TMSI_LEN);
1057 generate_mid_from_tmsi(mid, tmsi);
1058
1059 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1060
Harald Welte39e2ead2009-07-23 21:13:03 +02001061 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001062
Harald Welteee5ad162009-08-09 19:07:00 +02001063 /* send MM INFO with network name */
Harald Weltedb253af2008-12-30 17:56:55 +00001064 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001065
Holger Freyther07cc8d82008-12-29 06:23:46 +00001066 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001067}
1068
Harald Weltefc977a82008-12-27 10:19:37 +00001069static char bcd2char(u_int8_t bcd)
1070{
1071 if (bcd < 0xa)
1072 return '0' + bcd;
1073 else
1074 return 'A' + (bcd - 0xa);
1075}
1076
Harald Weltebf5e8df2009-02-03 12:59:45 +00001077/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001078static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1079{
1080 int i;
1081 u_int8_t mi_type;
1082 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001083 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001084
1085 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1086
1087 switch (mi_type) {
1088 case GSM_MI_TYPE_NONE:
1089 break;
1090 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001091 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1092 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1093 memcpy(&tmsi, &mi[1], 4);
1094 tmsi = ntohl(tmsi);
1095 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001096 }
1097 break;
1098 case GSM_MI_TYPE_IMSI:
1099 case GSM_MI_TYPE_IMEI:
1100 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001101 *str_cur++ = bcd2char(mi[0] >> 4);
1102
1103 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001104 if (str_cur + 2 >= string + str_len)
1105 return str_cur - string;
1106 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001107 /* skip last nibble in last input byte when GSM_EVEN */
1108 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1109 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001110 }
1111 break;
1112 default:
1113 break;
1114 }
Harald Weltefc977a82008-12-27 10:19:37 +00001115 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001116
Harald Weltefc977a82008-12-27 10:19:37 +00001117 return str_cur - string;
1118}
1119
Harald Weltebf5e8df2009-02-03 12:59:45 +00001120/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001121static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1122{
1123 struct msgb *msg = gsm48_msgb_alloc();
1124 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001125
Harald Welte231ad4f2008-12-27 11:15:38 +00001126 msg->lchan = lchan;
1127
1128 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1129 gh->proto_discr = GSM48_PDISC_MM;
1130 gh->msg_type = GSM48_MT_MM_ID_REQ;
1131 gh->data[0] = id_type;
1132
Harald Welte39e2ead2009-07-23 21:13:03 +02001133 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001134}
1135
1136#define MI_SIZE 32
1137
Harald Weltebf5e8df2009-02-03 12:59:45 +00001138/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001139static int mm_rx_id_resp(struct msgb *msg)
1140{
1141 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001142 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001143 struct gsm_bts *bts = lchan->ts->trx->bts;
1144 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001145 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1146 char mi_string[MI_SIZE];
1147
1148 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001149 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001150 mi_type, mi_string);
1151
Harald Welte75a983f2008-12-27 21:34:06 +00001152 switch (mi_type) {
1153 case GSM_MI_TYPE_IMSI:
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001154 if (!lchan->subscr) {
Harald Welte9176bd42009-07-23 18:46:00 +02001155 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001156 if (lchan->subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1157 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &lchan->subscr);
1158 }
1159 }
Holger Freyther73487a22008-12-31 18:53:57 +00001160 if (lchan->loc_operation)
1161 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001162 break;
1163 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001164 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001165 /* update subscribe <-> IMEI mapping */
1166 if (lchan->subscr)
1167 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001168 if (lchan->loc_operation)
1169 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001170 break;
1171 }
Holger Freyther73487a22008-12-31 18:53:57 +00001172
1173 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001174 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001175}
1176
Harald Welte255539c2008-12-28 02:26:27 +00001177
1178static void loc_upd_rej_cb(void *data)
1179{
1180 struct gsm_lchan *lchan = data;
1181
Holger Freyther73487a22008-12-31 18:53:57 +00001182 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001183 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001184 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001185}
1186
Holger Freytherb7193e42008-12-29 17:44:08 +00001187static void schedule_reject(struct gsm_lchan *lchan)
1188{
Holger Freyther73487a22008-12-31 18:53:57 +00001189 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1190 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001191 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001192}
1193
Harald Welte2a139372009-02-22 21:14:55 +00001194static const char *lupd_name(u_int8_t type)
1195{
1196 switch (type) {
1197 case GSM48_LUPD_NORMAL:
1198 return "NORMAL";
1199 case GSM48_LUPD_PERIODIC:
1200 return "PEROIDOC";
1201 case GSM48_LUPD_IMSI_ATT:
1202 return "IMSI ATTACH";
1203 default:
1204 return "UNKNOWN";
1205 }
1206}
1207
Harald Welte231ad4f2008-12-27 11:15:38 +00001208#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001209/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001210static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001211{
Harald Welte8470bf22008-12-25 23:28:35 +00001212 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001213 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001214 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001215 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001216 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001217 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001218 char mi_string[MI_SIZE];
1219 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001220
Harald Welte8470bf22008-12-25 23:28:35 +00001221 lu = (struct gsm48_loc_upd_req *) gh->data;
1222
1223 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001224
Harald Weltefc977a82008-12-27 10:19:37 +00001225 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1226
Harald Weltea0368542009-06-27 02:58:43 +02001227 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001228 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001229
Holger Freythereaf04692009-06-06 13:54:44 +00001230 /*
1231 * Pseudo Spoof detection: Just drop a second/concurrent
1232 * location updating request.
1233 */
1234 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001235 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001236 lchan->loc_operation);
1237 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1238 return 0;
1239 }
1240
Holger Freyther73487a22008-12-31 18:53:57 +00001241 allocate_loc_updating_req(lchan);
1242
Harald Welte52b1f982008-12-23 20:25:15 +00001243 switch (mi_type) {
1244 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001245 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001246 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001247 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001248 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001249
Harald Welte52b1f982008-12-23 20:25:15 +00001250 /* look up subscriber based on IMSI */
Harald Welte9176bd42009-07-23 18:46:00 +02001251 subscr = db_create_subscriber(bts->network, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001252 if (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1253 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &subscr);
1254 }
Harald Welte4b634542008-12-27 01:55:51 +00001255 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001256 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001257 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001258 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001259 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001260 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001261
Harald Welte52b1f982008-12-23 20:25:15 +00001262 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte9176bd42009-07-23 18:46:00 +02001263 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001264 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001265 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001266 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001267 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001268 }
1269 break;
1270 case GSM_MI_TYPE_IMEI:
1271 case GSM_MI_TYPE_IMEISV:
1272 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001273 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001274 break;
1275 default:
Harald Weltea0368542009-06-27 02:58:43 +02001276 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001277 break;
1278 }
1279
Harald Welte24516ea2009-07-04 10:18:00 +02001280 /* schedule the reject timer */
1281 schedule_reject(lchan);
1282
Harald Welte4bfdfe72009-06-10 23:11:52 +08001283 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001284 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001285 /* FIXME: request id? close channel? */
1286 return -EINVAL;
1287 }
1288
Harald Welte255539c2008-12-28 02:26:27 +00001289 lchan->subscr = subscr;
1290
Harald Welte24516ea2009-07-04 10:18:00 +02001291 /* check if we can let the subscriber into our network immediately
1292 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001293 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001294}
1295
Harald Welte13cac662009-07-29 12:10:35 +02001296/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte7584aea2009-02-11 11:44:12 +00001297int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1298{
1299 struct msgb *msg = gsm48_msgb_alloc();
1300 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1301 struct gsm48_chan_mode_modify *cmm =
1302 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001303 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001304
Harald Welte4a543e82009-02-28 13:17:55 +00001305 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001306
Harald Welte45b407a2009-05-23 15:51:12 +00001307 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001308 msg->lchan = lchan;
1309 gh->proto_discr = GSM48_PDISC_RR;
1310 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1311
1312 /* fill the channel information element, this code
1313 * should probably be shared with rsl_rx_chan_rqd() */
1314 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001315 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001316 cmm->chan_desc.h0.h = 0;
1317 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1318 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1319 cmm->mode = mode;
1320
Harald Welte39e2ead2009-07-23 21:13:03 +02001321 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001322}
1323
Harald Welte4bfdfe72009-06-10 23:11:52 +08001324#if 0
1325static u_int8_t to_bcd8(u_int8_t val)
1326{
1327 return ((val / 10) << 4) | (val % 10);
1328}
1329#endif
1330
Harald Weltedb253af2008-12-30 17:56:55 +00001331/* Section 9.2.15a */
1332int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1333{
1334 struct msgb *msg = gsm48_msgb_alloc();
1335 struct gsm48_hdr *gh;
1336 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001337 u_int8_t *ptr8;
1338 u_int16_t *ptr16;
1339 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001340 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001341#if 0
1342 time_t cur_t;
1343 struct tm* cur_time;
1344 int tz15min;
1345#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001346
1347 msg->lchan = lchan;
1348
1349 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1350 gh->proto_discr = GSM48_PDISC_MM;
1351 gh->msg_type = GSM48_MT_MM_INFO;
1352
1353 if (net->name_long) {
1354 name_len = strlen(net->name_long);
1355 /* 10.5.3.5a */
1356 ptr8 = msgb_put(msg, 3);
1357 ptr8[0] = GSM48_IE_NAME_LONG;
1358 ptr8[1] = name_len*2 +1;
1359 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1360
1361 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1362 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001363 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001364
1365 /* FIXME: Use Cell Broadcast, not UCS-2, since
1366 * UCS-2 is only supported by later revisions of the spec */
1367 }
1368
1369 if (net->name_short) {
1370 name_len = strlen(net->name_short);
1371 /* 10.5.3.5a */
1372 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001373 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001374 ptr8[1] = name_len*2 + 1;
1375 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1376
Harald Weltee872cb12009-01-01 00:33:37 +00001377 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001378 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001379 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001380 }
1381
1382#if 0
1383 /* Section 10.5.3.9 */
1384 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001385 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001386 ptr8 = msgb_put(msg, 8);
1387 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1388 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1389 ptr8[2] = to_bcd8(cur_time->tm_mon);
1390 ptr8[3] = to_bcd8(cur_time->tm_mday);
1391 ptr8[4] = to_bcd8(cur_time->tm_hour);
1392 ptr8[5] = to_bcd8(cur_time->tm_min);
1393 ptr8[6] = to_bcd8(cur_time->tm_sec);
1394 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1395 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001396 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001397 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001398 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001399#endif
1400
Harald Welte39e2ead2009-07-23 21:13:03 +02001401 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001402}
1403
Harald Welte4b634542008-12-27 01:55:51 +00001404static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1405{
Harald Welte4b634542008-12-27 01:55:51 +00001406 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001407 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001408}
Harald Welteba4cf162009-01-10 01:49:35 +00001409
1410/* 9.2.6 CM service reject */
1411static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1412 enum gsm48_reject_value value)
1413{
1414 struct msgb *msg = gsm48_msgb_alloc();
1415 struct gsm48_hdr *gh;
1416
1417 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1418
1419 msg->lchan = lchan;
1420 use_lchan(lchan);
1421
1422 gh->proto_discr = GSM48_PDISC_MM;
1423 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1424 gh->data[0] = value;
1425 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1426
Harald Welte39e2ead2009-07-23 21:13:03 +02001427 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001428}
1429
Harald Welte3ac7f102009-08-10 10:12:45 +02001430static int send_siemens_mrpci(struct gsm_lchan *lchan,
1431 u_int8_t *classmark2_lv)
1432{
1433 struct rsl_mrpci mrpci;
1434
1435 if (classmark2_lv[0] < 2)
1436 return -EINVAL;
1437
1438 mrpci.power_class = classmark2_lv[1] & 0x7;
1439 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1440 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1441 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1442
1443 return rsl_siemens_mrpci(lchan, &mrpci);
1444}
Harald Welte4ed0e922009-01-10 03:17:30 +00001445
1446/*
1447 * Handle CM Service Requests
1448 * a) Verify that the packet is long enough to contain the information
1449 * we require otherwsie reject with INCORRECT_MESSAGE
1450 * b) Try to parse the TMSI. If we do not have one reject
1451 * c) Check that we know the subscriber with the TMSI otherwise reject
1452 * with a HLR cause
1453 * d) Set the subscriber on the gsm_lchan and accept
1454 */
Harald Welte4b634542008-12-27 01:55:51 +00001455static int gsm48_rx_mm_serv_req(struct msgb *msg)
1456{
Harald Welteba4cf162009-01-10 01:49:35 +00001457 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001458 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001459
Harald Welte9176bd42009-07-23 18:46:00 +02001460 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001461 struct gsm_subscriber *subscr;
1462 struct gsm48_hdr *gh = msgb_l3(msg);
1463 struct gsm48_service_request *req =
1464 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001465 /* unfortunately in Phase1 the classmar2 length is variable */
1466 u_int8_t classmark2_len = gh->data[1];
1467 u_int8_t *classmark2 = gh->data+2;
1468 u_int8_t mi_len = *(classmark2 + classmark2_len);
1469 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001470
Harald Weltec9e02182009-05-01 19:07:53 +00001471 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001472 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001473 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001474 return gsm48_tx_mm_serv_rej(msg->lchan,
1475 GSM48_REJECT_INCORRECT_MESSAGE);
1476 }
1477
1478 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001479 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001480 return gsm48_tx_mm_serv_rej(msg->lchan,
1481 GSM48_REJECT_INCORRECT_MESSAGE);
1482 }
1483
Harald Weltec9e02182009-05-01 19:07:53 +00001484 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001485 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001486 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001487 return gsm48_tx_mm_serv_rej(msg->lchan,
1488 GSM48_REJECT_INCORRECT_MESSAGE);
1489 }
1490
Harald Weltec9e02182009-05-01 19:07:53 +00001491 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001492 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001493 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001494
Harald Welte3ac7f102009-08-10 10:12:45 +02001495 if (is_siemens_bts(bts))
1496 send_siemens_mrpci(msg->lchan, classmark2-1);
1497
Harald Welte9176bd42009-07-23 18:46:00 +02001498 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001499
Harald Welte2a139372009-02-22 21:14:55 +00001500 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001501 if (!subscr)
1502 return gsm48_tx_mm_serv_rej(msg->lchan,
1503 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1504
1505 if (!msg->lchan->subscr)
1506 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001507 else if (msg->lchan->subscr != subscr) {
1508 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1509 subscr_put(subscr);
1510 }
1511
Harald Weltec2e302d2009-07-05 14:08:13 +02001512 subscr->equipment.classmark2_len = classmark2_len;
1513 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1514 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001515
Harald Welte4b634542008-12-27 01:55:51 +00001516 return gsm48_tx_mm_serv_ack(msg->lchan);
1517}
1518
Harald Welte2a139372009-02-22 21:14:55 +00001519static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1520{
Harald Welte9176bd42009-07-23 18:46:00 +02001521 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001522 struct gsm48_hdr *gh = msgb_l3(msg);
1523 struct gsm48_imsi_detach_ind *idi =
1524 (struct gsm48_imsi_detach_ind *) gh->data;
1525 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1526 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001527 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001528
1529 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1530 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1531 mi_type, mi_string);
1532
1533 switch (mi_type) {
1534 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001535 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001536 break;
1537 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001538 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001539 break;
1540 case GSM_MI_TYPE_IMEI:
1541 case GSM_MI_TYPE_IMEISV:
1542 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001543 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001544 break;
1545 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001546 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001547 break;
1548 }
1549
Holger Freyther4a49e772009-04-12 05:37:29 +00001550 if (subscr) {
1551 subscr_update(subscr, msg->trx->bts,
1552 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001553 DEBUGP(DMM, "Subscriber: %s\n",
1554 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001555 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001556 } else
Harald Welte2a139372009-02-22 21:14:55 +00001557 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1558
Harald Welte2a139372009-02-22 21:14:55 +00001559 return 0;
1560}
1561
Harald Welted2a7f5a2009-06-05 20:08:20 +00001562static int gsm48_rx_mm_status(struct msgb *msg)
1563{
1564 struct gsm48_hdr *gh = msgb_l3(msg);
1565
1566 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1567
1568 return 0;
1569}
1570
Harald Weltebf5e8df2009-02-03 12:59:45 +00001571/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001572static int gsm0408_rcv_mm(struct msgb *msg)
1573{
1574 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001575 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001576
1577 switch (gh->msg_type & 0xbf) {
1578 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001579 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001580 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001581 break;
1582 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001583 rc = mm_rx_id_resp(msg);
1584 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001585 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001586 rc = gsm48_rx_mm_serv_req(msg);
1587 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001588 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001589 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001590 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001591 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001592 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1593 msg->lchan->subscr ?
1594 msg->lchan->subscr->imsi :
1595 "unknown subscriber");
1596 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001597 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001598 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1599 break;
1600 case GSM48_MT_MM_CM_REEST_REQ:
1601 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1602 break;
1603 case GSM48_MT_MM_AUTH_RESP:
1604 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001605 break;
1606 default:
1607 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1608 gh->msg_type);
1609 break;
1610 }
1611
1612 return rc;
1613}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001614
Harald Welte2d35ae62009-02-06 12:02:13 +00001615/* Receive a PAGING RESPONSE message from the MS */
1616static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1617{
Harald Welte9176bd42009-07-23 18:46:00 +02001618 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001619 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001620 u_int8_t *classmark2_lv = gh->data + 1;
1621 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1622 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001623 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001624 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001625 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001626 int rc = 0;
1627
Harald Welte61548982009-02-22 21:26:29 +00001628 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001629 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1630 mi_type, mi_string);
Harald Welte3ac7f102009-08-10 10:12:45 +02001631
1632 if (is_siemens_bts(bts))
1633 send_siemens_mrpci(msg->lchan, classmark2_lv);
1634
Harald Weltefe18d8f2009-02-22 21:14:24 +00001635 switch (mi_type) {
1636 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001637 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001638 break;
1639 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001640 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001641 break;
1642 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001643
1644 if (!subscr) {
1645 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001646 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001647 return -EINVAL;
1648 }
1649 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte76042182009-08-08 16:03:15 +02001650 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001651
Harald Weltec2e302d2009-07-05 14:08:13 +02001652 subscr->equipment.classmark2_len = *classmark2_lv;
1653 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1654 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001655
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001656 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001657 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001658 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001659 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1660 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001661 return -EINVAL;
1662 } else {
1663 DEBUGP(DRR, "<- Channel already owned by us\n");
1664 subscr_put(subscr);
1665 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001666 }
1667
Harald Welte595ad7b2009-02-16 22:05:44 +00001668 sig_data.subscr = subscr;
1669 sig_data.bts = msg->lchan->ts->trx->bts;
1670 sig_data.lchan = msg->lchan;
1671
1672 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001673
1674 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001675 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001676
Harald Welte7584aea2009-02-11 11:44:12 +00001677 /* FIXME: somehow signal the completion of the PAGING to
1678 * the entity that requested the paging */
1679
Harald Welte2d35ae62009-02-06 12:02:13 +00001680 return rc;
1681}
1682
Harald Weltef7c43522009-06-09 20:24:21 +00001683static int gsm48_rx_rr_classmark(struct msgb *msg)
1684{
1685 struct gsm48_hdr *gh = msgb_l3(msg);
1686 struct gsm_subscriber *subscr = msg->lchan->subscr;
1687 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1688 u_int8_t cm2_len, cm3_len = 0;
1689 u_int8_t *cm2, *cm3 = NULL;
1690
1691 DEBUGP(DRR, "CLASSMARK CHANGE ");
1692
1693 /* classmark 2 */
1694 cm2_len = gh->data[0];
1695 cm2 = &gh->data[1];
1696 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1697
1698 if (payload_len > cm2_len + 1) {
1699 /* we must have a classmark3 */
1700 if (gh->data[cm2_len+1] != 0x20) {
1701 DEBUGPC(DRR, "ERR CM3 TAG\n");
1702 return -EINVAL;
1703 }
1704 if (cm2_len > 3) {
1705 DEBUGPC(DRR, "CM2 too long!\n");
1706 return -EINVAL;
1707 }
1708
1709 cm3_len = gh->data[cm2_len+2];
1710 cm3 = &gh->data[cm2_len+3];
1711 if (cm3_len > 14) {
1712 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1713 return -EINVAL;
1714 }
1715 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1716 }
1717 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001718 subscr->equipment.classmark2_len = cm2_len;
1719 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001720 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001721 subscr->equipment.classmark3_len = cm3_len;
1722 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001723 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001724 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001725 }
1726
Harald Weltef7c43522009-06-09 20:24:21 +00001727 return 0;
1728}
1729
Harald Weltecf5b3592009-05-01 18:28:42 +00001730static int gsm48_rx_rr_status(struct msgb *msg)
1731{
1732 struct gsm48_hdr *gh = msgb_l3(msg);
1733
1734 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1735 rr_cause_name(gh->data[0]));
1736
1737 return 0;
1738}
1739
Harald Weltef7c43522009-06-09 20:24:21 +00001740static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1741{
1742 struct gsm48_hdr *gh = msgb_l3(msg);
1743 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1744 static struct gsm_meas_rep meas_rep;
1745
Harald Welte10d0e672009-06-27 02:53:10 +02001746 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001747 parse_meas_rep(&meas_rep, gh->data, payload_len);
1748 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001749 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001750 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001751 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001752 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001753 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001754 else
Harald Welte10d0e672009-06-27 02:53:10 +02001755 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001756 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1757 meas_rep.rxqual_sub);
1758
Harald Welte10d0e672009-06-27 02:53:10 +02001759 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001760
1761 /* FIXME: put the results somwhere */
1762
1763 return 0;
1764}
1765
Harald Weltebf5e8df2009-02-03 12:59:45 +00001766/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001767static int gsm0408_rcv_rr(struct msgb *msg)
1768{
1769 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001770 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001771
1772 switch (gh->msg_type) {
1773 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001774 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001775 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001776 case GSM48_MT_RR_GPRS_SUSP_REQ:
1777 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1778 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001779 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001780 rc = gsm48_rr_rx_pag_resp(msg);
1781 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001782 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1783 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte13cac662009-07-29 12:10:35 +02001784 /* We've successfully modified the MS side of the channel,
1785 * now go on to modify the BTS side of the channel */
Harald Welte9943c5b2009-07-29 15:41:29 +02001786 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte2c38aa82009-02-18 03:44:24 +00001787 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001788 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001789 case GSM48_MT_RR_STATUS:
1790 rc = gsm48_rx_rr_status(msg);
1791 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001792 case GSM48_MT_RR_MEAS_REP:
1793 rc = gsm48_rx_rr_meas_rep(msg);
1794 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001795 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001796 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001797 gh->msg_type);
1798 break;
1799 }
1800
Harald Welte2d35ae62009-02-06 12:02:13 +00001801 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001802}
1803
Harald Welte115d1032009-08-10 11:43:22 +02001804/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Holger Freythere64a7a32009-02-06 21:55:37 +00001805int gsm48_send_rr_release(struct gsm_lchan *lchan)
1806{
1807 struct msgb *msg = gsm48_msgb_alloc();
1808 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1809 u_int8_t *cause;
1810
1811 msg->lchan = lchan;
1812 gh->proto_discr = GSM48_PDISC_RR;
1813 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1814
1815 cause = msgb_put(msg, 1);
1816 cause[0] = GSM48_RR_CAUSE_NORMAL;
1817
1818 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1819 lchan->nr, lchan->type);
1820
Harald Welteae0f2362009-07-19 18:36:49 +02001821 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001822 gsm48_sendmsg(msg, NULL);
Harald Welte76042182009-08-08 16:03:15 +02001823 /* FIXME: Start Timer T3109 */
Harald Welteae0f2362009-07-19 18:36:49 +02001824
1825 /* Deactivate the SACCH on the BTS side */
1826 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001827}
1828
Harald Welte4bc90a12008-12-27 16:32:52 +00001829/* Call Control */
1830
Harald Welte7584aea2009-02-11 11:44:12 +00001831/* The entire call control code is written in accordance with Figure 7.10c
1832 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1833 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1834 * it for voice */
1835
Harald Welte4bfdfe72009-06-10 23:11:52 +08001836static void new_cc_state(struct gsm_trans *trans, int state)
1837{
1838 if (state > 31 || state < 0)
1839 return;
1840
1841 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltedcaf5652009-07-23 18:56:43 +02001842 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001843
Harald Weltedcaf5652009-07-23 18:56:43 +02001844 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001845}
1846
1847static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001848{
1849 struct msgb *msg = gsm48_msgb_alloc();
1850 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1851 u_int8_t *cause, *call_state;
1852
Harald Welte4bc90a12008-12-27 16:32:52 +00001853 gh->msg_type = GSM48_MT_CC_STATUS;
1854
1855 cause = msgb_put(msg, 3);
1856 cause[0] = 2;
1857 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1858 cause[2] = 0x80 | 30; /* response to status inquiry */
1859
1860 call_state = msgb_put(msg, 1);
1861 call_state[0] = 0xc0 | 0x00;
1862
Harald Welte39e2ead2009-07-23 21:13:03 +02001863 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001864}
1865
Harald Welte6f4b7532008-12-29 00:39:37 +00001866static int gsm48_tx_simple(struct gsm_lchan *lchan,
1867 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001868{
1869 struct msgb *msg = gsm48_msgb_alloc();
1870 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1871
1872 msg->lchan = lchan;
1873
Harald Welte6f4b7532008-12-29 00:39:37 +00001874 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001875 gh->msg_type = msg_type;
1876
Harald Welte39e2ead2009-07-23 21:13:03 +02001877 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001878}
1879
Harald Welte4bfdfe72009-06-10 23:11:52 +08001880static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1881{
Harald Weltedcaf5652009-07-23 18:56:43 +02001882 if (bsc_timer_pending(&trans->cc.timer)) {
1883 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1884 bsc_del_timer(&trans->cc.timer);
1885 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001886 }
1887}
1888
1889static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1890 int msg_type, struct gsm_mncc *mncc)
1891{
1892 struct msgb *msg;
1893
1894 if (trans)
1895 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001896 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001897 "Sending '%s' to MNCC.\n",
1898 trans->lchan->ts->trx->bts->nr,
1899 trans->lchan->ts->trx->nr,
1900 trans->lchan->ts->nr, trans->transaction_id,
1901 (trans->subscr)?(trans->subscr->extension):"-",
1902 get_mncc_name(msg_type));
1903 else
1904 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1905 "Sending '%s' to MNCC.\n",
1906 (trans->subscr)?(trans->subscr->extension):"-",
1907 get_mncc_name(msg_type));
1908 else
1909 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1910 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1911
1912 mncc->msg_type = msg_type;
1913
Harald Welte966636f2009-06-26 19:39:35 +02001914 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001915 if (!msg)
1916 return -ENOMEM;
1917 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1918 msgb_enqueue(&net->upqueue, msg);
1919
1920 return 0;
1921}
1922
1923int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1924 u_int32_t callref, int location, int value)
1925{
1926 struct gsm_mncc rel;
1927
Harald Welte92f70c52009-06-12 01:54:08 +08001928 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001929 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001930 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001931 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1932}
1933
Harald Weltedcaf5652009-07-23 18:56:43 +02001934/* Call Control Specific transaction release.
1935 * gets called by trans_free, DO NOT CALL YOURSELF! */
1936void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001937{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001938 gsm48_stop_cc_timer(trans);
1939
1940 /* send release to L4, if callref still exists */
1941 if (trans->callref) {
1942 /* Ressource unavailable */
Harald Welte596fed42009-07-23 19:06:52 +02001943 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001944 GSM48_CAUSE_LOC_PRN_S_LU,
1945 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001946 }
Harald Weltedcaf5652009-07-23 18:56:43 +02001947 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001948 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltedcaf5652009-07-23 18:56:43 +02001949 if (trans->lchan)
1950 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001951}
1952
1953static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1954
Harald Welte09e38af2009-02-16 22:52:23 +00001955/* call-back from paging the B-end of the connection */
1956static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001957 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001958{
Harald Welte7ccf7782009-02-17 01:43:01 +00001959 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001960 struct gsm_subscriber *subscr = param;
1961 struct gsm_trans *transt, *tmp;
1962 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001963
Harald Welte09e38af2009-02-16 22:52:23 +00001964 if (hooknum != GSM_HOOK_RR_PAGING)
1965 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001966
1967 if (!subscr)
1968 return -EINVAL;
1969 net = subscr->net;
1970 if (!net) {
1971 DEBUGP(DCC, "Error Network not set!\n");
1972 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001973 }
Harald Welte7584aea2009-02-11 11:44:12 +00001974
Harald Welte4bfdfe72009-06-10 23:11:52 +08001975 /* check all tranactions (without lchan) for subscriber */
1976 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
1977 if (transt->subscr != subscr || transt->lchan)
1978 continue;
1979 switch (event) {
1980 case GSM_PAGING_SUCCEEDED:
1981 if (!lchan) // paranoid
1982 break;
1983 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
1984 subscr->extension);
1985 /* Assign lchan */
1986 if (!transt->lchan) {
1987 transt->lchan = lchan;
1988 use_lchan(lchan);
1989 }
1990 /* send SETUP request to called party */
Harald Weltedcaf5652009-07-23 18:56:43 +02001991 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001992 break;
1993 case GSM_PAGING_EXPIRED:
1994 DEBUGP(DCC, "Paging subscr %s expired!\n",
1995 subscr->extension);
1996 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02001997 mncc_release_ind(transt->subscr->net, transt,
1998 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001999 GSM48_CAUSE_LOC_PRN_S_LU,
2000 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002001 transt->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002002 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002003 break;
2004 }
2005 }
Harald Welte09e38af2009-02-16 22:52:23 +00002006 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00002007}
Harald Welte7584aea2009-02-11 11:44:12 +00002008
Harald Welte805f6442009-07-28 18:25:29 +02002009/* some other part of the code sends us a signal */
2010static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2011 void *handler_data, void *signal_data)
2012{
2013 struct gsm_lchan *lchan = signal_data;
2014 struct gsm_bts_trx_ts *ts;
2015 int rc;
2016
2017 if (subsys != SS_ABISIP)
2018 return 0;
2019
2020 /* in case we use direct BTS-to-BTS RTP */
2021 if (ipacc_rtp_direct)
2022 return 0;
2023
2024 ts = lchan->ts;
2025
2026 switch (signal) {
2027 case S_ABISIP_BIND_ACK:
2028 /* the BTS has successfully bound a TCH to a local ip/port,
2029 * which means we can connect our UDP socket to it */
2030 if (ts->abis_ip.rtp_socket) {
2031 rtp_socket_free(ts->abis_ip.rtp_socket);
2032 ts->abis_ip.rtp_socket = NULL;
2033 }
2034
2035 ts->abis_ip.rtp_socket = rtp_socket_create();
2036 if (!ts->abis_ip.rtp_socket)
2037 goto out_err;
2038
2039 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2040 ts->abis_ip.bound_ip,
2041 ts->abis_ip.bound_port);
2042 if (rc < 0)
2043 goto out_err;
2044 break;
2045 case S_ABISIP_DISC_IND:
2046 /* the BTS tells us a RTP stream has been disconnected */
2047 if (ts->abis_ip.rtp_socket) {
2048 rtp_socket_free(ts->abis_ip.rtp_socket);
2049 ts->abis_ip.rtp_socket = NULL;
2050 }
2051 break;
2052 }
2053
2054 return 0;
2055out_err:
2056 /* FIXME: do something */
2057 return 0;
2058}
2059
2060/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2061static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2062{
2063 struct gsm_bts_trx_ts *ts = lchan->ts;
2064 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2065 int rc;
2066
2067 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2068 ntohs(rs->rtp.sin_local.sin_port),
2069 ts->abis_ip.conn_id,
2070 /* FIXME: use RTP payload of bound socket, not BTS*/
2071 ts->abis_ip.rtp_payload2);
2072
2073 return rc;
2074}
2075
Harald Welte49f48b82009-02-17 15:29:33 +00002076/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00002077static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00002078{
Harald Welte11fa29c2009-02-19 17:24:39 +00002079 struct gsm_bts *bts = lchan->ts->trx->bts;
2080 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00002081 struct gsm_bts_trx_ts *ts;
Harald Welte805f6442009-07-28 18:25:29 +02002082 int rc;
Harald Welte49f48b82009-02-17 15:29:33 +00002083
Harald Welte11fa29c2009-02-19 17:24:39 +00002084 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2085 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2086 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2087
2088 if (bts->type != remote_bts->type) {
2089 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2090 return -EINVAL;
2091 }
Harald Welte49f48b82009-02-17 15:29:33 +00002092
Harald Welte11fa29c2009-02-19 17:24:39 +00002093 switch (bts->type) {
2094 case GSM_BTS_TYPE_NANOBTS_900:
2095 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte805f6442009-07-28 18:25:29 +02002096 if (!ipacc_rtp_direct) {
2097 /* connect the TCH's to our RTP proxy */
2098 rc = ipacc_connect_proxy_bind(lchan);
2099 if (rc < 0)
2100 return rc;
2101 rc = ipacc_connect_proxy_bind(remote_lchan);
2102
2103 /* connect them with each other */
2104 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2105 remote_lchan->ts->abis_ip.rtp_socket);
2106 } else {
2107 /* directly connect TCH RTP streams to each other */
2108 ts = remote_lchan->ts;
2109 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2110 ts->abis_ip.bound_port,
2111 lchan->ts->abis_ip.conn_id,
2112 ts->abis_ip.rtp_payload2);
2113 if (rc < 0)
2114 return rc;
2115 ts = lchan->ts;
2116 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2117 ts->abis_ip.bound_port,
2118 remote_lchan->ts->abis_ip.conn_id,
2119 ts->abis_ip.rtp_payload2);
2120 }
Harald Welte11fa29c2009-02-19 17:24:39 +00002121 break;
2122 case GSM_BTS_TYPE_BS11:
2123 trau_mux_map_lchan(lchan, remote_lchan);
2124 break;
2125 default:
2126 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte805f6442009-07-28 18:25:29 +02002127 rc = -EINVAL;
Harald Welte11fa29c2009-02-19 17:24:39 +00002128 break;
2129 }
Harald Welte49f48b82009-02-17 15:29:33 +00002130
2131 return 0;
2132}
2133
Harald Welte4bfdfe72009-06-10 23:11:52 +08002134/* bridge channels of two transactions */
2135static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002136{
Harald Weltedcaf5652009-07-23 18:56:43 +02002137 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2138 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002139
Harald Welte4bfdfe72009-06-10 23:11:52 +08002140 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002141 return -EIO;
2142
Harald Welte4bfdfe72009-06-10 23:11:52 +08002143 if (!trans1->lchan || !trans2->lchan)
2144 return -EIO;
2145
2146 /* through-connect channel */
2147 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002148}
2149
Harald Welte4bfdfe72009-06-10 23:11:52 +08002150/* enable receive of channels to upqueue */
2151static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2152{
2153 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002154
Harald Welte4bfdfe72009-06-10 23:11:52 +08002155 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002156 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002157 if (!trans)
2158 return -EIO;
2159 if (!trans->lchan)
2160 return 0;
2161
2162 // todo IPACCESS
2163 if (enable)
2164 return trau_recv_lchan(trans->lchan, data->callref);
2165 return trau_mux_unmap(NULL, data->callref);
2166}
2167
2168/* send a frame to channel */
2169static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2170{
2171 struct gsm_trans *trans;
2172
2173 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002174 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002175 if (!trans)
2176 return -EIO;
2177 if (!trans->lchan)
2178 return 0;
2179 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2180 trans->lchan->type != GSM_LCHAN_TCH_H)
2181 return 0;
2182
2183 // todo IPACCESS
2184 return trau_send_lchan(trans->lchan,
2185 (struct decoded_trau_frame *)frame->data);
2186}
2187
2188
2189static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2190{
2191 DEBUGP(DCC, "-> STATUS ENQ\n");
2192 return gsm48_cc_tx_status(trans, msg);
2193}
2194
2195static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2196static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2197
2198static void gsm48_cc_timeout(void *arg)
2199{
2200 struct gsm_trans *trans = arg;
2201 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002202 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2203 int mo_location = GSM48_CAUSE_LOC_USER;
2204 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2205 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002206 struct gsm_mncc mo_rel, l4_rel;
2207
2208 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2209 mo_rel.callref = trans->callref;
2210 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2211 l4_rel.callref = trans->callref;
2212
Harald Weltedcaf5652009-07-23 18:56:43 +02002213 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002214 case 0x303:
2215 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002216 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002217 break;
2218 case 0x310:
2219 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002220 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002221 break;
2222 case 0x313:
2223 disconnect = 1;
2224 /* unknown, did not find it in the specs */
2225 break;
2226 case 0x301:
2227 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002228 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002229 break;
2230 case 0x308:
Harald Weltedcaf5652009-07-23 18:56:43 +02002231 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002232 /* restart T308 a second time */
Harald Weltedcaf5652009-07-23 18:56:43 +02002233 gsm48_cc_tx_release(trans, &trans->cc.msg);
2234 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002235 break; /* stay in release state */
2236 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002237 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002238 return;
2239// release = 1;
2240// l4_cause = 14;
2241// break;
2242 case 0x306:
2243 release = 1;
Harald Weltedcaf5652009-07-23 18:56:43 +02002244 mo_cause = trans->cc.msg.cause.value;
2245 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002246 break;
2247 case 0x323:
2248 disconnect = 1;
2249 break;
2250 default:
2251 release = 1;
2252 }
2253
2254 if (release && trans->callref) {
2255 /* process release towards layer 4 */
Harald Welte596fed42009-07-23 19:06:52 +02002256 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002257 l4_location, l4_cause);
2258 trans->callref = 0;
2259 }
2260
2261 if (disconnect && trans->callref) {
2262 /* process disconnect towards layer 4 */
2263 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte596fed42009-07-23 19:06:52 +02002264 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002265 }
2266
2267 /* process disconnect towards mobile station */
2268 if (disconnect || release) {
2269 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltedcaf5652009-07-23 18:56:43 +02002270 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2271 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2272 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002273 mo_rel.cause.diag_len = 3;
2274
2275 if (disconnect)
2276 gsm48_cc_tx_disconnect(trans, &mo_rel);
2277 if (release)
2278 gsm48_cc_tx_release(trans, &mo_rel);
2279 }
2280
2281}
2282
2283static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2284 int sec, int micro)
2285{
2286 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltedcaf5652009-07-23 18:56:43 +02002287 trans->cc.timer.cb = gsm48_cc_timeout;
2288 trans->cc.timer.data = trans;
2289 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2290 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002291}
2292
2293static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2294{
2295 struct gsm48_hdr *gh = msgb_l3(msg);
2296 u_int8_t msg_type = gh->msg_type & 0xbf;
2297 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2298 struct tlv_parsed tp;
2299 struct gsm_mncc setup;
2300
2301 memset(&setup, 0, sizeof(struct gsm_mncc));
2302 setup.callref = trans->callref;
2303 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2304 /* emergency setup is identified by msg_type */
2305 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2306 setup.emergency = 1;
2307
2308 /* use subscriber as calling party number */
2309 if (trans->subscr) {
2310 setup.fields |= MNCC_F_CALLING;
2311 strncpy(setup.calling.number, trans->subscr->extension,
2312 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002313 strncpy(setup.imsi, trans->subscr->imsi,
2314 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002315 }
2316 /* bearer capability */
2317 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2318 setup.fields |= MNCC_F_BEARER_CAP;
2319 decode_bearer_cap(&setup.bearer_cap,
2320 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2321 }
2322 /* facility */
2323 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2324 setup.fields |= MNCC_F_FACILITY;
2325 decode_facility(&setup.facility,
2326 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2327 }
2328 /* called party bcd number */
2329 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2330 setup.fields |= MNCC_F_CALLED;
2331 decode_called(&setup.called,
2332 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2333 }
2334 /* user-user */
2335 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2336 setup.fields |= MNCC_F_USERUSER;
2337 decode_useruser(&setup.useruser,
2338 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2339 }
2340 /* ss-version */
2341 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2342 setup.fields |= MNCC_F_SSVERSION;
2343 decode_ssversion(&setup.ssversion,
2344 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2345 }
2346 /* CLIR suppression */
2347 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2348 setup.clir.sup = 1;
2349 /* CLIR invocation */
2350 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2351 setup.clir.inv = 1;
2352 /* cc cap */
2353 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2354 setup.fields |= MNCC_F_CCCAP;
2355 decode_cccap(&setup.cccap,
2356 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2357 }
2358
Harald Welte4bfdfe72009-06-10 23:11:52 +08002359 new_cc_state(trans, GSM_CSTATE_INITIATED);
2360
2361 /* indicate setup to MNCC */
Harald Welte596fed42009-07-23 19:06:52 +02002362 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002363
Harald Welte13cac662009-07-29 12:10:35 +02002364 /* MNCC code will modify the channel asynchronously, we should
2365 * ipaccess-bind only after the modification has been made to the
2366 * lchan->tch_mode */
Harald Welte4bfdfe72009-06-10 23:11:52 +08002367 return 0;
2368}
2369
2370static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002371{
2372 struct msgb *msg = gsm48_msgb_alloc();
2373 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002374 struct gsm_mncc *setup = arg;
Harald Welte78283ef2009-07-23 21:36:44 +02002375 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00002376
Harald Welte7ccf7782009-02-17 01:43:01 +00002377 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002378
Harald Welte4bfdfe72009-06-10 23:11:52 +08002379 /* transaction id must not be assigned */
2380 if (trans->transaction_id != 0xff) { /* unasssigned */
2381 DEBUGP(DCC, "TX Setup with assigned transaction. "
2382 "This is not allowed!\n");
2383 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002384 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002385 GSM48_CAUSE_LOC_PRN_S_LU,
2386 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002387 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002388 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002389 return rc;
2390 }
2391
2392 /* Get free transaction_id */
Harald Welte78283ef2009-07-23 21:36:44 +02002393 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2394 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002395 /* no free transaction ID */
Harald Welte596fed42009-07-23 19:06:52 +02002396 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002397 GSM48_CAUSE_LOC_PRN_S_LU,
2398 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002399 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002400 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002401 return rc;
2402 }
Harald Welte78283ef2009-07-23 21:36:44 +02002403 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00002404
Harald Welte65e74cc2008-12-29 01:55:35 +00002405 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002406
Harald Welte4bfdfe72009-06-10 23:11:52 +08002407 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002408
Harald Welte4bfdfe72009-06-10 23:11:52 +08002409 /* bearer capability */
2410 if (setup->fields & MNCC_F_BEARER_CAP)
2411 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2412 /* facility */
2413 if (setup->fields & MNCC_F_FACILITY)
2414 encode_facility(msg, 0, &setup->facility);
2415 /* progress */
2416 if (setup->fields & MNCC_F_PROGRESS)
2417 encode_progress(msg, 0, &setup->progress);
2418 /* calling party BCD number */
2419 if (setup->fields & MNCC_F_CALLING)
2420 encode_calling(msg, &setup->calling);
2421 /* called party BCD number */
2422 if (setup->fields & MNCC_F_CALLED)
2423 encode_called(msg, &setup->called);
2424 /* user-user */
2425 if (setup->fields & MNCC_F_USERUSER)
2426 encode_useruser(msg, 0, &setup->useruser);
2427 /* redirecting party BCD number */
2428 if (setup->fields & MNCC_F_REDIRECTING)
2429 encode_redirecting(msg, &setup->redirecting);
2430 /* signal */
2431 if (setup->fields & MNCC_F_SIGNAL)
2432 encode_signal(msg, setup->signal);
2433
2434 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002435
Harald Welte39e2ead2009-07-23 21:13:03 +02002436 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002437}
2438
Harald Welte4bfdfe72009-06-10 23:11:52 +08002439static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2440{
2441 struct gsm48_hdr *gh = msgb_l3(msg);
2442 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2443 struct tlv_parsed tp;
2444 struct gsm_mncc call_conf;
2445
2446 gsm48_stop_cc_timer(trans);
2447 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2448
2449 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2450 call_conf.callref = trans->callref;
2451 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2452#if 0
2453 /* repeat */
2454 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2455 call_conf.repeat = 1;
2456 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2457 call_conf.repeat = 2;
2458#endif
2459 /* bearer capability */
2460 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2461 call_conf.fields |= MNCC_F_BEARER_CAP;
2462 decode_bearer_cap(&call_conf.bearer_cap,
2463 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2464 }
2465 /* cause */
2466 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2467 call_conf.fields |= MNCC_F_CAUSE;
2468 decode_cause(&call_conf.cause,
2469 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2470 }
2471 /* cc cap */
2472 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2473 call_conf.fields |= MNCC_F_CCCAP;
2474 decode_cccap(&call_conf.cccap,
2475 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2476 }
2477
2478 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2479
Harald Welte596fed42009-07-23 19:06:52 +02002480 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2481 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002482}
2483
2484static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2485{
2486 struct gsm_mncc *proceeding = arg;
2487 struct msgb *msg = gsm48_msgb_alloc();
2488 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2489
Harald Welte4bfdfe72009-06-10 23:11:52 +08002490 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2491
2492 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2493
2494 /* bearer capability */
2495 if (proceeding->fields & MNCC_F_BEARER_CAP)
2496 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2497 /* facility */
2498 if (proceeding->fields & MNCC_F_FACILITY)
2499 encode_facility(msg, 0, &proceeding->facility);
2500 /* progress */
2501 if (proceeding->fields & MNCC_F_PROGRESS)
2502 encode_progress(msg, 0, &proceeding->progress);
2503
Harald Welte39e2ead2009-07-23 21:13:03 +02002504 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002505}
2506
2507static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2508{
2509 struct gsm48_hdr *gh = msgb_l3(msg);
2510 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2511 struct tlv_parsed tp;
2512 struct gsm_mncc alerting;
2513
2514 gsm48_stop_cc_timer(trans);
2515 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2516
2517 memset(&alerting, 0, sizeof(struct gsm_mncc));
2518 alerting.callref = trans->callref;
2519 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2520 /* facility */
2521 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2522 alerting.fields |= MNCC_F_FACILITY;
2523 decode_facility(&alerting.facility,
2524 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2525 }
2526
2527 /* progress */
2528 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2529 alerting.fields |= MNCC_F_PROGRESS;
2530 decode_progress(&alerting.progress,
2531 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2532 }
2533 /* ss-version */
2534 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2535 alerting.fields |= MNCC_F_SSVERSION;
2536 decode_ssversion(&alerting.ssversion,
2537 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2538 }
2539
2540 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2541
Harald Welte596fed42009-07-23 19:06:52 +02002542 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2543 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002544}
2545
2546static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2547{
2548 struct gsm_mncc *alerting = arg;
2549 struct msgb *msg = gsm48_msgb_alloc();
2550 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2551
Harald Welte4bfdfe72009-06-10 23:11:52 +08002552 gh->msg_type = GSM48_MT_CC_ALERTING;
2553
2554 /* facility */
2555 if (alerting->fields & MNCC_F_FACILITY)
2556 encode_facility(msg, 0, &alerting->facility);
2557 /* progress */
2558 if (alerting->fields & MNCC_F_PROGRESS)
2559 encode_progress(msg, 0, &alerting->progress);
2560 /* user-user */
2561 if (alerting->fields & MNCC_F_USERUSER)
2562 encode_useruser(msg, 0, &alerting->useruser);
2563
2564 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2565
Harald Welte39e2ead2009-07-23 21:13:03 +02002566 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002567}
2568
2569static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2570{
2571 struct gsm_mncc *progress = arg;
2572 struct msgb *msg = gsm48_msgb_alloc();
2573 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2574
Harald Welte4bfdfe72009-06-10 23:11:52 +08002575 gh->msg_type = GSM48_MT_CC_PROGRESS;
2576
2577 /* progress */
2578 encode_progress(msg, 1, &progress->progress);
2579 /* user-user */
2580 if (progress->fields & MNCC_F_USERUSER)
2581 encode_useruser(msg, 0, &progress->useruser);
2582
Harald Welte39e2ead2009-07-23 21:13:03 +02002583 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002584}
2585
2586static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2587{
2588 struct gsm_mncc *connect = arg;
2589 struct msgb *msg = gsm48_msgb_alloc();
2590 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2591
Harald Welte4bfdfe72009-06-10 23:11:52 +08002592 gh->msg_type = GSM48_MT_CC_CONNECT;
2593
2594 gsm48_stop_cc_timer(trans);
2595 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2596
2597 /* facility */
2598 if (connect->fields & MNCC_F_FACILITY)
2599 encode_facility(msg, 0, &connect->facility);
2600 /* progress */
2601 if (connect->fields & MNCC_F_PROGRESS)
2602 encode_progress(msg, 0, &connect->progress);
2603 /* connected number */
2604 if (connect->fields & MNCC_F_CONNECTED)
2605 encode_connected(msg, &connect->connected);
2606 /* user-user */
2607 if (connect->fields & MNCC_F_USERUSER)
2608 encode_useruser(msg, 0, &connect->useruser);
2609
2610 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2611
Harald Welte39e2ead2009-07-23 21:13:03 +02002612 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002613}
2614
2615static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2616{
2617 struct gsm48_hdr *gh = msgb_l3(msg);
2618 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2619 struct tlv_parsed tp;
2620 struct gsm_mncc connect;
2621
2622 gsm48_stop_cc_timer(trans);
2623
2624 memset(&connect, 0, sizeof(struct gsm_mncc));
2625 connect.callref = trans->callref;
2626 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2627 /* use subscriber as connected party number */
2628 if (trans->subscr) {
2629 connect.fields |= MNCC_F_CONNECTED;
2630 strncpy(connect.connected.number, trans->subscr->extension,
2631 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002632 strncpy(connect.imsi, trans->subscr->imsi,
2633 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002634 }
2635 /* facility */
2636 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2637 connect.fields |= MNCC_F_FACILITY;
2638 decode_facility(&connect.facility,
2639 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2640 }
2641 /* user-user */
2642 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2643 connect.fields |= MNCC_F_USERUSER;
2644 decode_useruser(&connect.useruser,
2645 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2646 }
2647 /* ss-version */
2648 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2649 connect.fields |= MNCC_F_SSVERSION;
2650 decode_ssversion(&connect.ssversion,
2651 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2652 }
2653
2654 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2655
Harald Welte596fed42009-07-23 19:06:52 +02002656 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002657}
2658
2659
2660static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2661{
2662 struct gsm_mncc connect_ack;
2663
2664 gsm48_stop_cc_timer(trans);
2665
2666 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2667
2668 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2669 connect_ack.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002670 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002671 &connect_ack);
2672}
2673
2674static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2675{
2676 struct msgb *msg = gsm48_msgb_alloc();
2677 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2678
Harald Welte4bfdfe72009-06-10 23:11:52 +08002679 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2680
2681 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2682
Harald Welte39e2ead2009-07-23 21:13:03 +02002683 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002684}
2685
2686static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2687{
2688 struct gsm48_hdr *gh = msgb_l3(msg);
2689 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2690 struct tlv_parsed tp;
2691 struct gsm_mncc disc;
2692
2693 gsm48_stop_cc_timer(trans);
2694
2695 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2696
2697 memset(&disc, 0, sizeof(struct gsm_mncc));
2698 disc.callref = trans->callref;
2699 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2700 /* cause */
2701 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2702 disc.fields |= MNCC_F_CAUSE;
2703 decode_cause(&disc.cause,
2704 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2705 }
2706 /* facility */
2707 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2708 disc.fields |= MNCC_F_FACILITY;
2709 decode_facility(&disc.facility,
2710 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2711 }
2712 /* user-user */
2713 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2714 disc.fields |= MNCC_F_USERUSER;
2715 decode_useruser(&disc.useruser,
2716 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2717 }
2718 /* ss-version */
2719 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2720 disc.fields |= MNCC_F_SSVERSION;
2721 decode_ssversion(&disc.ssversion,
2722 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2723 }
2724
Harald Welte596fed42009-07-23 19:06:52 +02002725 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002726
2727}
2728
Harald Weltec66b71c2009-06-11 14:23:20 +08002729static struct gsm_mncc_cause default_cause = {
2730 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2731 .coding = 0,
2732 .rec = 0,
2733 .rec_val = 0,
2734 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2735 .diag_len = 0,
2736 .diag = { 0 },
2737};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002738
2739static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2740{
2741 struct gsm_mncc *disc = arg;
2742 struct msgb *msg = gsm48_msgb_alloc();
2743 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2744
Harald Welte4bfdfe72009-06-10 23:11:52 +08002745 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2746
2747 gsm48_stop_cc_timer(trans);
2748 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2749
2750 /* cause */
2751 if (disc->fields & MNCC_F_CAUSE)
2752 encode_cause(msg, 1, &disc->cause);
2753 else
2754 encode_cause(msg, 1, &default_cause);
2755
2756 /* facility */
2757 if (disc->fields & MNCC_F_FACILITY)
2758 encode_facility(msg, 0, &disc->facility);
2759 /* progress */
2760 if (disc->fields & MNCC_F_PROGRESS)
2761 encode_progress(msg, 0, &disc->progress);
2762 /* user-user */
2763 if (disc->fields & MNCC_F_USERUSER)
2764 encode_useruser(msg, 0, &disc->useruser);
2765
2766 /* store disconnect cause for T306 expiry */
Harald Weltedcaf5652009-07-23 18:56:43 +02002767 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002768
2769 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2770
Harald Welte39e2ead2009-07-23 21:13:03 +02002771 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002772}
2773
2774static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2775{
2776 struct gsm48_hdr *gh = msgb_l3(msg);
2777 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2778 struct tlv_parsed tp;
2779 struct gsm_mncc rel;
2780 int rc;
2781
2782 gsm48_stop_cc_timer(trans);
2783
2784 memset(&rel, 0, sizeof(struct gsm_mncc));
2785 rel.callref = trans->callref;
2786 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2787 /* cause */
2788 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2789 rel.fields |= MNCC_F_CAUSE;
2790 decode_cause(&rel.cause,
2791 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2792 }
2793 /* facility */
2794 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2795 rel.fields |= MNCC_F_FACILITY;
2796 decode_facility(&rel.facility,
2797 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2798 }
2799 /* user-user */
2800 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2801 rel.fields |= MNCC_F_USERUSER;
2802 decode_useruser(&rel.useruser,
2803 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2804 }
2805 /* ss-version */
2806 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2807 rel.fields |= MNCC_F_SSVERSION;
2808 decode_ssversion(&rel.ssversion,
2809 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2810 }
2811
Harald Weltedcaf5652009-07-23 18:56:43 +02002812 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002813 /* release collision 5.4.5 */
Harald Welte596fed42009-07-23 19:06:52 +02002814 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002815 } else {
Harald Welte596fed42009-07-23 19:06:52 +02002816 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002817 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte596fed42009-07-23 19:06:52 +02002818 GSM48_MT_CC_RELEASE_COMPL);
2819 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002820 }
2821
2822 new_cc_state(trans, GSM_CSTATE_NULL);
2823
2824 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002825 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002826
2827 return rc;
2828}
2829
2830static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2831{
2832 struct gsm_mncc *rel = arg;
2833 struct msgb *msg = gsm48_msgb_alloc();
2834 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2835
Harald Welte4bfdfe72009-06-10 23:11:52 +08002836 gh->msg_type = GSM48_MT_CC_RELEASE;
2837
2838 trans->callref = 0;
2839
2840 gsm48_stop_cc_timer(trans);
2841 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2842
2843 /* cause */
2844 if (rel->fields & MNCC_F_CAUSE)
2845 encode_cause(msg, 0, &rel->cause);
2846 /* facility */
2847 if (rel->fields & MNCC_F_FACILITY)
2848 encode_facility(msg, 0, &rel->facility);
2849 /* user-user */
2850 if (rel->fields & MNCC_F_USERUSER)
2851 encode_useruser(msg, 0, &rel->useruser);
2852
Harald Weltedcaf5652009-07-23 18:56:43 +02002853 trans->cc.T308_second = 0;
2854 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002855
Harald Weltedcaf5652009-07-23 18:56:43 +02002856 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002857 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2858
Harald Welte39e2ead2009-07-23 21:13:03 +02002859 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002860}
2861
2862static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2863{
2864 struct gsm48_hdr *gh = msgb_l3(msg);
2865 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2866 struct tlv_parsed tp;
2867 struct gsm_mncc rel;
2868 int rc = 0;
2869
2870 gsm48_stop_cc_timer(trans);
2871
2872 memset(&rel, 0, sizeof(struct gsm_mncc));
2873 rel.callref = trans->callref;
2874 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2875 /* cause */
2876 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2877 rel.fields |= MNCC_F_CAUSE;
2878 decode_cause(&rel.cause,
2879 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2880 }
2881 /* facility */
2882 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2883 rel.fields |= MNCC_F_FACILITY;
2884 decode_facility(&rel.facility,
2885 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2886 }
2887 /* user-user */
2888 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2889 rel.fields |= MNCC_F_USERUSER;
2890 decode_useruser(&rel.useruser,
2891 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2892 }
2893 /* ss-version */
2894 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2895 rel.fields |= MNCC_F_SSVERSION;
2896 decode_ssversion(&rel.ssversion,
2897 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2898 }
2899
2900 if (trans->callref) {
Harald Weltedcaf5652009-07-23 18:56:43 +02002901 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002902 case GSM_CSTATE_CALL_PRESENT:
Harald Welte596fed42009-07-23 19:06:52 +02002903 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002904 MNCC_REJ_IND, &rel);
2905 break;
2906 case GSM_CSTATE_RELEASE_REQ:
Harald Welte596fed42009-07-23 19:06:52 +02002907 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002908 MNCC_REL_CNF, &rel);
2909 break;
2910 default:
Harald Welte596fed42009-07-23 19:06:52 +02002911 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002912 MNCC_REL_IND, &rel);
2913 }
2914 }
2915
2916 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002917 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002918
2919 return rc;
2920}
2921
2922static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2923{
2924 struct gsm_mncc *rel = arg;
2925 struct msgb *msg = gsm48_msgb_alloc();
2926 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2927
Harald Welte4bfdfe72009-06-10 23:11:52 +08002928 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2929
2930 trans->callref = 0;
2931
2932 gsm48_stop_cc_timer(trans);
2933
2934 /* cause */
2935 if (rel->fields & MNCC_F_CAUSE)
2936 encode_cause(msg, 0, &rel->cause);
2937 /* facility */
2938 if (rel->fields & MNCC_F_FACILITY)
2939 encode_facility(msg, 0, &rel->facility);
2940 /* user-user */
2941 if (rel->fields & MNCC_F_USERUSER)
2942 encode_useruser(msg, 0, &rel->useruser);
2943
Harald Weltedcaf5652009-07-23 18:56:43 +02002944 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002945
Harald Welte39e2ead2009-07-23 21:13:03 +02002946 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002947}
2948
2949static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2950{
2951 struct gsm48_hdr *gh = msgb_l3(msg);
2952 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2953 struct tlv_parsed tp;
2954 struct gsm_mncc fac;
2955
2956 memset(&fac, 0, sizeof(struct gsm_mncc));
2957 fac.callref = trans->callref;
2958 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2959 /* facility */
2960 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2961 fac.fields |= MNCC_F_FACILITY;
2962 decode_facility(&fac.facility,
2963 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2964 }
2965 /* ss-version */
2966 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2967 fac.fields |= MNCC_F_SSVERSION;
2968 decode_ssversion(&fac.ssversion,
2969 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2970 }
2971
Harald Welte596fed42009-07-23 19:06:52 +02002972 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002973}
2974
2975static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2976{
2977 struct gsm_mncc *fac = arg;
2978 struct msgb *msg = gsm48_msgb_alloc();
2979 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2980
Harald Welte4bfdfe72009-06-10 23:11:52 +08002981 gh->msg_type = GSM48_MT_CC_FACILITY;
2982
2983 /* facility */
2984 encode_facility(msg, 1, &fac->facility);
2985
Harald Welte39e2ead2009-07-23 21:13:03 +02002986 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002987}
2988
2989static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2990{
2991 struct gsm_mncc hold;
2992
2993 memset(&hold, 0, sizeof(struct gsm_mncc));
2994 hold.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002995 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002996}
2997
2998static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2999{
3000 struct msgb *msg = gsm48_msgb_alloc();
3001 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3002
Harald Welte4bfdfe72009-06-10 23:11:52 +08003003 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3004
Harald Welte39e2ead2009-07-23 21:13:03 +02003005 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003006}
3007
3008static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3009{
3010 struct gsm_mncc *hold_rej = arg;
3011 struct msgb *msg = gsm48_msgb_alloc();
3012 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3013
Harald Welte4bfdfe72009-06-10 23:11:52 +08003014 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3015
3016 /* cause */
3017 if (hold_rej->fields & MNCC_F_CAUSE)
3018 encode_cause(msg, 1, &hold_rej->cause);
3019 else
3020 encode_cause(msg, 1, &default_cause);
3021
Harald Welte39e2ead2009-07-23 21:13:03 +02003022 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003023}
3024
3025static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3026{
3027 struct gsm_mncc retrieve;
3028
3029 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3030 retrieve.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003031 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3032 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003033}
3034
3035static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3036{
3037 struct msgb *msg = gsm48_msgb_alloc();
3038 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3039
Harald Welte4bfdfe72009-06-10 23:11:52 +08003040 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3041
Harald Welte39e2ead2009-07-23 21:13:03 +02003042 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003043}
3044
3045static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3046{
3047 struct gsm_mncc *retrieve_rej = arg;
3048 struct msgb *msg = gsm48_msgb_alloc();
3049 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3050
Harald Welte4bfdfe72009-06-10 23:11:52 +08003051 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3052
3053 /* cause */
3054 if (retrieve_rej->fields & MNCC_F_CAUSE)
3055 encode_cause(msg, 1, &retrieve_rej->cause);
3056 else
3057 encode_cause(msg, 1, &default_cause);
3058
Harald Welte39e2ead2009-07-23 21:13:03 +02003059 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003060}
3061
3062static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3063{
3064 struct gsm48_hdr *gh = msgb_l3(msg);
3065 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3066 struct tlv_parsed tp;
3067 struct gsm_mncc dtmf;
3068
3069 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3070 dtmf.callref = trans->callref;
3071 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3072 /* keypad facility */
3073 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3074 dtmf.fields |= MNCC_F_KEYPAD;
3075 decode_keypad(&dtmf.keypad,
3076 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3077 }
3078
Harald Welte596fed42009-07-23 19:06:52 +02003079 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003080}
3081
3082static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3083{
3084 struct gsm_mncc *dtmf = arg;
3085 struct msgb *msg = gsm48_msgb_alloc();
3086 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3087
Harald Welte4bfdfe72009-06-10 23:11:52 +08003088 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3089
3090 /* keypad */
3091 if (dtmf->fields & MNCC_F_KEYPAD)
3092 encode_keypad(msg, dtmf->keypad);
3093
Harald Welte39e2ead2009-07-23 21:13:03 +02003094 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003095}
3096
3097static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3098{
3099 struct gsm_mncc *dtmf = arg;
3100 struct msgb *msg = gsm48_msgb_alloc();
3101 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3102
Harald Welte4bfdfe72009-06-10 23:11:52 +08003103 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3104
3105 /* cause */
3106 if (dtmf->fields & MNCC_F_CAUSE)
3107 encode_cause(msg, 1, &dtmf->cause);
3108 else
3109 encode_cause(msg, 1, &default_cause);
3110
Harald Welte39e2ead2009-07-23 21:13:03 +02003111 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003112}
3113
3114static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3115{
3116 struct msgb *msg = gsm48_msgb_alloc();
3117 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3118
Harald Welte4bfdfe72009-06-10 23:11:52 +08003119 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3120
Harald Welte39e2ead2009-07-23 21:13:03 +02003121 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003122}
3123
3124static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3125{
3126 struct gsm_mncc dtmf;
3127
3128 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3129 dtmf.callref = trans->callref;
3130
Harald Welte596fed42009-07-23 19:06:52 +02003131 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003132}
3133
3134static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3135{
3136 struct gsm48_hdr *gh = msgb_l3(msg);
3137 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3138 struct tlv_parsed tp;
3139 struct gsm_mncc modify;
3140
3141 memset(&modify, 0, sizeof(struct gsm_mncc));
3142 modify.callref = trans->callref;
3143 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3144 /* bearer capability */
3145 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3146 modify.fields |= MNCC_F_BEARER_CAP;
3147 decode_bearer_cap(&modify.bearer_cap,
3148 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3149 }
3150
3151 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3152
Harald Welte596fed42009-07-23 19:06:52 +02003153 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003154}
3155
3156static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3157{
3158 struct gsm_mncc *modify = arg;
3159 struct msgb *msg = gsm48_msgb_alloc();
3160 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3161
Harald Welte4bfdfe72009-06-10 23:11:52 +08003162 gh->msg_type = GSM48_MT_CC_MODIFY;
3163
3164 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3165
3166 /* bearer capability */
3167 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3168
3169 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3170
Harald Welte39e2ead2009-07-23 21:13:03 +02003171 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003172}
3173
3174static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3175{
3176 struct gsm48_hdr *gh = msgb_l3(msg);
3177 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3178 struct tlv_parsed tp;
3179 struct gsm_mncc modify;
3180
3181 gsm48_stop_cc_timer(trans);
3182
3183 memset(&modify, 0, sizeof(struct gsm_mncc));
3184 modify.callref = trans->callref;
3185 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3186 /* bearer capability */
3187 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3188 modify.fields |= MNCC_F_BEARER_CAP;
3189 decode_bearer_cap(&modify.bearer_cap,
3190 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3191 }
3192
3193 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3194
Harald Welte596fed42009-07-23 19:06:52 +02003195 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003196}
3197
3198static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3199{
3200 struct gsm_mncc *modify = arg;
3201 struct msgb *msg = gsm48_msgb_alloc();
3202 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3203
Harald Welte4bfdfe72009-06-10 23:11:52 +08003204 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3205
3206 /* bearer capability */
3207 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3208
3209 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3210
Harald Welte39e2ead2009-07-23 21:13:03 +02003211 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003212}
3213
3214static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3215{
3216 struct gsm48_hdr *gh = msgb_l3(msg);
3217 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3218 struct tlv_parsed tp;
3219 struct gsm_mncc modify;
3220
3221 gsm48_stop_cc_timer(trans);
3222
3223 memset(&modify, 0, sizeof(struct gsm_mncc));
3224 modify.callref = trans->callref;
3225 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3226 /* bearer capability */
3227 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3228 modify.fields |= GSM48_IE_BEARER_CAP;
3229 decode_bearer_cap(&modify.bearer_cap,
3230 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3231 }
3232 /* cause */
3233 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3234 modify.fields |= MNCC_F_CAUSE;
3235 decode_cause(&modify.cause,
3236 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3237 }
3238
3239 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3240
Harald Welte596fed42009-07-23 19:06:52 +02003241 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003242}
3243
3244static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3245{
3246 struct gsm_mncc *modify = arg;
3247 struct msgb *msg = gsm48_msgb_alloc();
3248 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3249
Harald Welte4bfdfe72009-06-10 23:11:52 +08003250 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3251
3252 /* bearer capability */
3253 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3254 /* cause */
3255 encode_cause(msg, 1, &modify->cause);
3256
3257 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3258
Harald Welte39e2ead2009-07-23 21:13:03 +02003259 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003260}
3261
3262static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3263{
3264 struct gsm_mncc *notify = arg;
3265 struct msgb *msg = gsm48_msgb_alloc();
3266 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3267
Harald Welte4bfdfe72009-06-10 23:11:52 +08003268 gh->msg_type = GSM48_MT_CC_NOTIFY;
3269
3270 /* notify */
3271 encode_notify(msg, notify->notify);
3272
Harald Welte39e2ead2009-07-23 21:13:03 +02003273 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003274}
3275
3276static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3277{
3278 struct gsm48_hdr *gh = msgb_l3(msg);
3279 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3280// struct tlv_parsed tp;
3281 struct gsm_mncc notify;
3282
3283 memset(&notify, 0, sizeof(struct gsm_mncc));
3284 notify.callref = trans->callref;
3285// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3286 if (payload_len >= 1)
3287 decode_notify(&notify.notify, gh->data);
3288
Harald Welte596fed42009-07-23 19:06:52 +02003289 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003290}
3291
3292static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3293{
3294 struct gsm_mncc *user = arg;
3295 struct msgb *msg = gsm48_msgb_alloc();
3296 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3297
Harald Welte4bfdfe72009-06-10 23:11:52 +08003298 gh->msg_type = GSM48_MT_CC_USER_INFO;
3299
3300 /* user-user */
3301 if (user->fields & MNCC_F_USERUSER)
3302 encode_useruser(msg, 1, &user->useruser);
3303 /* more data */
3304 if (user->more)
3305 encode_more(msg);
3306
Harald Welte39e2ead2009-07-23 21:13:03 +02003307 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003308}
3309
3310static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3311{
3312 struct gsm48_hdr *gh = msgb_l3(msg);
3313 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3314 struct tlv_parsed tp;
3315 struct gsm_mncc user;
3316
3317 memset(&user, 0, sizeof(struct gsm_mncc));
3318 user.callref = trans->callref;
3319 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3320 /* user-user */
3321 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3322 user.fields |= MNCC_F_USERUSER;
3323 decode_useruser(&user.useruser,
3324 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3325 }
3326 /* more data */
3327 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3328 user.more = 1;
3329
Harald Welte596fed42009-07-23 19:06:52 +02003330 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003331}
3332
3333static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3334{
3335 struct gsm_mncc *mode = arg;
Harald Welte13cac662009-07-29 12:10:35 +02003336 int rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003337
Harald Welte13cac662009-07-29 12:10:35 +02003338 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3339 if (rc < 0)
3340 return rc;
3341
3342 /* FIXME: we not only need to do this after mode modify, but
3343 * also after channel activation */
3344 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3345 mode->lchan_mode != GSM48_CMODE_SIGN)
3346 rc = rsl_ipacc_bind(trans->lchan);
3347
3348 return rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003349}
3350
3351static struct downstate {
3352 u_int32_t states;
3353 int type;
3354 int (*rout) (struct gsm_trans *trans, void *arg);
3355} downstatelist[] = {
3356 /* mobile originating call establishment */
3357 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3358 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3359 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3360 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3361 {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 */
3362 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3363 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3364 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3365 /* mobile terminating call establishment */
3366 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3367 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3368 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3369 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3370 /* signalling during call */
3371 {SBIT(GSM_CSTATE_ACTIVE),
3372 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3373 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3374 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3375 {ALL_STATES,
3376 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3377 {ALL_STATES,
3378 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3379 {ALL_STATES,
3380 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3381 {SBIT(GSM_CSTATE_ACTIVE),
3382 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3383 {SBIT(GSM_CSTATE_ACTIVE),
3384 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3385 {SBIT(GSM_CSTATE_ACTIVE),
3386 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3387 {SBIT(GSM_CSTATE_ACTIVE),
3388 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3389 {SBIT(GSM_CSTATE_ACTIVE),
3390 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3391 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3392 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3393 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3394 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3395 {SBIT(GSM_CSTATE_ACTIVE),
3396 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3397 /* clearing */
3398 {SBIT(GSM_CSTATE_INITIATED),
3399 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3400 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3401 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3402 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3403 MNCC_REL_REQ, gsm48_cc_tx_release},
3404 /* special */
3405 {ALL_STATES,
3406 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3407};
3408
3409#define DOWNSLLEN \
3410 (sizeof(downstatelist) / sizeof(struct downstate))
3411
3412
3413int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3414{
Harald Welte1a6f7982009-08-09 18:52:33 +02003415 int i, rc = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003416 struct gsm_trans *trans = NULL, *transt;
3417 struct gsm_subscriber *subscr;
Harald Welte1a6f7982009-08-09 18:52:33 +02003418 struct gsm_lchan *lchan = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003419 struct gsm_bts *bts = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003420 struct gsm_mncc *data = arg, rel;
3421
3422 /* handle special messages */
3423 switch(msg_type) {
3424 case MNCC_BRIDGE:
3425 return tch_bridge(net, arg);
3426 case MNCC_FRAME_DROP:
3427 return tch_recv(net, arg, 0);
3428 case MNCC_FRAME_RECV:
3429 return tch_recv(net, arg, 1);
3430 case GSM_TRAU_FRAME:
3431 return tch_frame(net, arg);
3432 }
3433
3434 memset(&rel, 0, sizeof(struct gsm_mncc));
3435 rel.callref = data->callref;
3436
3437 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02003438 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003439
3440 /* Callref unknown */
3441 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003442 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003443 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3444 "Received '%s' from MNCC with "
3445 "unknown callref %d\n", data->called.number,
3446 get_mncc_name(msg_type), data->callref);
3447 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003448 return mncc_release_ind(net, NULL, data->callref,
3449 GSM48_CAUSE_LOC_PRN_S_LU,
3450 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003451 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003452 if (!data->called.number[0] && !data->imsi[0]) {
3453 DEBUGP(DCC, "(bts - trx - ts - ti) "
3454 "Received '%s' from MNCC with "
3455 "no number or IMSI\n", get_mncc_name(msg_type));
3456 /* Invalid number */
3457 return mncc_release_ind(net, NULL, data->callref,
3458 GSM48_CAUSE_LOC_PRN_S_LU,
3459 GSM48_CC_CAUSE_INV_NR_FORMAT);
3460 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003461 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003462 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02003463 subscr = subscr_get_by_extension(net,
3464 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003465 else
Harald Welte9176bd42009-07-23 18:46:00 +02003466 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003467 /* If subscriber is not found */
3468 if (!subscr) {
3469 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3470 "Received '%s' from MNCC with "
3471 "unknown subscriber %s\n", data->called.number,
3472 get_mncc_name(msg_type), data->called.number);
3473 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003474 return mncc_release_ind(net, NULL, data->callref,
3475 GSM48_CAUSE_LOC_PRN_S_LU,
3476 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003477 }
3478 /* If subscriber is not "attached" */
3479 if (!subscr->lac) {
3480 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3481 "Received '%s' from MNCC with "
3482 "detached subscriber %s\n", data->called.number,
3483 get_mncc_name(msg_type), data->called.number);
3484 subscr_put(subscr);
3485 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003486 return mncc_release_ind(net, NULL, data->callref,
3487 GSM48_CAUSE_LOC_PRN_S_LU,
3488 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003489 }
3490 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003491 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3492 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003493 DEBUGP(DCC, "No memory for trans.\n");
3494 subscr_put(subscr);
3495 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003496 mncc_release_ind(net, NULL, data->callref,
3497 GSM48_CAUSE_LOC_PRN_S_LU,
3498 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003499 return -ENOMEM;
3500 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003501 /* Find lchan */
Harald Welte1a6f7982009-08-09 18:52:33 +02003502 lchan = lchan_for_subscr(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003503 /* If subscriber has no lchan */
3504 if (!lchan) {
3505 /* find transaction with this subscriber already paging */
3506 llist_for_each_entry(transt, &net->trans_list, entry) {
3507 /* Transaction of our lchan? */
3508 if (transt == trans ||
3509 transt->subscr != subscr)
3510 continue;
3511 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3512 "Received '%s' from MNCC with "
3513 "unallocated channel, paging already "
3514 "started.\n", bts->nr,
3515 data->called.number,
3516 get_mncc_name(msg_type));
3517 return 0;
3518 }
3519 /* store setup informations until paging was successfull */
Harald Weltedcaf5652009-07-23 18:56:43 +02003520 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Weltea1b28582009-08-01 19:31:47 +02003521 /* Trigger paging */
3522 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3523 setup_trig_pag_evt, subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003524 return 0;
3525 }
3526 /* Assign lchan */
3527 trans->lchan = lchan;
3528 use_lchan(lchan);
3529 }
3530 lchan = trans->lchan;
3531
3532 /* if paging did not respond yet */
3533 if (!lchan) {
3534 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3535 "Received '%s' from MNCC in paging state\n",
3536 (trans->subscr)?(trans->subscr->extension):"-",
3537 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003538 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3539 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003540 if (msg_type == MNCC_REL_REQ)
3541 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3542 else
3543 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3544 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003545 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003546 return rc;
3547 }
3548
3549 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3550 "Received '%s' from MNCC in state %d (%s)\n",
3551 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3552 trans->transaction_id,
3553 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003554 get_mncc_name(msg_type), trans->cc.state,
3555 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003556
3557 /* Find function for current state and message */
3558 for (i = 0; i < DOWNSLLEN; i++)
3559 if ((msg_type == downstatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003560 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003561 break;
3562 if (i == DOWNSLLEN) {
3563 DEBUGP(DCC, "Message unhandled at this state.\n");
3564 return 0;
3565 }
3566
3567 rc = downstatelist[i].rout(trans, arg);
3568
3569 return rc;
3570}
3571
3572
3573static struct datastate {
3574 u_int32_t states;
3575 int type;
3576 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3577} datastatelist[] = {
3578 /* mobile originating call establishment */
3579 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3580 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3581 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3582 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3583 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3584 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3585 /* mobile terminating call establishment */
3586 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3587 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3588 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3589 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3590 {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 */
3591 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3592 /* signalling during call */
3593 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3594 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3595 {SBIT(GSM_CSTATE_ACTIVE),
3596 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3597 {ALL_STATES,
3598 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3599 {ALL_STATES,
3600 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3601 {ALL_STATES,
3602 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3603 {SBIT(GSM_CSTATE_ACTIVE),
3604 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3605 {SBIT(GSM_CSTATE_ACTIVE),
3606 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3607 {SBIT(GSM_CSTATE_ACTIVE),
3608 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3609 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3610 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3611 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3612 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3613 {SBIT(GSM_CSTATE_ACTIVE),
3614 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3615 /* clearing */
3616 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3617 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3618 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3619 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3620 {ALL_STATES, /* 5.4.3.4 */
3621 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3622};
3623
3624#define DATASLLEN \
3625 (sizeof(datastatelist) / sizeof(struct datastate))
3626
Harald Welte4bc90a12008-12-27 16:32:52 +00003627static int gsm0408_rcv_cc(struct msgb *msg)
3628{
3629 struct gsm48_hdr *gh = msgb_l3(msg);
3630 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003631 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003632 struct gsm_lchan *lchan = msg->lchan;
Harald Weltedcaf5652009-07-23 18:56:43 +02003633 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003634 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003635
Harald Welte4bfdfe72009-06-10 23:11:52 +08003636 if (msg_type & 0x80) {
3637 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3638 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003639 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003640
3641 /* Find transaction */
Harald Welteb8b40732009-07-23 21:58:40 +02003642 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltedcaf5652009-07-23 18:56:43 +02003643
Harald Welte6f5aee02009-07-23 21:21:14 +02003644 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003645 "Received '%s' from MS in state %d (%s)\n",
3646 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3647 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003648 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3649 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003650
3651 /* Create transaction */
3652 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003653 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003654 "creating new trans.\n", transaction_id);
3655 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003656 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3657 transaction_id, new_callref++);
3658 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003659 DEBUGP(DCC, "No memory for trans.\n");
3660 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003661 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003662 GSM48_MT_CC_RELEASE_COMPL);
3663 return -ENOMEM;
3664 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003665 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003666 trans->lchan = lchan;
3667 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003668 }
3669
3670 /* find function for current state and message */
3671 for (i = 0; i < DATASLLEN; i++)
3672 if ((msg_type == datastatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003673 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003674 break;
3675 if (i == DATASLLEN) {
3676 DEBUGP(DCC, "Message unhandled at this state.\n");
3677 return 0;
3678 }
3679
3680 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003681
3682 return rc;
3683}
3684
Harald Welte52b1f982008-12-23 20:25:15 +00003685/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3686int gsm0408_rcvmsg(struct msgb *msg)
3687{
3688 struct gsm48_hdr *gh = msgb_l3(msg);
3689 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003690 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003691
3692 switch (pdisc) {
3693 case GSM48_PDISC_CC:
3694 rc = gsm0408_rcv_cc(msg);
3695 break;
3696 case GSM48_PDISC_MM:
3697 rc = gsm0408_rcv_mm(msg);
3698 break;
3699 case GSM48_PDISC_RR:
3700 rc = gsm0408_rcv_rr(msg);
3701 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003702 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003703 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003704 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003705 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003706 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003707 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3708 pdisc);
3709 break;
3710 default:
3711 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3712 pdisc);
3713 break;
3714 }
3715
3716 return rc;
3717}
Harald Welte8470bf22008-12-25 23:28:35 +00003718
Harald Welte8470bf22008-12-25 23:28:35 +00003719/* Section 9.1.8 / Table 9.9 */
3720struct chreq {
3721 u_int8_t val;
3722 u_int8_t mask;
3723 enum chreq_type type;
3724};
3725
3726/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3727static const struct chreq chreq_type_neci1[] = {
3728 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3729 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3730 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3731 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3732 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3733 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3734 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3735 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3736 { 0x10, 0xf0, CHREQ_T_SDCCH },
3737 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3738 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3739 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3740};
3741
3742/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3743static const struct chreq chreq_type_neci0[] = {
3744 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3745 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3746 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3747 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3748 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3749 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3750 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3751 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3752};
3753
3754static const enum gsm_chan_t ctype_by_chreq[] = {
3755 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3756 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3757 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3758 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3759 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3760 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3761 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3762 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3763 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3764 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3765 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3766 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3767};
3768
Harald Weltee14a57c2008-12-29 04:08:28 +00003769static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3770 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3771 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3772 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3773 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3774 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3775 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3776 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3777 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3778 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3779 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3780 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3781 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3782};
3783
Harald Welte8470bf22008-12-25 23:28:35 +00003784enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3785{
3786 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003787 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte8470bf22008-12-25 23:28:35 +00003788
Harald Weltee58ca7c2009-08-10 02:14:46 +02003789 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3790 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte8470bf22008-12-25 23:28:35 +00003791 if ((ra & chr->mask) == chr->val)
3792 return ctype_by_chreq[chr->type];
3793 }
3794 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3795 return GSM_LCHAN_SDCCH;
3796}
Harald Weltee14a57c2008-12-29 04:08:28 +00003797
3798enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3799{
3800 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003801 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Weltee14a57c2008-12-29 04:08:28 +00003802
Harald Weltee58ca7c2009-08-10 02:14:46 +02003803 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3804 const struct chreq *chr = &chreq_type_neci0[i];
Harald Weltee14a57c2008-12-29 04:08:28 +00003805 if ((ra & chr->mask) == chr->val)
3806 return reason_by_chreq[chr->type];
3807 }
3808 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3809 return GSM_CHREQ_REASON_OTHER;
3810}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003811
3812/* dequeue messages to layer 4 */
3813int bsc_upqueue(struct gsm_network *net)
3814{
3815 struct gsm_mncc *mncc;
3816 struct msgb *msg;
3817 int work = 0;
3818
3819 if (net)
3820 while ((msg = msgb_dequeue(&net->upqueue))) {
3821 mncc = (struct gsm_mncc *)msg->data;
3822 if (net->mncc_recv)
3823 net->mncc_recv(net, mncc->msg_type, mncc);
3824 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003825 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003826 }
3827
3828 return work;
3829}
Harald Weltedcaf5652009-07-23 18:56:43 +02003830
Harald Welte805f6442009-07-28 18:25:29 +02003831/*
3832 * This will be ran by the linker when loading the DSO. We use it to
3833 * do system initialization, e.g. registration of signal handlers.
3834 */
3835static __attribute__((constructor)) void on_dso_load_0408(void)
3836{
3837 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3838 "loc_updating_oper");
3839 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3840 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3841}