blob: 65940a0f55ff4ee2bd290b0c44f473cb5d9362df [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 Freythere97f7fb2008-12-31 18:52:11 +0000307static int reject_cause = 0;
308void gsm0408_set_reject_cause(int cause)
309{
310 reject_cause = cause;
311}
312
Harald Welte4bfdfe72009-06-10 23:11:52 +0800313static u_int32_t new_callref = 0x80000001;
314
Holger Freyther73487a22008-12-31 18:53:57 +0000315static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
316 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000317{
318 if (!subscriber)
319 return 0;
320
Holger Freyther73487a22008-12-31 18:53:57 +0000321 /*
322 * Do not send accept yet as more information should arrive. Some
323 * phones will not send us the information and we will have to check
324 * what we want to do with that.
325 */
326 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
327 return 0;
328
Jan Luebbe06513f22009-08-12 12:48:00 +0200329 switch (subscriber->net->auth_policy) {
330 case GSM_AUTH_POLICY_CLOSED:
331 return subscriber->authorized;
332 case GSM_AUTH_POLICY_ACCEPT_ALL:
Holger Freyther89824fc2008-12-30 16:18:18 +0000333 return 1;
Jan Luebbe06513f22009-08-12 12:48:00 +0200334 case GSM_AUTH_POLICY_TOKEN:
335 default:
336 return 0;
337 }
Holger Freyther89824fc2008-12-30 16:18:18 +0000338}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000339
Holger Freyther73487a22008-12-31 18:53:57 +0000340static void release_loc_updating_req(struct gsm_lchan *lchan)
341{
Harald Welte179f0642008-12-31 23:59:18 +0000342 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000343 return;
344
Harald Welteff117a82009-05-23 05:22:08 +0000345 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200346 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000347 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000348 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000349}
350
351static void allocate_loc_updating_req(struct gsm_lchan *lchan)
352{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000353 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000354 release_loc_updating_req(lchan);
355
Harald Welte470ec292009-06-26 20:25:23 +0200356 lchan->loc_operation = talloc_zero(tall_locop_ctx,
357 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000358}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000359
Holger Freytherd51524f2009-06-09 08:27:07 +0000360static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
361{
362 u_int32_t tmsi;
363
364 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welteee5ad162009-08-09 19:07:00 +0200365 int rc;
366
Holger Freytherd51524f2009-06-09 08:27:07 +0000367 db_subscriber_alloc_tmsi(lchan->subscr);
Holger Freytherd51524f2009-06-09 08:27:07 +0000368 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
369 release_loc_updating_req(lchan);
Harald Welteee5ad162009-08-09 19:07:00 +0200370 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
371 /* call subscr_update after putting the loc_upd_acc
372 * in the transmit queue, since S_SUBSCR_ATTACHED might
373 * trigger further action like SMS delivery */
374 subscr_update(lchan->subscr, msg->trx->bts,
375 GSM_SUBSCRIBER_UPDATE_ATTACHED);
376 return rc;
Holger Freytherd51524f2009-06-09 08:27:07 +0000377 }
378
379 return 0;
380}
381
Holger Freyther7c19f742009-06-06 13:54:35 +0000382static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
383 void *handler_data, void *signal_data)
384{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800385 struct gsm_trans *trans, *temp;
386
Holger Freyther7c19f742009-06-06 13:54:35 +0000387 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
388 return 0;
389
390 /*
391 * Cancel any outstanding location updating request
392 * operation taking place on the lchan.
393 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200394 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200395 if (!lchan)
396 return 0;
397
Holger Freyther7c19f742009-06-06 13:54:35 +0000398 release_loc_updating_req(lchan);
399
Harald Welte4bfdfe72009-06-10 23:11:52 +0800400 /* Free all transactions that are associated with the released lchan */
Harald Weltedcaf5652009-07-23 18:56:43 +0200401 /* FIXME: this is not neccessarily the right thing to do, we should
402 * only set trans->lchan to NULL and wait for another lchan to be
403 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800404 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
405 if (trans->lchan == lchan)
Harald Weltedcaf5652009-07-23 18:56:43 +0200406 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800407 }
408
Holger Freyther7c19f742009-06-06 13:54:35 +0000409 return 0;
410}
411
Harald Welte52b1f982008-12-23 20:25:15 +0000412static void to_bcd(u_int8_t *bcd, u_int16_t val)
413{
Harald Welte4b634542008-12-27 01:55:51 +0000414 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000415 val = val / 10;
416 bcd[1] = val % 10;
417 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000418 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000419 val = val / 10;
420}
421
Holger Freyther17746612008-12-28 16:32:44 +0000422void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000423 u_int16_t mnc, u_int16_t lac)
424{
425 u_int8_t bcd[3];
426
427 to_bcd(bcd, mcc);
428 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
429 lai48->digits[1] = bcd[2];
430
431 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000432 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
433#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000434 lai48->digits[1] |= bcd[2] << 4;
435 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000436#else
437 lai48->digits[1] |= 0xf << 4;
438 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
439#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000440
Harald Welte4b634542008-12-27 01:55:51 +0000441 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000442}
443
Harald Welte255539c2008-12-28 02:26:27 +0000444#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000445#define MID_TMSI_LEN (TMSI_LEN + 2)
446
Harald Welte255539c2008-12-28 02:26:27 +0000447int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000448{
Harald Welte65e74cc2008-12-29 01:55:35 +0000449 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000450
Harald Welte4b634542008-12-27 01:55:51 +0000451 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000452 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000453 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000454 *tptr = htonl(tmsi);
455
456 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000457}
458
Harald Welte09e38af2009-02-16 22:52:23 +0000459static const char bcd_num_digits[] = {
460 '0', '1', '2', '3', '4', '5', '6', '7',
461 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
462};
463
Harald Welte0c389302009-06-10 12:08:54 +0800464/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
465int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
466 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000467{
468 u_int8_t in_len = bcd_lv[0];
469 int i;
470
Harald Welte0c389302009-06-10 12:08:54 +0800471 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000472 /* lower nibble */
473 output_len--;
474 if (output_len <= 1)
475 break;
476 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
477
478 /* higher nibble */
479 output_len--;
480 if (output_len <= 1)
481 break;
482 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
483 }
484 if (output_len >= 1)
485 *output++ = '\0';
486
Harald Welte0c389302009-06-10 12:08:54 +0800487 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000488}
489
490/* convert a single ASCII character to call-control BCD */
491static int asc_to_bcd(const char asc)
492{
493 int i;
494
495 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
496 if (bcd_num_digits[i] == asc)
497 return i;
498 }
499 return -EINVAL;
500}
501
Harald Welte0c389302009-06-10 12:08:54 +0800502/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000503int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800504 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000505{
506 int in_len = strlen(input);
507 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800508 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000509
510 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800511 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000512 if (in_len % 2)
513 bcd_lv[0]++;
514
Harald Welte0c389302009-06-10 12:08:54 +0800515 if (bcd_lv[0] > max_len)
516 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000517
518 for (i = 0; i < in_len; i++) {
519 int rc = asc_to_bcd(input[i]);
520 if (rc < 0)
521 return rc;
522 if (i % 2 == 0)
523 *bcd_cur = rc;
524 else
525 *bcd_cur++ |= (rc << 4);
526 }
527 /* append padding nibble in case of odd length */
528 if (i % 2)
529 *bcd_cur++ |= 0xf0;
530
531 /* return how many bytes we used */
532 return (bcd_cur - bcd_lv);
533}
534
Harald Welte0c389302009-06-10 12:08:54 +0800535/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800536static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800537 const u_int8_t *lv)
538{
539 u_int8_t in_len = lv[0];
540 int i, s;
541
542 if (in_len < 1)
543 return -EINVAL;
544
Harald Welte4bfdfe72009-06-10 23:11:52 +0800545 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800546
547 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800548 bcap->transfer = lv[1] & 0x07;
549 bcap->mode = (lv[1] & 0x08) >> 3;
550 bcap->coding = (lv[1] & 0x10) >> 4;
551 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800552
553 i = 1;
554 s = 0;
555 while(!(lv[i] & 0x80)) {
556 i++; /* octet 3a etc */
557 if (in_len < i)
558 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800559 bcap->speech_ver[s++] = lv[i] & 0x0f;
560 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800561 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800562 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800563 if (s == 7) /* maximum speech versions + end of list */
564 return 0;
565 }
566
567 return 0;
568}
569
570/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800571static int encode_bearer_cap(struct msgb *msg, int lv_only,
572 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800573{
574 u_int8_t lv[32 + 1];
575 int i, s;
576
Harald Welte4bfdfe72009-06-10 23:11:52 +0800577 lv[1] = bcap->transfer;
578 lv[1] |= bcap->mode << 3;
579 lv[1] |= bcap->coding << 4;
580 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800581
582 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800583 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800584 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800585 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800586 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800588 }
589 lv[i] |= 0x80; /* last IE of octet 3 etc */
590
591 lv[0] = i;
592 if (lv_only)
593 msgb_lv_put(msg, lv[0], lv+1);
594 else
595 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
596
597 return 0;
598}
599
600/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800601static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800602{
603 u_int8_t in_len = lv[0];
604
605 if (in_len < 1)
606 return -EINVAL;
607
608 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800609 ccap->dtmf = lv[1] & 0x01;
610 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800611
612 return 0;
613}
614
615/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800616static int decode_called(struct gsm_mncc_number *called,
617 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800618{
619 u_int8_t in_len = lv[0];
620
621 if (in_len < 1)
622 return -EINVAL;
623
624 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800625 called->plan = lv[1] & 0x0f;
626 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800627
628 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800629 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800630
631 return 0;
632}
633
634/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800635static int encode_called(struct msgb *msg,
636 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800637{
638 u_int8_t lv[18];
639 int ret;
640
641 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800642 lv[1] = called->plan;
643 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800644
645 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800646 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800647 if (ret < 0)
648 return ret;
649
650 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
651
652 return 0;
653}
654
655/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800656static int encode_callerid(struct msgb *msg, int ie,
657 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800658{
659 u_int8_t lv[13];
660 int h_len = 1;
661 int ret;
662
663 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800664 lv[1] = callerid->plan;
665 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800666
Harald Welte4bfdfe72009-06-10 23:11:52 +0800667 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800668 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800669 lv[2] = callerid->screen;
670 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800671 lv[2] |= 0x80;
672 h_len++;
673 } else
674 lv[1] |= 0x80;
675
676 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800677 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800678 if (ret < 0)
679 return ret;
680
681 msgb_tlv_put(msg, ie, lv[0], lv+1);
682
683 return 0;
684}
685
686/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800687static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800688 const u_int8_t *lv)
689{
690 u_int8_t in_len = lv[0];
691 int i;
692
693 if (in_len < 2)
694 return -EINVAL;
695
Harald Welte4bfdfe72009-06-10 23:11:52 +0800696 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800697
698 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800699 cause->location = lv[1] & 0x0f;
700 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800701
702 i = 1;
703 if (!(lv[i] & 0x80)) {
704 i++; /* octet 3a */
705 if (in_len < i+1)
706 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800707 cause->rec = 1;
708 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800709
710 }
711 i++;
712
713 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800714 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800715 i++;
716
717 if (in_len < i) /* no diag */
718 return 0;
719
720 if (in_len - (i-1) > 32) /* maximum 32 octets */
721 return 0;
722
723 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800724 memcpy(cause->diag, lv + i, in_len - (i-1));
725 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800726
727 return 0;
728}
729
730/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800731static int encode_cause(struct msgb *msg, int lv_only,
732 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800733{
734 u_int8_t lv[32+4];
735 int i;
736
Harald Welte4bfdfe72009-06-10 23:11:52 +0800737 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800738 return -EINVAL;
739
740 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800741 lv[1] = cause->location;
742 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800743
744 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800746 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800747 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800748 }
749 lv[i] |= 0x80; /* end of octet 3 */
750
751 /* octet 4 */
752 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800753 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800754
755 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800756 if (cause->diag_len) {
757 memcpy(lv + i, cause->diag, cause->diag_len);
758 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800759 }
760
761 lv[0] = i;
762 if (lv_only)
763 msgb_lv_put(msg, lv[0], lv+1);
764 else
765 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
766
767 return 0;
768}
769
770/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800771static int encode_calling(struct msgb *msg,
772 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800773{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800774 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800775}
776
777/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800778static int encode_connected(struct msgb *msg,
779 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800780{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800781 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800782}
783
784/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800785static int encode_redirecting(struct msgb *msg,
786 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800787{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800788 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800789}
790
791/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800792static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800793 const u_int8_t *lv)
794{
795 u_int8_t in_len = lv[0];
796
797 if (in_len < 1)
798 return -EINVAL;
799
Harald Welte4bfdfe72009-06-10 23:11:52 +0800800 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800801 return -EINVAL;
802
Harald Welte4bfdfe72009-06-10 23:11:52 +0800803 memcpy(facility->info, lv+1, in_len);
804 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800805
806 return 0;
807}
808
809/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800810static int encode_facility(struct msgb *msg, int lv_only,
811 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800812{
813 u_int8_t lv[GSM_MAX_FACILITY + 1];
814
Harald Welte4bfdfe72009-06-10 23:11:52 +0800815 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800816 return -EINVAL;
817
Harald Welte4bfdfe72009-06-10 23:11:52 +0800818 memcpy(lv+1, facility->info, facility->len);
819 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800820 if (lv_only)
821 msgb_lv_put(msg, lv[0], lv+1);
822 else
823 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
824
825 return 0;
826}
827
828/* decode 'notify' */
829static int decode_notify(int *notify, const u_int8_t *v)
830{
831 *notify = v[0] & 0x7f;
832
833 return 0;
834}
835
836/* encode 'notify' */
837static int encode_notify(struct msgb *msg, int notify)
838{
839 msgb_v_put(msg, notify | 0x80);
840
841 return 0;
842}
843
844/* encode 'signal' */
845static int encode_signal(struct msgb *msg, int signal)
846{
847 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
848
849 return 0;
850}
851
852/* decode 'keypad' */
853static int decode_keypad(int *keypad, const u_int8_t *lv)
854{
855 u_int8_t in_len = lv[0];
856
857 if (in_len < 1)
858 return -EINVAL;
859
860 *keypad = lv[1] & 0x7f;
861
862 return 0;
863}
864
865/* encode 'keypad' */
866static int encode_keypad(struct msgb *msg, int keypad)
867{
868 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
869
870 return 0;
871}
872
873/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800874static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800875 const u_int8_t *lv)
876{
877 u_int8_t in_len = lv[0];
878
879 if (in_len < 2)
880 return -EINVAL;
881
Harald Welte4bfdfe72009-06-10 23:11:52 +0800882 progress->coding = (lv[1] & 0x60) >> 5;
883 progress->location = lv[1] & 0x0f;
884 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800885
886 return 0;
887}
888
889/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800890static int encode_progress(struct msgb *msg, int lv_only,
891 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800892{
893 u_int8_t lv[3];
894
895 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800896 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
897 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800898 if (lv_only)
899 msgb_lv_put(msg, lv[0], lv+1);
900 else
901 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
902
903 return 0;
904}
905
906/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800907static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800908 const u_int8_t *lv)
909{
910 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800911 char *info = uu->info;
912 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800913 int i;
914
915 if (in_len < 1)
916 return -EINVAL;
917
Harald Welte4bfdfe72009-06-10 23:11:52 +0800918 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800919
920 for (i = 2; i <= in_len; i++) {
921 info_len--;
922 if (info_len <= 1)
923 break;
924 *info++ = lv[i];
925 }
926 if (info_len >= 1)
927 *info++ = '\0';
928
929 return 0;
930}
931
932/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800933static int encode_useruser(struct msgb *msg, int lv_only,
934 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800935{
936 u_int8_t lv[GSM_MAX_USERUSER + 2];
937
Harald Welte4bfdfe72009-06-10 23:11:52 +0800938 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800939 return -EINVAL;
940
Harald Welte4bfdfe72009-06-10 23:11:52 +0800941 lv[0] = 1 + strlen(uu->info);
942 lv[1] = uu->proto;
943 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800944 if (lv_only)
945 msgb_lv_put(msg, lv[0], lv+1);
946 else
947 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
948
949 return 0;
950}
951
952/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800953static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800954 const u_int8_t *lv)
955{
956 u_int8_t in_len = lv[0];
957
Harald Welte4bfdfe72009-06-10 23:11:52 +0800958 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800959 return -EINVAL;
960
Harald Welte4bfdfe72009-06-10 23:11:52 +0800961 memcpy(ssv->info, lv + 1, in_len);
962 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800963
964 return 0;
965}
966
967/* encode 'more data' */
968static int encode_more(struct msgb *msg)
969{
970 u_int8_t *ie;
971
972 ie = msgb_put(msg, 1);
973 ie[0] = GSM48_IE_MORE_DATA;
974
975 return 0;
976}
977
Holger Freyther819dd202009-01-04 03:52:50 +0000978struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000979{
Harald Welte966636f2009-06-26 19:39:35 +0200980 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
981 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000982}
983
Harald Welte39e2ead2009-07-23 21:13:03 +0200984int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000985{
Harald Welte39e2ead2009-07-23 21:13:03 +0200986 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
987
988 /* if we get passed a transaction reference, do some common
989 * work that the caller no longer has to do */
990 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200991 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200992 msg->lchan = trans->lchan;
993 }
994
Harald Welte65e74cc2008-12-29 01:55:35 +0000995 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000996 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000997
Harald Welte4bfdfe72009-06-10 23:11:52 +0800998 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
999 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1000 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1001 msg->trx->nr, msg->lchan->ts->nr,
1002 gh->proto_discr & 0xf0,
1003 cc_msg_names[gh->msg_type & 0x3f]);
1004 else
1005 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1006 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1007 msg->trx->nr, msg->lchan->ts->nr,
1008 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001009 }
1010
Harald Welte4b634542008-12-27 01:55:51 +00001011 msg->l3h = msg->data;
1012
Harald Welte8470bf22008-12-25 23:28:35 +00001013 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001014}
1015
Holger Freyther429e7762008-12-30 13:28:30 +00001016/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001017int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001018{
Harald Welte8470bf22008-12-25 23:28:35 +00001019 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001020 struct gsm48_hdr *gh;
1021
Harald Welte8470bf22008-12-25 23:28:35 +00001022 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001023
1024 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1025 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001026 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001027 gh->data[0] = cause;
1028
Harald Weltedb253af2008-12-30 17:56:55 +00001029 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1030
Harald Welte39e2ead2009-07-23 21:13:03 +02001031 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001032}
1033
1034/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001035int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001036{
Harald Welte8470bf22008-12-25 23:28:35 +00001037 struct gsm_bts *bts = lchan->ts->trx->bts;
1038 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001039 struct gsm48_hdr *gh;
1040 struct gsm48_loc_area_id *lai;
1041 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001042 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001043
Harald Welte8470bf22008-12-25 23:28:35 +00001044 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001045
1046 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1047 gh->proto_discr = GSM48_PDISC_MM;
1048 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1049
1050 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001051 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001052 bts->network->network_code, bts->location_area_code);
1053
1054 mid = msgb_put(msg, MID_TMSI_LEN);
1055 generate_mid_from_tmsi(mid, tmsi);
1056
1057 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1058
Harald Welte39e2ead2009-07-23 21:13:03 +02001059 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001060
Harald Welteee5ad162009-08-09 19:07:00 +02001061 /* send MM INFO with network name */
Harald Weltedb253af2008-12-30 17:56:55 +00001062 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001063
Holger Freyther07cc8d82008-12-29 06:23:46 +00001064 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001065}
1066
Harald Weltefc977a82008-12-27 10:19:37 +00001067static char bcd2char(u_int8_t bcd)
1068{
1069 if (bcd < 0xa)
1070 return '0' + bcd;
1071 else
1072 return 'A' + (bcd - 0xa);
1073}
1074
Harald Weltebf5e8df2009-02-03 12:59:45 +00001075/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001076static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1077{
1078 int i;
1079 u_int8_t mi_type;
1080 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001081 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001082
1083 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1084
1085 switch (mi_type) {
1086 case GSM_MI_TYPE_NONE:
1087 break;
1088 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001089 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1090 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1091 memcpy(&tmsi, &mi[1], 4);
1092 tmsi = ntohl(tmsi);
1093 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001094 }
1095 break;
1096 case GSM_MI_TYPE_IMSI:
1097 case GSM_MI_TYPE_IMEI:
1098 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001099 *str_cur++ = bcd2char(mi[0] >> 4);
1100
1101 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001102 if (str_cur + 2 >= string + str_len)
1103 return str_cur - string;
1104 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001105 /* skip last nibble in last input byte when GSM_EVEN */
1106 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1107 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001108 }
1109 break;
1110 default:
1111 break;
1112 }
Harald Weltefc977a82008-12-27 10:19:37 +00001113 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001114
Harald Weltefc977a82008-12-27 10:19:37 +00001115 return str_cur - string;
1116}
1117
Harald Weltebf5e8df2009-02-03 12:59:45 +00001118/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001119static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1120{
1121 struct msgb *msg = gsm48_msgb_alloc();
1122 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001123
Harald Welte231ad4f2008-12-27 11:15:38 +00001124 msg->lchan = lchan;
1125
1126 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1127 gh->proto_discr = GSM48_PDISC_MM;
1128 gh->msg_type = GSM48_MT_MM_ID_REQ;
1129 gh->data[0] = id_type;
1130
Harald Welte39e2ead2009-07-23 21:13:03 +02001131 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001132}
1133
1134#define MI_SIZE 32
1135
Harald Weltebf5e8df2009-02-03 12:59:45 +00001136/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001137static int mm_rx_id_resp(struct msgb *msg)
1138{
1139 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001140 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001141 struct gsm_bts *bts = lchan->ts->trx->bts;
1142 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001143 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1144 char mi_string[MI_SIZE];
1145
1146 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001147 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001148 mi_type, mi_string);
1149
Harald Welte75a983f2008-12-27 21:34:06 +00001150 switch (mi_type) {
1151 case GSM_MI_TYPE_IMSI:
Jan Luebbe370b41d2009-08-12 10:19:34 +02001152 /* look up subscriber based on IMSI, create if not found */
1153 if (!lchan->subscr) {
1154 lchan->subscr = subscr_get_by_imsi(net, mi_string);
1155 }
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001156 if (!lchan->subscr) {
Harald Welte9176bd42009-07-23 18:46:00 +02001157 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001158 if (lchan->subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1159 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &lchan->subscr);
1160 }
1161 }
Holger Freyther73487a22008-12-31 18:53:57 +00001162 if (lchan->loc_operation)
1163 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001164 break;
1165 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001166 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001167 /* update subscribe <-> IMEI mapping */
1168 if (lchan->subscr)
1169 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001170 if (lchan->loc_operation)
1171 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001172 break;
1173 }
Holger Freyther73487a22008-12-31 18:53:57 +00001174
1175 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001176 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001177}
1178
Harald Welte255539c2008-12-28 02:26:27 +00001179
1180static void loc_upd_rej_cb(void *data)
1181{
1182 struct gsm_lchan *lchan = data;
1183
Holger Freyther73487a22008-12-31 18:53:57 +00001184 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001185 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001186 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001187}
1188
Holger Freytherb7193e42008-12-29 17:44:08 +00001189static void schedule_reject(struct gsm_lchan *lchan)
1190{
Holger Freyther73487a22008-12-31 18:53:57 +00001191 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1192 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001193 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001194}
1195
Harald Welte2a139372009-02-22 21:14:55 +00001196static const char *lupd_name(u_int8_t type)
1197{
1198 switch (type) {
1199 case GSM48_LUPD_NORMAL:
1200 return "NORMAL";
1201 case GSM48_LUPD_PERIODIC:
1202 return "PEROIDOC";
1203 case GSM48_LUPD_IMSI_ATT:
1204 return "IMSI ATTACH";
1205 default:
1206 return "UNKNOWN";
1207 }
1208}
1209
Harald Welte231ad4f2008-12-27 11:15:38 +00001210#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001211/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001212static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001213{
Harald Welte8470bf22008-12-25 23:28:35 +00001214 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001215 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001216 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001217 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001218 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001219 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001220 char mi_string[MI_SIZE];
1221 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001222
Harald Welte8470bf22008-12-25 23:28:35 +00001223 lu = (struct gsm48_loc_upd_req *) gh->data;
1224
1225 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001226
Harald Weltefc977a82008-12-27 10:19:37 +00001227 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1228
Harald Weltea0368542009-06-27 02:58:43 +02001229 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001230 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001231
Holger Freythereaf04692009-06-06 13:54:44 +00001232 /*
1233 * Pseudo Spoof detection: Just drop a second/concurrent
1234 * location updating request.
1235 */
1236 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001237 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001238 lchan->loc_operation);
1239 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1240 return 0;
1241 }
1242
Holger Freyther73487a22008-12-31 18:53:57 +00001243 allocate_loc_updating_req(lchan);
1244
Harald Welte52b1f982008-12-23 20:25:15 +00001245 switch (mi_type) {
1246 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001247 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001248 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001249 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001250 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001251
Jan Luebbe370b41d2009-08-12 10:19:34 +02001252 /* look up subscriber based on IMSI, create if not found */
1253 subscr = subscr_get_by_imsi(bts->network, mi_string);
1254 if (!subscr) {
1255 subscr = db_create_subscriber(bts->network, mi_string);
1256 }
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001257 if (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
1258 dispatch_signal(SS_SUBSCR, S_SUBSCR_FIRST_CONTACT, &subscr);
1259 }
Harald Welte4b634542008-12-27 01:55:51 +00001260 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001261 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001262 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001263 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001264 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001265 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001266
Harald Welte52b1f982008-12-23 20:25:15 +00001267 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte9176bd42009-07-23 18:46:00 +02001268 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001269 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001270 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001271 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001272 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001273 }
1274 break;
1275 case GSM_MI_TYPE_IMEI:
1276 case GSM_MI_TYPE_IMEISV:
1277 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001278 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001279 break;
1280 default:
Harald Weltea0368542009-06-27 02:58:43 +02001281 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001282 break;
1283 }
1284
Harald Welte24516ea2009-07-04 10:18:00 +02001285 /* schedule the reject timer */
1286 schedule_reject(lchan);
1287
Harald Welte4bfdfe72009-06-10 23:11:52 +08001288 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001289 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001290 /* FIXME: request id? close channel? */
1291 return -EINVAL;
1292 }
1293
Harald Welte255539c2008-12-28 02:26:27 +00001294 lchan->subscr = subscr;
1295
Harald Welte24516ea2009-07-04 10:18:00 +02001296 /* check if we can let the subscriber into our network immediately
1297 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001298 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001299}
1300
Harald Welte13cac662009-07-29 12:10:35 +02001301/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte7584aea2009-02-11 11:44:12 +00001302int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1303{
1304 struct msgb *msg = gsm48_msgb_alloc();
1305 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1306 struct gsm48_chan_mode_modify *cmm =
1307 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001308 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001309
Harald Welte4a543e82009-02-28 13:17:55 +00001310 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001311
Harald Welte45b407a2009-05-23 15:51:12 +00001312 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001313 msg->lchan = lchan;
1314 gh->proto_discr = GSM48_PDISC_RR;
1315 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1316
1317 /* fill the channel information element, this code
1318 * should probably be shared with rsl_rx_chan_rqd() */
1319 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001320 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001321 cmm->chan_desc.h0.h = 0;
1322 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1323 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1324 cmm->mode = mode;
1325
Harald Welte39e2ead2009-07-23 21:13:03 +02001326 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001327}
1328
Harald Welte4bfdfe72009-06-10 23:11:52 +08001329#if 0
1330static u_int8_t to_bcd8(u_int8_t val)
1331{
1332 return ((val / 10) << 4) | (val % 10);
1333}
1334#endif
1335
Harald Weltedb253af2008-12-30 17:56:55 +00001336/* Section 9.2.15a */
1337int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1338{
1339 struct msgb *msg = gsm48_msgb_alloc();
1340 struct gsm48_hdr *gh;
1341 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001342 u_int8_t *ptr8;
1343 u_int16_t *ptr16;
1344 int name_len;
Harald Weltedb253af2008-12-30 17:56:55 +00001345 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001346#if 0
1347 time_t cur_t;
1348 struct tm* cur_time;
1349 int tz15min;
1350#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001351
1352 msg->lchan = lchan;
1353
1354 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1355 gh->proto_discr = GSM48_PDISC_MM;
1356 gh->msg_type = GSM48_MT_MM_INFO;
1357
1358 if (net->name_long) {
1359 name_len = strlen(net->name_long);
1360 /* 10.5.3.5a */
1361 ptr8 = msgb_put(msg, 3);
1362 ptr8[0] = GSM48_IE_NAME_LONG;
1363 ptr8[1] = name_len*2 +1;
1364 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1365
1366 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1367 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001368 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001369
1370 /* FIXME: Use Cell Broadcast, not UCS-2, since
1371 * UCS-2 is only supported by later revisions of the spec */
1372 }
1373
1374 if (net->name_short) {
1375 name_len = strlen(net->name_short);
1376 /* 10.5.3.5a */
1377 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001378 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001379 ptr8[1] = name_len*2 + 1;
1380 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1381
Harald Weltee872cb12009-01-01 00:33:37 +00001382 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001383 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001384 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001385 }
1386
1387#if 0
1388 /* Section 10.5.3.9 */
1389 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001390 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001391 ptr8 = msgb_put(msg, 8);
1392 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1393 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1394 ptr8[2] = to_bcd8(cur_time->tm_mon);
1395 ptr8[3] = to_bcd8(cur_time->tm_mday);
1396 ptr8[4] = to_bcd8(cur_time->tm_hour);
1397 ptr8[5] = to_bcd8(cur_time->tm_min);
1398 ptr8[6] = to_bcd8(cur_time->tm_sec);
1399 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1400 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001401 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001402 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001403 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001404#endif
1405
Harald Welte39e2ead2009-07-23 21:13:03 +02001406 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001407}
1408
Harald Welte7984d5c2009-08-12 22:56:50 +02001409/* Section 9.2.2 */
1410int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
1411{
1412 struct msgb *msg = gsm48_msgb_alloc();
1413 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1414 u_int8_t *r;
1415
1416 DEBUGP(DMM, "-> AUTH REQ\n");
1417
1418 msg->lchan = lchan;
1419 gh->proto_discr = GSM48_PDISC_MM;
1420 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
1421
1422 /* 16 bytes RAND parameters */
1423 r = msgb_put(msg, 16);
1424 if (rand)
1425 memcpy(r, rand, 16);
1426
1427 return gsm48_sendmsg(msg, NULL);
1428}
1429
1430/* Section 9.2.1 */
1431int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
1432{
1433 DEBUGP(DMM, "-> AUTH REJECT\n");
1434 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
1435}
1436
Harald Welte4b634542008-12-27 01:55:51 +00001437static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1438{
Harald Welte4b634542008-12-27 01:55:51 +00001439 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001440 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001441}
Harald Welteba4cf162009-01-10 01:49:35 +00001442
1443/* 9.2.6 CM service reject */
1444static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1445 enum gsm48_reject_value value)
1446{
1447 struct msgb *msg = gsm48_msgb_alloc();
1448 struct gsm48_hdr *gh;
1449
1450 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1451
1452 msg->lchan = lchan;
1453 use_lchan(lchan);
1454
1455 gh->proto_discr = GSM48_PDISC_MM;
1456 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1457 gh->data[0] = value;
1458 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1459
Harald Welte39e2ead2009-07-23 21:13:03 +02001460 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001461}
1462
Harald Welte3ac7f102009-08-10 10:12:45 +02001463static int send_siemens_mrpci(struct gsm_lchan *lchan,
1464 u_int8_t *classmark2_lv)
1465{
1466 struct rsl_mrpci mrpci;
1467
1468 if (classmark2_lv[0] < 2)
1469 return -EINVAL;
1470
1471 mrpci.power_class = classmark2_lv[1] & 0x7;
1472 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1473 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1474 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1475
1476 return rsl_siemens_mrpci(lchan, &mrpci);
1477}
Harald Welte4ed0e922009-01-10 03:17:30 +00001478
1479/*
1480 * Handle CM Service Requests
1481 * a) Verify that the packet is long enough to contain the information
1482 * we require otherwsie reject with INCORRECT_MESSAGE
1483 * b) Try to parse the TMSI. If we do not have one reject
1484 * c) Check that we know the subscriber with the TMSI otherwise reject
1485 * with a HLR cause
1486 * d) Set the subscriber on the gsm_lchan and accept
1487 */
Harald Welte4b634542008-12-27 01:55:51 +00001488static int gsm48_rx_mm_serv_req(struct msgb *msg)
1489{
Harald Welteba4cf162009-01-10 01:49:35 +00001490 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001491 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001492
Harald Welte9176bd42009-07-23 18:46:00 +02001493 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001494 struct gsm_subscriber *subscr;
1495 struct gsm48_hdr *gh = msgb_l3(msg);
1496 struct gsm48_service_request *req =
1497 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001498 /* unfortunately in Phase1 the classmar2 length is variable */
1499 u_int8_t classmark2_len = gh->data[1];
1500 u_int8_t *classmark2 = gh->data+2;
1501 u_int8_t mi_len = *(classmark2 + classmark2_len);
1502 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001503
Harald Weltec9e02182009-05-01 19:07:53 +00001504 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001505 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001506 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001507 return gsm48_tx_mm_serv_rej(msg->lchan,
1508 GSM48_REJECT_INCORRECT_MESSAGE);
1509 }
1510
1511 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001512 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001513 return gsm48_tx_mm_serv_rej(msg->lchan,
1514 GSM48_REJECT_INCORRECT_MESSAGE);
1515 }
1516
Harald Weltec9e02182009-05-01 19:07:53 +00001517 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001518 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001519 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001520 return gsm48_tx_mm_serv_rej(msg->lchan,
1521 GSM48_REJECT_INCORRECT_MESSAGE);
1522 }
1523
Harald Weltec9e02182009-05-01 19:07:53 +00001524 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001525 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001526 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001527
Harald Welte3ac7f102009-08-10 10:12:45 +02001528 if (is_siemens_bts(bts))
1529 send_siemens_mrpci(msg->lchan, classmark2-1);
1530
Harald Welte9176bd42009-07-23 18:46:00 +02001531 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001532
Harald Welte2a139372009-02-22 21:14:55 +00001533 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001534 if (!subscr)
1535 return gsm48_tx_mm_serv_rej(msg->lchan,
1536 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1537
1538 if (!msg->lchan->subscr)
1539 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001540 else if (msg->lchan->subscr != subscr) {
1541 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1542 subscr_put(subscr);
1543 }
1544
Harald Weltec2e302d2009-07-05 14:08:13 +02001545 subscr->equipment.classmark2_len = classmark2_len;
1546 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1547 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001548
Harald Welte4b634542008-12-27 01:55:51 +00001549 return gsm48_tx_mm_serv_ack(msg->lchan);
1550}
1551
Harald Welte2a139372009-02-22 21:14:55 +00001552static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1553{
Harald Welte9176bd42009-07-23 18:46:00 +02001554 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001555 struct gsm48_hdr *gh = msgb_l3(msg);
1556 struct gsm48_imsi_detach_ind *idi =
1557 (struct gsm48_imsi_detach_ind *) gh->data;
1558 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1559 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001560 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001561
1562 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1563 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1564 mi_type, mi_string);
1565
1566 switch (mi_type) {
1567 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001568 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001569 break;
1570 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001571 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001572 break;
1573 case GSM_MI_TYPE_IMEI:
1574 case GSM_MI_TYPE_IMEISV:
1575 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001576 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001577 break;
1578 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001579 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001580 break;
1581 }
1582
Holger Freyther4a49e772009-04-12 05:37:29 +00001583 if (subscr) {
1584 subscr_update(subscr, msg->trx->bts,
1585 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001586 DEBUGP(DMM, "Subscriber: %s\n",
1587 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001588 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001589 } else
Harald Welte2a139372009-02-22 21:14:55 +00001590 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1591
Harald Welte2a139372009-02-22 21:14:55 +00001592 return 0;
1593}
1594
Harald Welted2a7f5a2009-06-05 20:08:20 +00001595static int gsm48_rx_mm_status(struct msgb *msg)
1596{
1597 struct gsm48_hdr *gh = msgb_l3(msg);
1598
1599 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1600
1601 return 0;
1602}
1603
Harald Weltebf5e8df2009-02-03 12:59:45 +00001604/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001605static int gsm0408_rcv_mm(struct msgb *msg)
1606{
1607 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001608 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001609
1610 switch (gh->msg_type & 0xbf) {
1611 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001612 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001613 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001614 break;
1615 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001616 rc = mm_rx_id_resp(msg);
1617 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001618 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001619 rc = gsm48_rx_mm_serv_req(msg);
1620 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001621 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001622 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001623 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001624 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001625 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1626 msg->lchan->subscr ?
1627 msg->lchan->subscr->imsi :
1628 "unknown subscriber");
1629 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001630 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001631 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1632 break;
1633 case GSM48_MT_MM_CM_REEST_REQ:
1634 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1635 break;
1636 case GSM48_MT_MM_AUTH_RESP:
1637 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001638 break;
1639 default:
1640 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1641 gh->msg_type);
1642 break;
1643 }
1644
1645 return rc;
1646}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001647
Harald Welte2d35ae62009-02-06 12:02:13 +00001648/* Receive a PAGING RESPONSE message from the MS */
1649static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1650{
Harald Welte9176bd42009-07-23 18:46:00 +02001651 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001652 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001653 u_int8_t *classmark2_lv = gh->data + 1;
1654 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1655 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001656 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001657 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001658 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001659 int rc = 0;
1660
Harald Welte61548982009-02-22 21:26:29 +00001661 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001662 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1663 mi_type, mi_string);
Harald Welte3ac7f102009-08-10 10:12:45 +02001664
1665 if (is_siemens_bts(bts))
1666 send_siemens_mrpci(msg->lchan, classmark2_lv);
1667
Harald Weltefe18d8f2009-02-22 21:14:24 +00001668 switch (mi_type) {
1669 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001670 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001671 break;
1672 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001673 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001674 break;
1675 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001676
1677 if (!subscr) {
1678 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001679 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001680 return -EINVAL;
1681 }
1682 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte76042182009-08-08 16:03:15 +02001683 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001684
Harald Weltec2e302d2009-07-05 14:08:13 +02001685 subscr->equipment.classmark2_len = *classmark2_lv;
1686 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1687 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001688
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001689 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001690 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001691 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001692 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1693 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001694 return -EINVAL;
1695 } else {
1696 DEBUGP(DRR, "<- Channel already owned by us\n");
1697 subscr_put(subscr);
1698 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001699 }
1700
Harald Welte595ad7b2009-02-16 22:05:44 +00001701 sig_data.subscr = subscr;
1702 sig_data.bts = msg->lchan->ts->trx->bts;
1703 sig_data.lchan = msg->lchan;
1704
1705 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001706
1707 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001708 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001709
Harald Welte7584aea2009-02-11 11:44:12 +00001710 /* FIXME: somehow signal the completion of the PAGING to
1711 * the entity that requested the paging */
1712
Harald Welte2d35ae62009-02-06 12:02:13 +00001713 return rc;
1714}
1715
Harald Weltef7c43522009-06-09 20:24:21 +00001716static int gsm48_rx_rr_classmark(struct msgb *msg)
1717{
1718 struct gsm48_hdr *gh = msgb_l3(msg);
1719 struct gsm_subscriber *subscr = msg->lchan->subscr;
1720 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1721 u_int8_t cm2_len, cm3_len = 0;
1722 u_int8_t *cm2, *cm3 = NULL;
1723
1724 DEBUGP(DRR, "CLASSMARK CHANGE ");
1725
1726 /* classmark 2 */
1727 cm2_len = gh->data[0];
1728 cm2 = &gh->data[1];
1729 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1730
1731 if (payload_len > cm2_len + 1) {
1732 /* we must have a classmark3 */
1733 if (gh->data[cm2_len+1] != 0x20) {
1734 DEBUGPC(DRR, "ERR CM3 TAG\n");
1735 return -EINVAL;
1736 }
1737 if (cm2_len > 3) {
1738 DEBUGPC(DRR, "CM2 too long!\n");
1739 return -EINVAL;
1740 }
1741
1742 cm3_len = gh->data[cm2_len+2];
1743 cm3 = &gh->data[cm2_len+3];
1744 if (cm3_len > 14) {
1745 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1746 return -EINVAL;
1747 }
1748 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1749 }
1750 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001751 subscr->equipment.classmark2_len = cm2_len;
1752 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001753 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001754 subscr->equipment.classmark3_len = cm3_len;
1755 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001756 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001757 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001758 }
1759
Harald Weltef7c43522009-06-09 20:24:21 +00001760 return 0;
1761}
1762
Harald Weltecf5b3592009-05-01 18:28:42 +00001763static int gsm48_rx_rr_status(struct msgb *msg)
1764{
1765 struct gsm48_hdr *gh = msgb_l3(msg);
1766
1767 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1768 rr_cause_name(gh->data[0]));
1769
1770 return 0;
1771}
1772
Harald Weltef7c43522009-06-09 20:24:21 +00001773static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1774{
1775 struct gsm48_hdr *gh = msgb_l3(msg);
1776 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1777 static struct gsm_meas_rep meas_rep;
1778
Harald Welte10d0e672009-06-27 02:53:10 +02001779 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001780 parse_meas_rep(&meas_rep, gh->data, payload_len);
1781 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001782 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001783 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001784 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001785 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001786 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001787 else
Harald Welte10d0e672009-06-27 02:53:10 +02001788 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001789 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1790 meas_rep.rxqual_sub);
1791
Harald Welte10d0e672009-06-27 02:53:10 +02001792 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001793
1794 /* FIXME: put the results somwhere */
1795
1796 return 0;
1797}
1798
Harald Weltebf5e8df2009-02-03 12:59:45 +00001799/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001800static int gsm0408_rcv_rr(struct msgb *msg)
1801{
1802 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001803 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001804
1805 switch (gh->msg_type) {
1806 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001807 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001808 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001809 case GSM48_MT_RR_GPRS_SUSP_REQ:
1810 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1811 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001812 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001813 rc = gsm48_rr_rx_pag_resp(msg);
1814 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001815 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1816 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte13cac662009-07-29 12:10:35 +02001817 /* We've successfully modified the MS side of the channel,
1818 * now go on to modify the BTS side of the channel */
Harald Welte9943c5b2009-07-29 15:41:29 +02001819 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte2c38aa82009-02-18 03:44:24 +00001820 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001821 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001822 case GSM48_MT_RR_STATUS:
1823 rc = gsm48_rx_rr_status(msg);
1824 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001825 case GSM48_MT_RR_MEAS_REP:
1826 rc = gsm48_rx_rr_meas_rep(msg);
1827 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001828 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001829 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001830 gh->msg_type);
1831 break;
1832 }
1833
Harald Welte2d35ae62009-02-06 12:02:13 +00001834 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001835}
1836
Harald Welte115d1032009-08-10 11:43:22 +02001837/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Holger Freythere64a7a32009-02-06 21:55:37 +00001838int gsm48_send_rr_release(struct gsm_lchan *lchan)
1839{
1840 struct msgb *msg = gsm48_msgb_alloc();
1841 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1842 u_int8_t *cause;
1843
1844 msg->lchan = lchan;
1845 gh->proto_discr = GSM48_PDISC_RR;
1846 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1847
1848 cause = msgb_put(msg, 1);
1849 cause[0] = GSM48_RR_CAUSE_NORMAL;
1850
1851 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1852 lchan->nr, lchan->type);
1853
Harald Welteae0f2362009-07-19 18:36:49 +02001854 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001855 gsm48_sendmsg(msg, NULL);
Harald Welte76042182009-08-08 16:03:15 +02001856 /* FIXME: Start Timer T3109 */
Harald Welteae0f2362009-07-19 18:36:49 +02001857
1858 /* Deactivate the SACCH on the BTS side */
1859 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001860}
1861
Harald Welte4bc90a12008-12-27 16:32:52 +00001862/* Call Control */
1863
Harald Welte7584aea2009-02-11 11:44:12 +00001864/* The entire call control code is written in accordance with Figure 7.10c
1865 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1866 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1867 * it for voice */
1868
Harald Welte4bfdfe72009-06-10 23:11:52 +08001869static void new_cc_state(struct gsm_trans *trans, int state)
1870{
1871 if (state > 31 || state < 0)
1872 return;
1873
1874 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltedcaf5652009-07-23 18:56:43 +02001875 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001876
Harald Weltedcaf5652009-07-23 18:56:43 +02001877 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001878}
1879
1880static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001881{
1882 struct msgb *msg = gsm48_msgb_alloc();
1883 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1884 u_int8_t *cause, *call_state;
1885
Harald Welte4bc90a12008-12-27 16:32:52 +00001886 gh->msg_type = GSM48_MT_CC_STATUS;
1887
1888 cause = msgb_put(msg, 3);
1889 cause[0] = 2;
1890 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1891 cause[2] = 0x80 | 30; /* response to status inquiry */
1892
1893 call_state = msgb_put(msg, 1);
1894 call_state[0] = 0xc0 | 0x00;
1895
Harald Welte39e2ead2009-07-23 21:13:03 +02001896 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001897}
1898
Harald Welte6f4b7532008-12-29 00:39:37 +00001899static int gsm48_tx_simple(struct gsm_lchan *lchan,
1900 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001901{
1902 struct msgb *msg = gsm48_msgb_alloc();
1903 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1904
1905 msg->lchan = lchan;
1906
Harald Welte6f4b7532008-12-29 00:39:37 +00001907 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001908 gh->msg_type = msg_type;
1909
Harald Welte39e2ead2009-07-23 21:13:03 +02001910 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001911}
1912
Harald Welte4bfdfe72009-06-10 23:11:52 +08001913static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1914{
Harald Weltedcaf5652009-07-23 18:56:43 +02001915 if (bsc_timer_pending(&trans->cc.timer)) {
1916 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1917 bsc_del_timer(&trans->cc.timer);
1918 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001919 }
1920}
1921
1922static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1923 int msg_type, struct gsm_mncc *mncc)
1924{
1925 struct msgb *msg;
1926
1927 if (trans)
1928 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001929 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001930 "Sending '%s' to MNCC.\n",
1931 trans->lchan->ts->trx->bts->nr,
1932 trans->lchan->ts->trx->nr,
1933 trans->lchan->ts->nr, trans->transaction_id,
1934 (trans->subscr)?(trans->subscr->extension):"-",
1935 get_mncc_name(msg_type));
1936 else
1937 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1938 "Sending '%s' to MNCC.\n",
1939 (trans->subscr)?(trans->subscr->extension):"-",
1940 get_mncc_name(msg_type));
1941 else
1942 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1943 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1944
1945 mncc->msg_type = msg_type;
1946
Harald Welte966636f2009-06-26 19:39:35 +02001947 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001948 if (!msg)
1949 return -ENOMEM;
1950 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1951 msgb_enqueue(&net->upqueue, msg);
1952
1953 return 0;
1954}
1955
1956int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1957 u_int32_t callref, int location, int value)
1958{
1959 struct gsm_mncc rel;
1960
Harald Welte92f70c52009-06-12 01:54:08 +08001961 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001962 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001963 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001964 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1965}
1966
Harald Weltedcaf5652009-07-23 18:56:43 +02001967/* Call Control Specific transaction release.
1968 * gets called by trans_free, DO NOT CALL YOURSELF! */
1969void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001970{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001971 gsm48_stop_cc_timer(trans);
1972
1973 /* send release to L4, if callref still exists */
1974 if (trans->callref) {
1975 /* Ressource unavailable */
Harald Welte596fed42009-07-23 19:06:52 +02001976 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001977 GSM48_CAUSE_LOC_PRN_S_LU,
1978 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001979 }
Harald Weltedcaf5652009-07-23 18:56:43 +02001980 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001981 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltedcaf5652009-07-23 18:56:43 +02001982 if (trans->lchan)
1983 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001984}
1985
1986static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
1987
Harald Welte09e38af2009-02-16 22:52:23 +00001988/* call-back from paging the B-end of the connection */
1989static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00001990 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001991{
Harald Welte7ccf7782009-02-17 01:43:01 +00001992 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001993 struct gsm_subscriber *subscr = param;
1994 struct gsm_trans *transt, *tmp;
1995 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02001996
Harald Welte09e38af2009-02-16 22:52:23 +00001997 if (hooknum != GSM_HOOK_RR_PAGING)
1998 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001999
2000 if (!subscr)
2001 return -EINVAL;
2002 net = subscr->net;
2003 if (!net) {
2004 DEBUGP(DCC, "Error Network not set!\n");
2005 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00002006 }
Harald Welte7584aea2009-02-11 11:44:12 +00002007
Harald Welte4bfdfe72009-06-10 23:11:52 +08002008 /* check all tranactions (without lchan) for subscriber */
2009 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
2010 if (transt->subscr != subscr || transt->lchan)
2011 continue;
2012 switch (event) {
2013 case GSM_PAGING_SUCCEEDED:
2014 if (!lchan) // paranoid
2015 break;
2016 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
2017 subscr->extension);
2018 /* Assign lchan */
2019 if (!transt->lchan) {
2020 transt->lchan = lchan;
2021 use_lchan(lchan);
2022 }
2023 /* send SETUP request to called party */
Harald Weltedcaf5652009-07-23 18:56:43 +02002024 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002025 break;
2026 case GSM_PAGING_EXPIRED:
2027 DEBUGP(DCC, "Paging subscr %s expired!\n",
2028 subscr->extension);
2029 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002030 mncc_release_ind(transt->subscr->net, transt,
2031 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002032 GSM48_CAUSE_LOC_PRN_S_LU,
2033 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002034 transt->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002035 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002036 break;
2037 }
2038 }
Harald Welte09e38af2009-02-16 22:52:23 +00002039 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00002040}
Harald Welte7584aea2009-02-11 11:44:12 +00002041
Harald Welte805f6442009-07-28 18:25:29 +02002042/* some other part of the code sends us a signal */
2043static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2044 void *handler_data, void *signal_data)
2045{
2046 struct gsm_lchan *lchan = signal_data;
2047 struct gsm_bts_trx_ts *ts;
2048 int rc;
2049
2050 if (subsys != SS_ABISIP)
2051 return 0;
2052
2053 /* in case we use direct BTS-to-BTS RTP */
2054 if (ipacc_rtp_direct)
2055 return 0;
2056
2057 ts = lchan->ts;
2058
2059 switch (signal) {
2060 case S_ABISIP_BIND_ACK:
2061 /* the BTS has successfully bound a TCH to a local ip/port,
2062 * which means we can connect our UDP socket to it */
2063 if (ts->abis_ip.rtp_socket) {
2064 rtp_socket_free(ts->abis_ip.rtp_socket);
2065 ts->abis_ip.rtp_socket = NULL;
2066 }
2067
2068 ts->abis_ip.rtp_socket = rtp_socket_create();
2069 if (!ts->abis_ip.rtp_socket)
2070 goto out_err;
2071
2072 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2073 ts->abis_ip.bound_ip,
2074 ts->abis_ip.bound_port);
2075 if (rc < 0)
2076 goto out_err;
2077 break;
2078 case S_ABISIP_DISC_IND:
2079 /* the BTS tells us a RTP stream has been disconnected */
2080 if (ts->abis_ip.rtp_socket) {
2081 rtp_socket_free(ts->abis_ip.rtp_socket);
2082 ts->abis_ip.rtp_socket = NULL;
2083 }
2084 break;
2085 }
2086
2087 return 0;
2088out_err:
2089 /* FIXME: do something */
2090 return 0;
2091}
2092
2093/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2094static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2095{
2096 struct gsm_bts_trx_ts *ts = lchan->ts;
2097 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2098 int rc;
2099
2100 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2101 ntohs(rs->rtp.sin_local.sin_port),
2102 ts->abis_ip.conn_id,
2103 /* FIXME: use RTP payload of bound socket, not BTS*/
2104 ts->abis_ip.rtp_payload2);
2105
2106 return rc;
2107}
2108
Harald Welte49f48b82009-02-17 15:29:33 +00002109/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00002110static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00002111{
Harald Welte11fa29c2009-02-19 17:24:39 +00002112 struct gsm_bts *bts = lchan->ts->trx->bts;
2113 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00002114 struct gsm_bts_trx_ts *ts;
Harald Welte805f6442009-07-28 18:25:29 +02002115 int rc;
Harald Welte49f48b82009-02-17 15:29:33 +00002116
Harald Welte11fa29c2009-02-19 17:24:39 +00002117 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2118 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2119 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2120
2121 if (bts->type != remote_bts->type) {
2122 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2123 return -EINVAL;
2124 }
Harald Welte49f48b82009-02-17 15:29:33 +00002125
Harald Welte11fa29c2009-02-19 17:24:39 +00002126 switch (bts->type) {
2127 case GSM_BTS_TYPE_NANOBTS_900:
2128 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte805f6442009-07-28 18:25:29 +02002129 if (!ipacc_rtp_direct) {
2130 /* connect the TCH's to our RTP proxy */
2131 rc = ipacc_connect_proxy_bind(lchan);
2132 if (rc < 0)
2133 return rc;
2134 rc = ipacc_connect_proxy_bind(remote_lchan);
2135
2136 /* connect them with each other */
2137 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2138 remote_lchan->ts->abis_ip.rtp_socket);
2139 } else {
2140 /* directly connect TCH RTP streams to each other */
2141 ts = remote_lchan->ts;
2142 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2143 ts->abis_ip.bound_port,
2144 lchan->ts->abis_ip.conn_id,
2145 ts->abis_ip.rtp_payload2);
2146 if (rc < 0)
2147 return rc;
2148 ts = lchan->ts;
2149 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2150 ts->abis_ip.bound_port,
2151 remote_lchan->ts->abis_ip.conn_id,
2152 ts->abis_ip.rtp_payload2);
2153 }
Harald Welte11fa29c2009-02-19 17:24:39 +00002154 break;
2155 case GSM_BTS_TYPE_BS11:
2156 trau_mux_map_lchan(lchan, remote_lchan);
2157 break;
2158 default:
2159 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte805f6442009-07-28 18:25:29 +02002160 rc = -EINVAL;
Harald Welte11fa29c2009-02-19 17:24:39 +00002161 break;
2162 }
Harald Welte49f48b82009-02-17 15:29:33 +00002163
2164 return 0;
2165}
2166
Harald Welte4bfdfe72009-06-10 23:11:52 +08002167/* bridge channels of two transactions */
2168static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002169{
Harald Weltedcaf5652009-07-23 18:56:43 +02002170 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2171 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002172
Harald Welte4bfdfe72009-06-10 23:11:52 +08002173 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002174 return -EIO;
2175
Harald Welte4bfdfe72009-06-10 23:11:52 +08002176 if (!trans1->lchan || !trans2->lchan)
2177 return -EIO;
2178
2179 /* through-connect channel */
2180 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002181}
2182
Harald Welte4bfdfe72009-06-10 23:11:52 +08002183/* enable receive of channels to upqueue */
2184static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2185{
2186 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002187
Harald Welte4bfdfe72009-06-10 23:11:52 +08002188 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002189 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002190 if (!trans)
2191 return -EIO;
2192 if (!trans->lchan)
2193 return 0;
2194
2195 // todo IPACCESS
2196 if (enable)
2197 return trau_recv_lchan(trans->lchan, data->callref);
2198 return trau_mux_unmap(NULL, data->callref);
2199}
2200
2201/* send a frame to channel */
2202static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2203{
2204 struct gsm_trans *trans;
2205
2206 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002207 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002208 if (!trans)
2209 return -EIO;
2210 if (!trans->lchan)
2211 return 0;
2212 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2213 trans->lchan->type != GSM_LCHAN_TCH_H)
2214 return 0;
2215
2216 // todo IPACCESS
2217 return trau_send_lchan(trans->lchan,
2218 (struct decoded_trau_frame *)frame->data);
2219}
2220
2221
2222static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2223{
2224 DEBUGP(DCC, "-> STATUS ENQ\n");
2225 return gsm48_cc_tx_status(trans, msg);
2226}
2227
2228static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2229static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2230
2231static void gsm48_cc_timeout(void *arg)
2232{
2233 struct gsm_trans *trans = arg;
2234 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002235 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2236 int mo_location = GSM48_CAUSE_LOC_USER;
2237 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2238 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002239 struct gsm_mncc mo_rel, l4_rel;
2240
2241 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2242 mo_rel.callref = trans->callref;
2243 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2244 l4_rel.callref = trans->callref;
2245
Harald Weltedcaf5652009-07-23 18:56:43 +02002246 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002247 case 0x303:
2248 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002249 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002250 break;
2251 case 0x310:
2252 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002253 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002254 break;
2255 case 0x313:
2256 disconnect = 1;
2257 /* unknown, did not find it in the specs */
2258 break;
2259 case 0x301:
2260 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002261 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002262 break;
2263 case 0x308:
Harald Weltedcaf5652009-07-23 18:56:43 +02002264 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002265 /* restart T308 a second time */
Harald Weltedcaf5652009-07-23 18:56:43 +02002266 gsm48_cc_tx_release(trans, &trans->cc.msg);
2267 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002268 break; /* stay in release state */
2269 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002270 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002271 return;
2272// release = 1;
2273// l4_cause = 14;
2274// break;
2275 case 0x306:
2276 release = 1;
Harald Weltedcaf5652009-07-23 18:56:43 +02002277 mo_cause = trans->cc.msg.cause.value;
2278 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002279 break;
2280 case 0x323:
2281 disconnect = 1;
2282 break;
2283 default:
2284 release = 1;
2285 }
2286
2287 if (release && trans->callref) {
2288 /* process release towards layer 4 */
Harald Welte596fed42009-07-23 19:06:52 +02002289 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002290 l4_location, l4_cause);
2291 trans->callref = 0;
2292 }
2293
2294 if (disconnect && trans->callref) {
2295 /* process disconnect towards layer 4 */
2296 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte596fed42009-07-23 19:06:52 +02002297 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002298 }
2299
2300 /* process disconnect towards mobile station */
2301 if (disconnect || release) {
2302 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltedcaf5652009-07-23 18:56:43 +02002303 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2304 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2305 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002306 mo_rel.cause.diag_len = 3;
2307
2308 if (disconnect)
2309 gsm48_cc_tx_disconnect(trans, &mo_rel);
2310 if (release)
2311 gsm48_cc_tx_release(trans, &mo_rel);
2312 }
2313
2314}
2315
2316static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2317 int sec, int micro)
2318{
2319 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltedcaf5652009-07-23 18:56:43 +02002320 trans->cc.timer.cb = gsm48_cc_timeout;
2321 trans->cc.timer.data = trans;
2322 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2323 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002324}
2325
2326static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2327{
2328 struct gsm48_hdr *gh = msgb_l3(msg);
2329 u_int8_t msg_type = gh->msg_type & 0xbf;
2330 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2331 struct tlv_parsed tp;
2332 struct gsm_mncc setup;
2333
2334 memset(&setup, 0, sizeof(struct gsm_mncc));
2335 setup.callref = trans->callref;
2336 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2337 /* emergency setup is identified by msg_type */
2338 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2339 setup.emergency = 1;
2340
2341 /* use subscriber as calling party number */
2342 if (trans->subscr) {
2343 setup.fields |= MNCC_F_CALLING;
2344 strncpy(setup.calling.number, trans->subscr->extension,
2345 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002346 strncpy(setup.imsi, trans->subscr->imsi,
2347 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002348 }
2349 /* bearer capability */
2350 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2351 setup.fields |= MNCC_F_BEARER_CAP;
2352 decode_bearer_cap(&setup.bearer_cap,
2353 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2354 }
2355 /* facility */
2356 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2357 setup.fields |= MNCC_F_FACILITY;
2358 decode_facility(&setup.facility,
2359 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2360 }
2361 /* called party bcd number */
2362 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2363 setup.fields |= MNCC_F_CALLED;
2364 decode_called(&setup.called,
2365 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2366 }
2367 /* user-user */
2368 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2369 setup.fields |= MNCC_F_USERUSER;
2370 decode_useruser(&setup.useruser,
2371 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2372 }
2373 /* ss-version */
2374 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2375 setup.fields |= MNCC_F_SSVERSION;
2376 decode_ssversion(&setup.ssversion,
2377 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2378 }
2379 /* CLIR suppression */
2380 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2381 setup.clir.sup = 1;
2382 /* CLIR invocation */
2383 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2384 setup.clir.inv = 1;
2385 /* cc cap */
2386 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2387 setup.fields |= MNCC_F_CCCAP;
2388 decode_cccap(&setup.cccap,
2389 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2390 }
2391
Harald Welte4bfdfe72009-06-10 23:11:52 +08002392 new_cc_state(trans, GSM_CSTATE_INITIATED);
2393
2394 /* indicate setup to MNCC */
Harald Welte596fed42009-07-23 19:06:52 +02002395 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002396
Harald Welte13cac662009-07-29 12:10:35 +02002397 /* MNCC code will modify the channel asynchronously, we should
2398 * ipaccess-bind only after the modification has been made to the
2399 * lchan->tch_mode */
Harald Welte4bfdfe72009-06-10 23:11:52 +08002400 return 0;
2401}
2402
2403static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002404{
2405 struct msgb *msg = gsm48_msgb_alloc();
2406 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002407 struct gsm_mncc *setup = arg;
Harald Welte78283ef2009-07-23 21:36:44 +02002408 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00002409
Harald Welte7ccf7782009-02-17 01:43:01 +00002410 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002411
Harald Welte4bfdfe72009-06-10 23:11:52 +08002412 /* transaction id must not be assigned */
2413 if (trans->transaction_id != 0xff) { /* unasssigned */
2414 DEBUGP(DCC, "TX Setup with assigned transaction. "
2415 "This is not allowed!\n");
2416 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002417 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002418 GSM48_CAUSE_LOC_PRN_S_LU,
2419 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002420 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002421 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002422 return rc;
2423 }
2424
2425 /* Get free transaction_id */
Harald Welte78283ef2009-07-23 21:36:44 +02002426 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2427 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002428 /* no free transaction ID */
Harald Welte596fed42009-07-23 19:06:52 +02002429 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002430 GSM48_CAUSE_LOC_PRN_S_LU,
2431 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002432 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002433 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002434 return rc;
2435 }
Harald Welte78283ef2009-07-23 21:36:44 +02002436 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00002437
Harald Welte65e74cc2008-12-29 01:55:35 +00002438 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002439
Harald Welte4bfdfe72009-06-10 23:11:52 +08002440 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002441
Harald Welte4bfdfe72009-06-10 23:11:52 +08002442 /* bearer capability */
2443 if (setup->fields & MNCC_F_BEARER_CAP)
2444 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2445 /* facility */
2446 if (setup->fields & MNCC_F_FACILITY)
2447 encode_facility(msg, 0, &setup->facility);
2448 /* progress */
2449 if (setup->fields & MNCC_F_PROGRESS)
2450 encode_progress(msg, 0, &setup->progress);
2451 /* calling party BCD number */
2452 if (setup->fields & MNCC_F_CALLING)
2453 encode_calling(msg, &setup->calling);
2454 /* called party BCD number */
2455 if (setup->fields & MNCC_F_CALLED)
2456 encode_called(msg, &setup->called);
2457 /* user-user */
2458 if (setup->fields & MNCC_F_USERUSER)
2459 encode_useruser(msg, 0, &setup->useruser);
2460 /* redirecting party BCD number */
2461 if (setup->fields & MNCC_F_REDIRECTING)
2462 encode_redirecting(msg, &setup->redirecting);
2463 /* signal */
2464 if (setup->fields & MNCC_F_SIGNAL)
2465 encode_signal(msg, setup->signal);
2466
2467 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002468
Harald Welte39e2ead2009-07-23 21:13:03 +02002469 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002470}
2471
Harald Welte4bfdfe72009-06-10 23:11:52 +08002472static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2473{
2474 struct gsm48_hdr *gh = msgb_l3(msg);
2475 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2476 struct tlv_parsed tp;
2477 struct gsm_mncc call_conf;
2478
2479 gsm48_stop_cc_timer(trans);
2480 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2481
2482 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2483 call_conf.callref = trans->callref;
2484 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2485#if 0
2486 /* repeat */
2487 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2488 call_conf.repeat = 1;
2489 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2490 call_conf.repeat = 2;
2491#endif
2492 /* bearer capability */
2493 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2494 call_conf.fields |= MNCC_F_BEARER_CAP;
2495 decode_bearer_cap(&call_conf.bearer_cap,
2496 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2497 }
2498 /* cause */
2499 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2500 call_conf.fields |= MNCC_F_CAUSE;
2501 decode_cause(&call_conf.cause,
2502 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2503 }
2504 /* cc cap */
2505 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2506 call_conf.fields |= MNCC_F_CCCAP;
2507 decode_cccap(&call_conf.cccap,
2508 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2509 }
2510
2511 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2512
Harald Welte596fed42009-07-23 19:06:52 +02002513 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2514 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002515}
2516
2517static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2518{
2519 struct gsm_mncc *proceeding = arg;
2520 struct msgb *msg = gsm48_msgb_alloc();
2521 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2522
Harald Welte4bfdfe72009-06-10 23:11:52 +08002523 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2524
2525 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2526
2527 /* bearer capability */
2528 if (proceeding->fields & MNCC_F_BEARER_CAP)
2529 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2530 /* facility */
2531 if (proceeding->fields & MNCC_F_FACILITY)
2532 encode_facility(msg, 0, &proceeding->facility);
2533 /* progress */
2534 if (proceeding->fields & MNCC_F_PROGRESS)
2535 encode_progress(msg, 0, &proceeding->progress);
2536
Harald Welte39e2ead2009-07-23 21:13:03 +02002537 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002538}
2539
2540static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2541{
2542 struct gsm48_hdr *gh = msgb_l3(msg);
2543 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2544 struct tlv_parsed tp;
2545 struct gsm_mncc alerting;
2546
2547 gsm48_stop_cc_timer(trans);
2548 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2549
2550 memset(&alerting, 0, sizeof(struct gsm_mncc));
2551 alerting.callref = trans->callref;
2552 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2553 /* facility */
2554 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2555 alerting.fields |= MNCC_F_FACILITY;
2556 decode_facility(&alerting.facility,
2557 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2558 }
2559
2560 /* progress */
2561 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2562 alerting.fields |= MNCC_F_PROGRESS;
2563 decode_progress(&alerting.progress,
2564 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2565 }
2566 /* ss-version */
2567 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2568 alerting.fields |= MNCC_F_SSVERSION;
2569 decode_ssversion(&alerting.ssversion,
2570 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2571 }
2572
2573 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2574
Harald Welte596fed42009-07-23 19:06:52 +02002575 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2576 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002577}
2578
2579static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2580{
2581 struct gsm_mncc *alerting = arg;
2582 struct msgb *msg = gsm48_msgb_alloc();
2583 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2584
Harald Welte4bfdfe72009-06-10 23:11:52 +08002585 gh->msg_type = GSM48_MT_CC_ALERTING;
2586
2587 /* facility */
2588 if (alerting->fields & MNCC_F_FACILITY)
2589 encode_facility(msg, 0, &alerting->facility);
2590 /* progress */
2591 if (alerting->fields & MNCC_F_PROGRESS)
2592 encode_progress(msg, 0, &alerting->progress);
2593 /* user-user */
2594 if (alerting->fields & MNCC_F_USERUSER)
2595 encode_useruser(msg, 0, &alerting->useruser);
2596
2597 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2598
Harald Welte39e2ead2009-07-23 21:13:03 +02002599 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002600}
2601
2602static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2603{
2604 struct gsm_mncc *progress = arg;
2605 struct msgb *msg = gsm48_msgb_alloc();
2606 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2607
Harald Welte4bfdfe72009-06-10 23:11:52 +08002608 gh->msg_type = GSM48_MT_CC_PROGRESS;
2609
2610 /* progress */
2611 encode_progress(msg, 1, &progress->progress);
2612 /* user-user */
2613 if (progress->fields & MNCC_F_USERUSER)
2614 encode_useruser(msg, 0, &progress->useruser);
2615
Harald Welte39e2ead2009-07-23 21:13:03 +02002616 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002617}
2618
2619static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2620{
2621 struct gsm_mncc *connect = arg;
2622 struct msgb *msg = gsm48_msgb_alloc();
2623 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2624
Harald Welte4bfdfe72009-06-10 23:11:52 +08002625 gh->msg_type = GSM48_MT_CC_CONNECT;
2626
2627 gsm48_stop_cc_timer(trans);
2628 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2629
2630 /* facility */
2631 if (connect->fields & MNCC_F_FACILITY)
2632 encode_facility(msg, 0, &connect->facility);
2633 /* progress */
2634 if (connect->fields & MNCC_F_PROGRESS)
2635 encode_progress(msg, 0, &connect->progress);
2636 /* connected number */
2637 if (connect->fields & MNCC_F_CONNECTED)
2638 encode_connected(msg, &connect->connected);
2639 /* user-user */
2640 if (connect->fields & MNCC_F_USERUSER)
2641 encode_useruser(msg, 0, &connect->useruser);
2642
2643 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2644
Harald Welte39e2ead2009-07-23 21:13:03 +02002645 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002646}
2647
2648static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2649{
2650 struct gsm48_hdr *gh = msgb_l3(msg);
2651 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2652 struct tlv_parsed tp;
2653 struct gsm_mncc connect;
2654
2655 gsm48_stop_cc_timer(trans);
2656
2657 memset(&connect, 0, sizeof(struct gsm_mncc));
2658 connect.callref = trans->callref;
2659 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2660 /* use subscriber as connected party number */
2661 if (trans->subscr) {
2662 connect.fields |= MNCC_F_CONNECTED;
2663 strncpy(connect.connected.number, trans->subscr->extension,
2664 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002665 strncpy(connect.imsi, trans->subscr->imsi,
2666 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002667 }
2668 /* facility */
2669 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2670 connect.fields |= MNCC_F_FACILITY;
2671 decode_facility(&connect.facility,
2672 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2673 }
2674 /* user-user */
2675 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2676 connect.fields |= MNCC_F_USERUSER;
2677 decode_useruser(&connect.useruser,
2678 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2679 }
2680 /* ss-version */
2681 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2682 connect.fields |= MNCC_F_SSVERSION;
2683 decode_ssversion(&connect.ssversion,
2684 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2685 }
2686
2687 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2688
Harald Welte596fed42009-07-23 19:06:52 +02002689 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002690}
2691
2692
2693static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2694{
2695 struct gsm_mncc connect_ack;
2696
2697 gsm48_stop_cc_timer(trans);
2698
2699 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2700
2701 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2702 connect_ack.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002703 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002704 &connect_ack);
2705}
2706
2707static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2708{
2709 struct msgb *msg = gsm48_msgb_alloc();
2710 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2711
Harald Welte4bfdfe72009-06-10 23:11:52 +08002712 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2713
2714 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2715
Harald Welte39e2ead2009-07-23 21:13:03 +02002716 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002717}
2718
2719static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2720{
2721 struct gsm48_hdr *gh = msgb_l3(msg);
2722 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2723 struct tlv_parsed tp;
2724 struct gsm_mncc disc;
2725
2726 gsm48_stop_cc_timer(trans);
2727
2728 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2729
2730 memset(&disc, 0, sizeof(struct gsm_mncc));
2731 disc.callref = trans->callref;
2732 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2733 /* cause */
2734 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2735 disc.fields |= MNCC_F_CAUSE;
2736 decode_cause(&disc.cause,
2737 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2738 }
2739 /* facility */
2740 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2741 disc.fields |= MNCC_F_FACILITY;
2742 decode_facility(&disc.facility,
2743 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2744 }
2745 /* user-user */
2746 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2747 disc.fields |= MNCC_F_USERUSER;
2748 decode_useruser(&disc.useruser,
2749 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2750 }
2751 /* ss-version */
2752 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2753 disc.fields |= MNCC_F_SSVERSION;
2754 decode_ssversion(&disc.ssversion,
2755 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2756 }
2757
Harald Welte596fed42009-07-23 19:06:52 +02002758 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002759
2760}
2761
Harald Weltec66b71c2009-06-11 14:23:20 +08002762static struct gsm_mncc_cause default_cause = {
2763 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2764 .coding = 0,
2765 .rec = 0,
2766 .rec_val = 0,
2767 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2768 .diag_len = 0,
2769 .diag = { 0 },
2770};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002771
2772static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2773{
2774 struct gsm_mncc *disc = arg;
2775 struct msgb *msg = gsm48_msgb_alloc();
2776 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2777
Harald Welte4bfdfe72009-06-10 23:11:52 +08002778 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2779
2780 gsm48_stop_cc_timer(trans);
2781 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2782
2783 /* cause */
2784 if (disc->fields & MNCC_F_CAUSE)
2785 encode_cause(msg, 1, &disc->cause);
2786 else
2787 encode_cause(msg, 1, &default_cause);
2788
2789 /* facility */
2790 if (disc->fields & MNCC_F_FACILITY)
2791 encode_facility(msg, 0, &disc->facility);
2792 /* progress */
2793 if (disc->fields & MNCC_F_PROGRESS)
2794 encode_progress(msg, 0, &disc->progress);
2795 /* user-user */
2796 if (disc->fields & MNCC_F_USERUSER)
2797 encode_useruser(msg, 0, &disc->useruser);
2798
2799 /* store disconnect cause for T306 expiry */
Harald Weltedcaf5652009-07-23 18:56:43 +02002800 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002801
2802 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2803
Harald Welte39e2ead2009-07-23 21:13:03 +02002804 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002805}
2806
2807static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2808{
2809 struct gsm48_hdr *gh = msgb_l3(msg);
2810 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2811 struct tlv_parsed tp;
2812 struct gsm_mncc rel;
2813 int rc;
2814
2815 gsm48_stop_cc_timer(trans);
2816
2817 memset(&rel, 0, sizeof(struct gsm_mncc));
2818 rel.callref = trans->callref;
2819 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2820 /* cause */
2821 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2822 rel.fields |= MNCC_F_CAUSE;
2823 decode_cause(&rel.cause,
2824 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2825 }
2826 /* facility */
2827 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2828 rel.fields |= MNCC_F_FACILITY;
2829 decode_facility(&rel.facility,
2830 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2831 }
2832 /* user-user */
2833 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2834 rel.fields |= MNCC_F_USERUSER;
2835 decode_useruser(&rel.useruser,
2836 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2837 }
2838 /* ss-version */
2839 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2840 rel.fields |= MNCC_F_SSVERSION;
2841 decode_ssversion(&rel.ssversion,
2842 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2843 }
2844
Harald Weltedcaf5652009-07-23 18:56:43 +02002845 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002846 /* release collision 5.4.5 */
Harald Welte596fed42009-07-23 19:06:52 +02002847 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002848 } else {
Harald Welte596fed42009-07-23 19:06:52 +02002849 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002850 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte596fed42009-07-23 19:06:52 +02002851 GSM48_MT_CC_RELEASE_COMPL);
2852 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002853 }
2854
2855 new_cc_state(trans, GSM_CSTATE_NULL);
2856
2857 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002858 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002859
2860 return rc;
2861}
2862
2863static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2864{
2865 struct gsm_mncc *rel = arg;
2866 struct msgb *msg = gsm48_msgb_alloc();
2867 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2868
Harald Welte4bfdfe72009-06-10 23:11:52 +08002869 gh->msg_type = GSM48_MT_CC_RELEASE;
2870
2871 trans->callref = 0;
2872
2873 gsm48_stop_cc_timer(trans);
2874 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2875
2876 /* cause */
2877 if (rel->fields & MNCC_F_CAUSE)
2878 encode_cause(msg, 0, &rel->cause);
2879 /* facility */
2880 if (rel->fields & MNCC_F_FACILITY)
2881 encode_facility(msg, 0, &rel->facility);
2882 /* user-user */
2883 if (rel->fields & MNCC_F_USERUSER)
2884 encode_useruser(msg, 0, &rel->useruser);
2885
Harald Weltedcaf5652009-07-23 18:56:43 +02002886 trans->cc.T308_second = 0;
2887 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002888
Harald Weltedcaf5652009-07-23 18:56:43 +02002889 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002890 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2891
Harald Welte39e2ead2009-07-23 21:13:03 +02002892 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002893}
2894
2895static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2896{
2897 struct gsm48_hdr *gh = msgb_l3(msg);
2898 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2899 struct tlv_parsed tp;
2900 struct gsm_mncc rel;
2901 int rc = 0;
2902
2903 gsm48_stop_cc_timer(trans);
2904
2905 memset(&rel, 0, sizeof(struct gsm_mncc));
2906 rel.callref = trans->callref;
2907 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2908 /* cause */
2909 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2910 rel.fields |= MNCC_F_CAUSE;
2911 decode_cause(&rel.cause,
2912 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2913 }
2914 /* facility */
2915 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2916 rel.fields |= MNCC_F_FACILITY;
2917 decode_facility(&rel.facility,
2918 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2919 }
2920 /* user-user */
2921 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2922 rel.fields |= MNCC_F_USERUSER;
2923 decode_useruser(&rel.useruser,
2924 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2925 }
2926 /* ss-version */
2927 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2928 rel.fields |= MNCC_F_SSVERSION;
2929 decode_ssversion(&rel.ssversion,
2930 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2931 }
2932
2933 if (trans->callref) {
Harald Weltedcaf5652009-07-23 18:56:43 +02002934 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002935 case GSM_CSTATE_CALL_PRESENT:
Harald Welte596fed42009-07-23 19:06:52 +02002936 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002937 MNCC_REJ_IND, &rel);
2938 break;
2939 case GSM_CSTATE_RELEASE_REQ:
Harald Welte596fed42009-07-23 19:06:52 +02002940 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002941 MNCC_REL_CNF, &rel);
2942 break;
2943 default:
Harald Welte596fed42009-07-23 19:06:52 +02002944 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002945 MNCC_REL_IND, &rel);
2946 }
2947 }
2948
2949 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002950 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002951
2952 return rc;
2953}
2954
2955static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2956{
2957 struct gsm_mncc *rel = arg;
2958 struct msgb *msg = gsm48_msgb_alloc();
2959 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2960
Harald Welte4bfdfe72009-06-10 23:11:52 +08002961 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2962
2963 trans->callref = 0;
2964
2965 gsm48_stop_cc_timer(trans);
2966
2967 /* cause */
2968 if (rel->fields & MNCC_F_CAUSE)
2969 encode_cause(msg, 0, &rel->cause);
2970 /* facility */
2971 if (rel->fields & MNCC_F_FACILITY)
2972 encode_facility(msg, 0, &rel->facility);
2973 /* user-user */
2974 if (rel->fields & MNCC_F_USERUSER)
2975 encode_useruser(msg, 0, &rel->useruser);
2976
Harald Weltedcaf5652009-07-23 18:56:43 +02002977 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002978
Harald Welte39e2ead2009-07-23 21:13:03 +02002979 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002980}
2981
2982static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2983{
2984 struct gsm48_hdr *gh = msgb_l3(msg);
2985 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2986 struct tlv_parsed tp;
2987 struct gsm_mncc fac;
2988
2989 memset(&fac, 0, sizeof(struct gsm_mncc));
2990 fac.callref = trans->callref;
2991 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
2992 /* facility */
2993 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2994 fac.fields |= MNCC_F_FACILITY;
2995 decode_facility(&fac.facility,
2996 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2997 }
2998 /* ss-version */
2999 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3000 fac.fields |= MNCC_F_SSVERSION;
3001 decode_ssversion(&fac.ssversion,
3002 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3003 }
3004
Harald Welte596fed42009-07-23 19:06:52 +02003005 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003006}
3007
3008static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
3009{
3010 struct gsm_mncc *fac = 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_FACILITY;
3015
3016 /* facility */
3017 encode_facility(msg, 1, &fac->facility);
3018
Harald Welte39e2ead2009-07-23 21:13:03 +02003019 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003020}
3021
3022static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
3023{
3024 struct gsm_mncc hold;
3025
3026 memset(&hold, 0, sizeof(struct gsm_mncc));
3027 hold.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003028 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003029}
3030
3031static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3032{
3033 struct msgb *msg = gsm48_msgb_alloc();
3034 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3035
Harald Welte4bfdfe72009-06-10 23:11:52 +08003036 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3037
Harald Welte39e2ead2009-07-23 21:13:03 +02003038 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003039}
3040
3041static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3042{
3043 struct gsm_mncc *hold_rej = arg;
3044 struct msgb *msg = gsm48_msgb_alloc();
3045 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3046
Harald Welte4bfdfe72009-06-10 23:11:52 +08003047 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3048
3049 /* cause */
3050 if (hold_rej->fields & MNCC_F_CAUSE)
3051 encode_cause(msg, 1, &hold_rej->cause);
3052 else
3053 encode_cause(msg, 1, &default_cause);
3054
Harald Welte39e2ead2009-07-23 21:13:03 +02003055 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003056}
3057
3058static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3059{
3060 struct gsm_mncc retrieve;
3061
3062 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3063 retrieve.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003064 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3065 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003066}
3067
3068static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3069{
3070 struct msgb *msg = gsm48_msgb_alloc();
3071 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3072
Harald Welte4bfdfe72009-06-10 23:11:52 +08003073 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3074
Harald Welte39e2ead2009-07-23 21:13:03 +02003075 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003076}
3077
3078static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3079{
3080 struct gsm_mncc *retrieve_rej = arg;
3081 struct msgb *msg = gsm48_msgb_alloc();
3082 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3083
Harald Welte4bfdfe72009-06-10 23:11:52 +08003084 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3085
3086 /* cause */
3087 if (retrieve_rej->fields & MNCC_F_CAUSE)
3088 encode_cause(msg, 1, &retrieve_rej->cause);
3089 else
3090 encode_cause(msg, 1, &default_cause);
3091
Harald Welte39e2ead2009-07-23 21:13:03 +02003092 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003093}
3094
3095static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3096{
3097 struct gsm48_hdr *gh = msgb_l3(msg);
3098 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3099 struct tlv_parsed tp;
3100 struct gsm_mncc dtmf;
3101
3102 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3103 dtmf.callref = trans->callref;
3104 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3105 /* keypad facility */
3106 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3107 dtmf.fields |= MNCC_F_KEYPAD;
3108 decode_keypad(&dtmf.keypad,
3109 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3110 }
3111
Harald Welte596fed42009-07-23 19:06:52 +02003112 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003113}
3114
3115static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3116{
3117 struct gsm_mncc *dtmf = arg;
3118 struct msgb *msg = gsm48_msgb_alloc();
3119 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3120
Harald Welte4bfdfe72009-06-10 23:11:52 +08003121 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3122
3123 /* keypad */
3124 if (dtmf->fields & MNCC_F_KEYPAD)
3125 encode_keypad(msg, dtmf->keypad);
3126
Harald Welte39e2ead2009-07-23 21:13:03 +02003127 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003128}
3129
3130static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3131{
3132 struct gsm_mncc *dtmf = arg;
3133 struct msgb *msg = gsm48_msgb_alloc();
3134 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3135
Harald Welte4bfdfe72009-06-10 23:11:52 +08003136 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3137
3138 /* cause */
3139 if (dtmf->fields & MNCC_F_CAUSE)
3140 encode_cause(msg, 1, &dtmf->cause);
3141 else
3142 encode_cause(msg, 1, &default_cause);
3143
Harald Welte39e2ead2009-07-23 21:13:03 +02003144 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003145}
3146
3147static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3148{
3149 struct msgb *msg = gsm48_msgb_alloc();
3150 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3151
Harald Welte4bfdfe72009-06-10 23:11:52 +08003152 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3153
Harald Welte39e2ead2009-07-23 21:13:03 +02003154 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003155}
3156
3157static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3158{
3159 struct gsm_mncc dtmf;
3160
3161 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3162 dtmf.callref = trans->callref;
3163
Harald Welte596fed42009-07-23 19:06:52 +02003164 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003165}
3166
3167static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3168{
3169 struct gsm48_hdr *gh = msgb_l3(msg);
3170 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3171 struct tlv_parsed tp;
3172 struct gsm_mncc modify;
3173
3174 memset(&modify, 0, sizeof(struct gsm_mncc));
3175 modify.callref = trans->callref;
3176 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3177 /* bearer capability */
3178 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3179 modify.fields |= MNCC_F_BEARER_CAP;
3180 decode_bearer_cap(&modify.bearer_cap,
3181 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3182 }
3183
3184 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3185
Harald Welte596fed42009-07-23 19:06:52 +02003186 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003187}
3188
3189static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3190{
3191 struct gsm_mncc *modify = arg;
3192 struct msgb *msg = gsm48_msgb_alloc();
3193 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3194
Harald Welte4bfdfe72009-06-10 23:11:52 +08003195 gh->msg_type = GSM48_MT_CC_MODIFY;
3196
3197 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3198
3199 /* bearer capability */
3200 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3201
3202 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3203
Harald Welte39e2ead2009-07-23 21:13:03 +02003204 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003205}
3206
3207static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3208{
3209 struct gsm48_hdr *gh = msgb_l3(msg);
3210 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3211 struct tlv_parsed tp;
3212 struct gsm_mncc modify;
3213
3214 gsm48_stop_cc_timer(trans);
3215
3216 memset(&modify, 0, sizeof(struct gsm_mncc));
3217 modify.callref = trans->callref;
3218 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3219 /* bearer capability */
3220 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3221 modify.fields |= MNCC_F_BEARER_CAP;
3222 decode_bearer_cap(&modify.bearer_cap,
3223 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3224 }
3225
3226 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3227
Harald Welte596fed42009-07-23 19:06:52 +02003228 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003229}
3230
3231static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3232{
3233 struct gsm_mncc *modify = arg;
3234 struct msgb *msg = gsm48_msgb_alloc();
3235 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3236
Harald Welte4bfdfe72009-06-10 23:11:52 +08003237 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3238
3239 /* bearer capability */
3240 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3241
3242 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3243
Harald Welte39e2ead2009-07-23 21:13:03 +02003244 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003245}
3246
3247static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3248{
3249 struct gsm48_hdr *gh = msgb_l3(msg);
3250 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3251 struct tlv_parsed tp;
3252 struct gsm_mncc modify;
3253
3254 gsm48_stop_cc_timer(trans);
3255
3256 memset(&modify, 0, sizeof(struct gsm_mncc));
3257 modify.callref = trans->callref;
3258 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3259 /* bearer capability */
3260 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3261 modify.fields |= GSM48_IE_BEARER_CAP;
3262 decode_bearer_cap(&modify.bearer_cap,
3263 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3264 }
3265 /* cause */
3266 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3267 modify.fields |= MNCC_F_CAUSE;
3268 decode_cause(&modify.cause,
3269 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3270 }
3271
3272 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3273
Harald Welte596fed42009-07-23 19:06:52 +02003274 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003275}
3276
3277static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3278{
3279 struct gsm_mncc *modify = arg;
3280 struct msgb *msg = gsm48_msgb_alloc();
3281 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3282
Harald Welte4bfdfe72009-06-10 23:11:52 +08003283 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3284
3285 /* bearer capability */
3286 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3287 /* cause */
3288 encode_cause(msg, 1, &modify->cause);
3289
3290 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3291
Harald Welte39e2ead2009-07-23 21:13:03 +02003292 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003293}
3294
3295static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3296{
3297 struct gsm_mncc *notify = arg;
3298 struct msgb *msg = gsm48_msgb_alloc();
3299 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3300
Harald Welte4bfdfe72009-06-10 23:11:52 +08003301 gh->msg_type = GSM48_MT_CC_NOTIFY;
3302
3303 /* notify */
3304 encode_notify(msg, notify->notify);
3305
Harald Welte39e2ead2009-07-23 21:13:03 +02003306 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003307}
3308
3309static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3310{
3311 struct gsm48_hdr *gh = msgb_l3(msg);
3312 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3313// struct tlv_parsed tp;
3314 struct gsm_mncc notify;
3315
3316 memset(&notify, 0, sizeof(struct gsm_mncc));
3317 notify.callref = trans->callref;
3318// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3319 if (payload_len >= 1)
3320 decode_notify(&notify.notify, gh->data);
3321
Harald Welte596fed42009-07-23 19:06:52 +02003322 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003323}
3324
3325static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3326{
3327 struct gsm_mncc *user = arg;
3328 struct msgb *msg = gsm48_msgb_alloc();
3329 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3330
Harald Welte4bfdfe72009-06-10 23:11:52 +08003331 gh->msg_type = GSM48_MT_CC_USER_INFO;
3332
3333 /* user-user */
3334 if (user->fields & MNCC_F_USERUSER)
3335 encode_useruser(msg, 1, &user->useruser);
3336 /* more data */
3337 if (user->more)
3338 encode_more(msg);
3339
Harald Welte39e2ead2009-07-23 21:13:03 +02003340 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003341}
3342
3343static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3344{
3345 struct gsm48_hdr *gh = msgb_l3(msg);
3346 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3347 struct tlv_parsed tp;
3348 struct gsm_mncc user;
3349
3350 memset(&user, 0, sizeof(struct gsm_mncc));
3351 user.callref = trans->callref;
3352 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3353 /* user-user */
3354 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3355 user.fields |= MNCC_F_USERUSER;
3356 decode_useruser(&user.useruser,
3357 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3358 }
3359 /* more data */
3360 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3361 user.more = 1;
3362
Harald Welte596fed42009-07-23 19:06:52 +02003363 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003364}
3365
3366static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3367{
3368 struct gsm_mncc *mode = arg;
Harald Welte13cac662009-07-29 12:10:35 +02003369 int rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003370
Harald Welte13cac662009-07-29 12:10:35 +02003371 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3372 if (rc < 0)
3373 return rc;
3374
3375 /* FIXME: we not only need to do this after mode modify, but
3376 * also after channel activation */
3377 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3378 mode->lchan_mode != GSM48_CMODE_SIGN)
3379 rc = rsl_ipacc_bind(trans->lchan);
3380
3381 return rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003382}
3383
3384static struct downstate {
3385 u_int32_t states;
3386 int type;
3387 int (*rout) (struct gsm_trans *trans, void *arg);
3388} downstatelist[] = {
3389 /* mobile originating call establishment */
3390 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3391 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3392 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3393 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3394 {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 */
3395 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3396 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3397 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3398 /* mobile terminating call establishment */
3399 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3400 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3401 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3402 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3403 /* signalling during call */
3404 {SBIT(GSM_CSTATE_ACTIVE),
3405 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3406 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3407 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3408 {ALL_STATES,
3409 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3410 {ALL_STATES,
3411 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3412 {ALL_STATES,
3413 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3414 {SBIT(GSM_CSTATE_ACTIVE),
3415 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3416 {SBIT(GSM_CSTATE_ACTIVE),
3417 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3418 {SBIT(GSM_CSTATE_ACTIVE),
3419 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3420 {SBIT(GSM_CSTATE_ACTIVE),
3421 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3422 {SBIT(GSM_CSTATE_ACTIVE),
3423 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3424 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3425 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3426 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3427 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3428 {SBIT(GSM_CSTATE_ACTIVE),
3429 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3430 /* clearing */
3431 {SBIT(GSM_CSTATE_INITIATED),
3432 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3433 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3434 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3435 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3436 MNCC_REL_REQ, gsm48_cc_tx_release},
3437 /* special */
3438 {ALL_STATES,
3439 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3440};
3441
3442#define DOWNSLLEN \
3443 (sizeof(downstatelist) / sizeof(struct downstate))
3444
3445
3446int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3447{
Harald Welte1a6f7982009-08-09 18:52:33 +02003448 int i, rc = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003449 struct gsm_trans *trans = NULL, *transt;
3450 struct gsm_subscriber *subscr;
Harald Welte1a6f7982009-08-09 18:52:33 +02003451 struct gsm_lchan *lchan = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003452 struct gsm_bts *bts = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003453 struct gsm_mncc *data = arg, rel;
3454
3455 /* handle special messages */
3456 switch(msg_type) {
3457 case MNCC_BRIDGE:
3458 return tch_bridge(net, arg);
3459 case MNCC_FRAME_DROP:
3460 return tch_recv(net, arg, 0);
3461 case MNCC_FRAME_RECV:
3462 return tch_recv(net, arg, 1);
3463 case GSM_TRAU_FRAME:
3464 return tch_frame(net, arg);
3465 }
3466
3467 memset(&rel, 0, sizeof(struct gsm_mncc));
3468 rel.callref = data->callref;
3469
3470 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02003471 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003472
3473 /* Callref unknown */
3474 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003475 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003476 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3477 "Received '%s' from MNCC with "
3478 "unknown callref %d\n", data->called.number,
3479 get_mncc_name(msg_type), data->callref);
3480 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003481 return mncc_release_ind(net, NULL, data->callref,
3482 GSM48_CAUSE_LOC_PRN_S_LU,
3483 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003484 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003485 if (!data->called.number[0] && !data->imsi[0]) {
3486 DEBUGP(DCC, "(bts - trx - ts - ti) "
3487 "Received '%s' from MNCC with "
3488 "no number or IMSI\n", get_mncc_name(msg_type));
3489 /* Invalid number */
3490 return mncc_release_ind(net, NULL, data->callref,
3491 GSM48_CAUSE_LOC_PRN_S_LU,
3492 GSM48_CC_CAUSE_INV_NR_FORMAT);
3493 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003494 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003495 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02003496 subscr = subscr_get_by_extension(net,
3497 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003498 else
Harald Welte9176bd42009-07-23 18:46:00 +02003499 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003500 /* If subscriber is not found */
3501 if (!subscr) {
3502 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3503 "Received '%s' from MNCC with "
3504 "unknown subscriber %s\n", data->called.number,
3505 get_mncc_name(msg_type), data->called.number);
3506 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003507 return mncc_release_ind(net, NULL, data->callref,
3508 GSM48_CAUSE_LOC_PRN_S_LU,
3509 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003510 }
3511 /* If subscriber is not "attached" */
3512 if (!subscr->lac) {
3513 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3514 "Received '%s' from MNCC with "
3515 "detached subscriber %s\n", data->called.number,
3516 get_mncc_name(msg_type), data->called.number);
3517 subscr_put(subscr);
3518 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003519 return mncc_release_ind(net, NULL, data->callref,
3520 GSM48_CAUSE_LOC_PRN_S_LU,
3521 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003522 }
3523 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003524 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3525 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003526 DEBUGP(DCC, "No memory for trans.\n");
3527 subscr_put(subscr);
3528 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003529 mncc_release_ind(net, NULL, data->callref,
3530 GSM48_CAUSE_LOC_PRN_S_LU,
3531 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003532 return -ENOMEM;
3533 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003534 /* Find lchan */
Harald Welte1a6f7982009-08-09 18:52:33 +02003535 lchan = lchan_for_subscr(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003536 /* If subscriber has no lchan */
3537 if (!lchan) {
3538 /* find transaction with this subscriber already paging */
3539 llist_for_each_entry(transt, &net->trans_list, entry) {
3540 /* Transaction of our lchan? */
3541 if (transt == trans ||
3542 transt->subscr != subscr)
3543 continue;
3544 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3545 "Received '%s' from MNCC with "
3546 "unallocated channel, paging already "
3547 "started.\n", bts->nr,
3548 data->called.number,
3549 get_mncc_name(msg_type));
3550 return 0;
3551 }
3552 /* store setup informations until paging was successfull */
Harald Weltedcaf5652009-07-23 18:56:43 +02003553 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Weltea1b28582009-08-01 19:31:47 +02003554 /* Trigger paging */
3555 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3556 setup_trig_pag_evt, subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003557 return 0;
3558 }
3559 /* Assign lchan */
3560 trans->lchan = lchan;
3561 use_lchan(lchan);
3562 }
3563 lchan = trans->lchan;
3564
3565 /* if paging did not respond yet */
3566 if (!lchan) {
3567 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3568 "Received '%s' from MNCC in paging state\n",
3569 (trans->subscr)?(trans->subscr->extension):"-",
3570 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003571 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3572 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003573 if (msg_type == MNCC_REL_REQ)
3574 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3575 else
3576 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3577 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003578 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003579 return rc;
3580 }
3581
3582 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3583 "Received '%s' from MNCC in state %d (%s)\n",
3584 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3585 trans->transaction_id,
3586 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003587 get_mncc_name(msg_type), trans->cc.state,
3588 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003589
3590 /* Find function for current state and message */
3591 for (i = 0; i < DOWNSLLEN; i++)
3592 if ((msg_type == downstatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003593 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003594 break;
3595 if (i == DOWNSLLEN) {
3596 DEBUGP(DCC, "Message unhandled at this state.\n");
3597 return 0;
3598 }
3599
3600 rc = downstatelist[i].rout(trans, arg);
3601
3602 return rc;
3603}
3604
3605
3606static struct datastate {
3607 u_int32_t states;
3608 int type;
3609 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3610} datastatelist[] = {
3611 /* mobile originating call establishment */
3612 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3613 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3614 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3615 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3616 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3617 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3618 /* mobile terminating call establishment */
3619 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3620 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3621 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3622 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3623 {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 */
3624 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3625 /* signalling during call */
3626 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3627 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3628 {SBIT(GSM_CSTATE_ACTIVE),
3629 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3630 {ALL_STATES,
3631 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3632 {ALL_STATES,
3633 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3634 {ALL_STATES,
3635 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3636 {SBIT(GSM_CSTATE_ACTIVE),
3637 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3638 {SBIT(GSM_CSTATE_ACTIVE),
3639 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3640 {SBIT(GSM_CSTATE_ACTIVE),
3641 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3642 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3643 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3644 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3645 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3646 {SBIT(GSM_CSTATE_ACTIVE),
3647 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3648 /* clearing */
3649 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3650 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3651 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3652 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3653 {ALL_STATES, /* 5.4.3.4 */
3654 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3655};
3656
3657#define DATASLLEN \
3658 (sizeof(datastatelist) / sizeof(struct datastate))
3659
Harald Welte4bc90a12008-12-27 16:32:52 +00003660static int gsm0408_rcv_cc(struct msgb *msg)
3661{
3662 struct gsm48_hdr *gh = msgb_l3(msg);
3663 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003664 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003665 struct gsm_lchan *lchan = msg->lchan;
Harald Weltedcaf5652009-07-23 18:56:43 +02003666 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003667 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003668
Harald Welte4bfdfe72009-06-10 23:11:52 +08003669 if (msg_type & 0x80) {
3670 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3671 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003672 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003673
3674 /* Find transaction */
Harald Welteb8b40732009-07-23 21:58:40 +02003675 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltedcaf5652009-07-23 18:56:43 +02003676
Harald Welte6f5aee02009-07-23 21:21:14 +02003677 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003678 "Received '%s' from MS in state %d (%s)\n",
3679 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3680 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003681 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3682 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003683
3684 /* Create transaction */
3685 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003686 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003687 "creating new trans.\n", transaction_id);
3688 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003689 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3690 transaction_id, new_callref++);
3691 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003692 DEBUGP(DCC, "No memory for trans.\n");
3693 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003694 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003695 GSM48_MT_CC_RELEASE_COMPL);
3696 return -ENOMEM;
3697 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003698 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003699 trans->lchan = lchan;
3700 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003701 }
3702
3703 /* find function for current state and message */
3704 for (i = 0; i < DATASLLEN; i++)
3705 if ((msg_type == datastatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003706 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003707 break;
3708 if (i == DATASLLEN) {
3709 DEBUGP(DCC, "Message unhandled at this state.\n");
3710 return 0;
3711 }
3712
3713 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003714
3715 return rc;
3716}
3717
Harald Welte52b1f982008-12-23 20:25:15 +00003718/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
3719int gsm0408_rcvmsg(struct msgb *msg)
3720{
3721 struct gsm48_hdr *gh = msgb_l3(msg);
3722 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003723 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003724
3725 switch (pdisc) {
3726 case GSM48_PDISC_CC:
3727 rc = gsm0408_rcv_cc(msg);
3728 break;
3729 case GSM48_PDISC_MM:
3730 rc = gsm0408_rcv_mm(msg);
3731 break;
3732 case GSM48_PDISC_RR:
3733 rc = gsm0408_rcv_rr(msg);
3734 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003735 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +00003736 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003737 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003738 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003739 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003740 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3741 pdisc);
3742 break;
3743 default:
3744 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3745 pdisc);
3746 break;
3747 }
3748
3749 return rc;
3750}
Harald Welte8470bf22008-12-25 23:28:35 +00003751
Harald Welte8470bf22008-12-25 23:28:35 +00003752/* Section 9.1.8 / Table 9.9 */
3753struct chreq {
3754 u_int8_t val;
3755 u_int8_t mask;
3756 enum chreq_type type;
3757};
3758
3759/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3760static const struct chreq chreq_type_neci1[] = {
3761 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3762 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3763 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3764 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3765 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3766 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3767 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3768 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3769 { 0x10, 0xf0, CHREQ_T_SDCCH },
3770 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3771 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3772 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3773};
3774
3775/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3776static const struct chreq chreq_type_neci0[] = {
3777 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3778 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3779 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3780 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3781 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3782 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3783 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3784 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3785};
3786
3787static const enum gsm_chan_t ctype_by_chreq[] = {
3788 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3789 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3790 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3791 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3792 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3793 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3794 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3795 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3796 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3797 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3798 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3799 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3800};
3801
Harald Weltee14a57c2008-12-29 04:08:28 +00003802static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3803 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3804 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3805 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3806 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3807 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3808 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3809 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3810 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3811 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3812 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3813 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3814 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3815};
3816
Harald Welte8470bf22008-12-25 23:28:35 +00003817enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3818{
3819 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003820 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte8470bf22008-12-25 23:28:35 +00003821
Harald Weltee58ca7c2009-08-10 02:14:46 +02003822 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3823 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte8470bf22008-12-25 23:28:35 +00003824 if ((ra & chr->mask) == chr->val)
3825 return ctype_by_chreq[chr->type];
3826 }
3827 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3828 return GSM_LCHAN_SDCCH;
3829}
Harald Weltee14a57c2008-12-29 04:08:28 +00003830
3831enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3832{
3833 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003834 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Weltee14a57c2008-12-29 04:08:28 +00003835
Harald Weltee58ca7c2009-08-10 02:14:46 +02003836 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3837 const struct chreq *chr = &chreq_type_neci0[i];
Harald Weltee14a57c2008-12-29 04:08:28 +00003838 if ((ra & chr->mask) == chr->val)
3839 return reason_by_chreq[chr->type];
3840 }
3841 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3842 return GSM_CHREQ_REASON_OTHER;
3843}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003844
3845/* dequeue messages to layer 4 */
3846int bsc_upqueue(struct gsm_network *net)
3847{
3848 struct gsm_mncc *mncc;
3849 struct msgb *msg;
3850 int work = 0;
3851
3852 if (net)
3853 while ((msg = msgb_dequeue(&net->upqueue))) {
3854 mncc = (struct gsm_mncc *)msg->data;
3855 if (net->mncc_recv)
3856 net->mncc_recv(net, mncc->msg_type, mncc);
3857 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003858 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003859 }
3860
3861 return work;
3862}
Harald Weltedcaf5652009-07-23 18:56:43 +02003863
Harald Welte805f6442009-07-28 18:25:29 +02003864/*
3865 * This will be ran by the linker when loading the DSO. We use it to
3866 * do system initialization, e.g. registration of signal handlers.
3867 */
3868static __attribute__((constructor)) void on_dso_load_0408(void)
3869{
3870 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3871 "loc_updating_oper");
3872 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3873 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3874}