blob: dc2bd199bb2806c1d1550f9c4afd86846188b857 [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>
Daniel Willmanneea93372009-08-13 03:42:07 +020038#include <openbsc/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000039#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000040#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000041#include <openbsc/gsm_04_08.h>
42#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000043#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000044#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000045#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000046#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000047#include <openbsc/trau_mux.h>
Harald Welte805f6442009-07-28 18:25:29 +020048#include <openbsc/rtp_proxy.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020049#include <openbsc/talloc.h>
Harald Weltedcaf5652009-07-23 18:56:43 +020050#include <openbsc/transaction.h>
Harald Welte52b1f982008-12-23 20:25:15 +000051
Harald Welte8470bf22008-12-25 23:28:35 +000052#define GSM48_ALLOC_SIZE 1024
53#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000054
Harald Welte0c389302009-06-10 12:08:54 +080055#define GSM_MAX_FACILITY 128
56#define GSM_MAX_SSVERSION 128
57#define GSM_MAX_USERUSER 128
58
Harald Welte2cf161b2009-06-20 22:36:41 +020059static void *tall_locop_ctx;
Harald Welte2cf161b2009-06-20 22:36:41 +020060
Harald Welte805f6442009-07-28 18:25:29 +020061/* should ip.access BTS use direct RTP streams between each other (1),
62 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
63int ipacc_rtp_direct = 1;
64
Harald Welte09e38af2009-02-16 22:52:23 +000065static const struct tlv_definition rsl_att_tlvdef = {
66 .def = {
67 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
69 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
70 [GSM48_IE_UTC] = { TLV_TYPE_TV },
71 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
72 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
73
74 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
75 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
76 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
77 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
78 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
79 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
80 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080081 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000082 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
83 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080084 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000086 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
89 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
91 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
92 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
94 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
95 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
96 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
98 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
99 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +0800100 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
101 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +0000102 /* FIXME: more elements */
103 },
104};
Harald Weltecf5b3592009-05-01 18:28:42 +0000105
106static const char *rr_cause_names[] = {
107 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
108 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
109 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
110 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
111 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
112 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
113 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
114 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
115 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
116 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
117 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
118 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
119 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
120 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
121 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
122 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
123 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
124};
125
Harald Welte4bfdfe72009-06-10 23:11:52 +0800126static const char *cc_state_names[] = {
127 "NULL",
128 "INITIATED",
129 "illegal state 2",
130 "MO_CALL_PROC",
131 "CALL_DELIVERED",
132 "illegal state 5",
133 "CALL_PRESENT",
134 "CALL_RECEIVED",
135 "CONNECT_REQUEST",
136 "MO_TERM_CALL_CONF",
137 "ACTIVE",
138 "DISCONNECT_REQ",
139 "DISCONNECT_IND",
140 "illegal state 13",
141 "illegal state 14",
142 "illegal state 15",
143 "illegal state 16",
144 "illegal state 17",
145 "illegal state 18",
146 "RELEASE_REQ",
147 "illegal state 20",
148 "illegal state 21",
149 "illegal state 22",
150 "illegal state 23",
151 "illegal state 24",
152 "illegal state 25",
153 "MO_ORIG_MODIFY",
154 "MO_TERM_MODIFY",
155 "CONNECT_IND",
156 "illegal state 29",
157 "illegal state 30",
158 "illegal state 31",
159};
160
161static const char *cc_msg_names[] = {
162 "unknown 0x00",
163 "ALERTING",
164 "CALL_PROC",
165 "PROGRESS",
166 "ESTAB",
167 "SETUP",
168 "ESTAB_CONF",
169 "CONNECT",
170 "CALL_CONF",
171 "START_CC",
172 "unknown 0x0a",
173 "RECALL",
174 "unknown 0x0c",
175 "unknown 0x0d",
176 "EMERG_SETUP",
177 "CONNECT_ACK",
178 "USER_INFO",
179 "unknown 0x11",
180 "unknown 0x12",
181 "MODIFY_REJECT",
182 "unknown 0x14",
183 "unknown 0x15",
184 "unknown 0x16",
185 "MODIFY",
186 "HOLD",
187 "HOLD_ACK",
188 "HOLD_REJ",
189 "unknown 0x1b",
190 "RETR",
191 "RETR_ACK",
192 "RETR_REJ",
193 "MODIFY_COMPL",
194 "unknown 0x20",
195 "unknown 0x21",
196 "unknown 0x22",
197 "unknown 0x23",
198 "unknown 0x24",
199 "DISCONNECT",
200 "unknown 0x26",
201 "unknown 0x27",
202 "unknown 0x28",
203 "unknown 0x29",
204 "RELEASE_COMPL",
205 "unknown 0x2b",
206 "unknown 0x2c",
207 "RELEASE",
208 "unknown 0x2e",
209 "unknown 0x2f",
210 "unknown 0x30",
211 "STOP_DTMF",
212 "STOP_DTMF_ACK",
213 "unknown 0x33",
214 "STATUS_ENQ",
215 "START_DTMF",
216 "START_DTMF_ACK",
217 "START_DTMF_REJ",
218 "unknown 0x38",
219 "CONG_CTRL",
220 "FACILITY",
221 "unknown 0x3b",
222 "STATUS",
223 "unknown 0x3c",
224 "NOTIFY",
225 "unknown 0x3f",
226};
227
Harald Weltecf5b3592009-05-01 18:28:42 +0000228static char strbuf[64];
229
230static const char *rr_cause_name(u_int8_t cause)
231{
232 if (cause < ARRAY_SIZE(rr_cause_names) &&
233 rr_cause_names[cause])
234 return rr_cause_names[cause];
235
236 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
237 return strbuf;
238}
239
Harald Weltef7c43522009-06-09 20:24:21 +0000240static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
241 int len)
242{
243 memset(rep, 0, sizeof(*rep));
244
245 if (data[0] & 0x80)
246 rep->flags |= MEAS_REP_F_BA1;
247 if (data[0] & 0x40)
248 rep->flags |= MEAS_REP_F_DTX;
Harald Welte5a691b52009-07-05 04:05:44 +0200249 if ((data[1] & 0x40) == 0x00)
Harald Weltef7c43522009-06-09 20:24:21 +0000250 rep->flags |= MEAS_REP_F_VALID;
251
252 rep->rxlev_full = data[0] & 0x3f;
253 rep->rxlev_sub = data[1] & 0x3f;
254 rep->rxqual_full = (data[3] >> 4) & 0x7;
255 rep->rxqual_sub = (data[3] >> 1) & 0x7;
256 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
257 if (rep->num_cell < 1)
258 return;
259
260 /* an encoding nightmare in perfection */
261
262 rep->cell[0].rxlev = data[4] & 0x3f;
263 rep->cell[0].bcch_freq = data[5] >> 2;
264 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
265 if (rep->num_cell < 2)
266 return;
267
268 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
269 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
270 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
271 if (rep->num_cell < 3)
272 return;
273
274 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
275 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
276 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
277 if (rep->num_cell < 4)
278 return;
279
280 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
281 rep->cell[3].bcch_freq = data[11] & 0x1f;
282 rep->cell[3].bsic = data[12] >> 2;
283 if (rep->num_cell < 5)
284 return;
285
286 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
287 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
288 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
289 if (rep->num_cell < 6)
290 return;
291
292 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
293 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
294 rep->cell[5].bsic = data[16] & 0x3f;
295}
296
Holger Freytherd51524f2009-06-09 08:27:07 +0000297int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000298static int gsm48_tx_simple(struct gsm_lchan *lchan,
299 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000300static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte65e74cc2008-12-29 01:55:35 +0000301
Harald Welte52b1f982008-12-23 20:25:15 +0000302struct gsm_lai {
303 u_int16_t mcc;
304 u_int16_t mnc;
305 u_int16_t lac;
306};
307
Holger Freythere97f7fb2008-12-31 18:52:11 +0000308static int reject_cause = 0;
309void gsm0408_set_reject_cause(int cause)
310{
311 reject_cause = cause;
312}
313
Harald Welte4bfdfe72009-06-10 23:11:52 +0800314static u_int32_t new_callref = 0x80000001;
315
Holger Freyther73487a22008-12-31 18:53:57 +0000316static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
317 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000318{
319 if (!subscriber)
320 return 0;
321
Holger Freyther73487a22008-12-31 18:53:57 +0000322 /*
323 * Do not send accept yet as more information should arrive. Some
324 * phones will not send us the information and we will have to check
325 * what we want to do with that.
326 */
327 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
328 return 0;
329
Jan Luebbe06513f22009-08-12 12:48:00 +0200330 switch (subscriber->net->auth_policy) {
331 case GSM_AUTH_POLICY_CLOSED:
332 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200333 case GSM_AUTH_POLICY_TOKEN:
Harald Welte (local)ee9afe32009-08-13 20:44:23 +0200334 if (subscriber->authorized)
335 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200336 return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT);
Jan Luebbe06513f22009-08-12 12:48:00 +0200337 case GSM_AUTH_POLICY_ACCEPT_ALL:
Holger Freyther89824fc2008-12-30 16:18:18 +0000338 return 1;
Jan Luebbe06513f22009-08-12 12:48:00 +0200339 default:
340 return 0;
341 }
Holger Freyther89824fc2008-12-30 16:18:18 +0000342}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000343
Holger Freyther73487a22008-12-31 18:53:57 +0000344static void release_loc_updating_req(struct gsm_lchan *lchan)
345{
Harald Welte179f0642008-12-31 23:59:18 +0000346 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000347 return;
348
Harald Welteff117a82009-05-23 05:22:08 +0000349 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200350 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000351 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000352 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000353}
354
355static void allocate_loc_updating_req(struct gsm_lchan *lchan)
356{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000357 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000358 release_loc_updating_req(lchan);
359
Harald Welte470ec292009-06-26 20:25:23 +0200360 lchan->loc_operation = talloc_zero(tall_locop_ctx,
361 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000362}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000363
Holger Freytherd51524f2009-06-09 08:27:07 +0000364static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
365{
366 u_int32_t tmsi;
367
368 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welteee5ad162009-08-09 19:07:00 +0200369 int rc;
370
Holger Freytherd51524f2009-06-09 08:27:07 +0000371 db_subscriber_alloc_tmsi(lchan->subscr);
Holger Freytherd51524f2009-06-09 08:27:07 +0000372 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
373 release_loc_updating_req(lchan);
Harald Welteee5ad162009-08-09 19:07:00 +0200374 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
375 /* call subscr_update after putting the loc_upd_acc
376 * in the transmit queue, since S_SUBSCR_ATTACHED might
377 * trigger further action like SMS delivery */
378 subscr_update(lchan->subscr, msg->trx->bts,
379 GSM_SUBSCRIBER_UPDATE_ATTACHED);
380 return rc;
Holger Freytherd51524f2009-06-09 08:27:07 +0000381 }
382
383 return 0;
384}
385
Holger Freyther7c19f742009-06-06 13:54:35 +0000386static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
387 void *handler_data, void *signal_data)
388{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800389 struct gsm_trans *trans, *temp;
390
Holger Freyther7c19f742009-06-06 13:54:35 +0000391 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
392 return 0;
393
394 /*
395 * Cancel any outstanding location updating request
396 * operation taking place on the lchan.
397 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200398 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200399 if (!lchan)
400 return 0;
401
Holger Freyther7c19f742009-06-06 13:54:35 +0000402 release_loc_updating_req(lchan);
403
Harald Welte4bfdfe72009-06-10 23:11:52 +0800404 /* Free all transactions that are associated with the released lchan */
Harald Weltedcaf5652009-07-23 18:56:43 +0200405 /* FIXME: this is not neccessarily the right thing to do, we should
406 * only set trans->lchan to NULL and wait for another lchan to be
407 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800408 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
409 if (trans->lchan == lchan)
Harald Weltedcaf5652009-07-23 18:56:43 +0200410 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800411 }
412
Holger Freyther7c19f742009-06-06 13:54:35 +0000413 return 0;
414}
415
Harald Welte52b1f982008-12-23 20:25:15 +0000416static void to_bcd(u_int8_t *bcd, u_int16_t val)
417{
Harald Welte4b634542008-12-27 01:55:51 +0000418 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000419 val = val / 10;
420 bcd[1] = val % 10;
421 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000422 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000423 val = val / 10;
424}
425
Holger Freyther17746612008-12-28 16:32:44 +0000426void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000427 u_int16_t mnc, u_int16_t lac)
428{
429 u_int8_t bcd[3];
430
431 to_bcd(bcd, mcc);
432 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
433 lai48->digits[1] = bcd[2];
434
435 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000436 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
437#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000438 lai48->digits[1] |= bcd[2] << 4;
439 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000440#else
441 lai48->digits[1] |= 0xf << 4;
442 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
443#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000444
Harald Welte4b634542008-12-27 01:55:51 +0000445 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000446}
447
Harald Welte255539c2008-12-28 02:26:27 +0000448#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000449#define MID_TMSI_LEN (TMSI_LEN + 2)
450
Harald Welte255539c2008-12-28 02:26:27 +0000451int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000452{
Harald Welte65e74cc2008-12-29 01:55:35 +0000453 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000454
Harald Welte4b634542008-12-27 01:55:51 +0000455 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000456 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000457 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000458 *tptr = htonl(tmsi);
459
460 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000461}
462
Harald Welte09e38af2009-02-16 22:52:23 +0000463static const char bcd_num_digits[] = {
464 '0', '1', '2', '3', '4', '5', '6', '7',
465 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
466};
467
Harald Welte0c389302009-06-10 12:08:54 +0800468/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
469int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
470 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000471{
472 u_int8_t in_len = bcd_lv[0];
473 int i;
474
Harald Welte0c389302009-06-10 12:08:54 +0800475 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000476 /* lower nibble */
477 output_len--;
478 if (output_len <= 1)
479 break;
480 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
481
482 /* higher nibble */
483 output_len--;
484 if (output_len <= 1)
485 break;
486 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
487 }
488 if (output_len >= 1)
489 *output++ = '\0';
490
Harald Welte0c389302009-06-10 12:08:54 +0800491 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000492}
493
494/* convert a single ASCII character to call-control BCD */
495static int asc_to_bcd(const char asc)
496{
497 int i;
498
499 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
500 if (bcd_num_digits[i] == asc)
501 return i;
502 }
503 return -EINVAL;
504}
505
Harald Welte0c389302009-06-10 12:08:54 +0800506/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000507int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800508 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000509{
510 int in_len = strlen(input);
511 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800512 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000513
514 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800515 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000516 if (in_len % 2)
517 bcd_lv[0]++;
518
Harald Welte0c389302009-06-10 12:08:54 +0800519 if (bcd_lv[0] > max_len)
520 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000521
522 for (i = 0; i < in_len; i++) {
523 int rc = asc_to_bcd(input[i]);
524 if (rc < 0)
525 return rc;
526 if (i % 2 == 0)
527 *bcd_cur = rc;
528 else
529 *bcd_cur++ |= (rc << 4);
530 }
531 /* append padding nibble in case of odd length */
532 if (i % 2)
533 *bcd_cur++ |= 0xf0;
534
535 /* return how many bytes we used */
536 return (bcd_cur - bcd_lv);
537}
538
Harald Welte0c389302009-06-10 12:08:54 +0800539/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800540static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800541 const u_int8_t *lv)
542{
543 u_int8_t in_len = lv[0];
544 int i, s;
545
546 if (in_len < 1)
547 return -EINVAL;
548
Harald Welte4bfdfe72009-06-10 23:11:52 +0800549 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800550
551 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800552 bcap->transfer = lv[1] & 0x07;
553 bcap->mode = (lv[1] & 0x08) >> 3;
554 bcap->coding = (lv[1] & 0x10) >> 4;
555 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800556
557 i = 1;
558 s = 0;
559 while(!(lv[i] & 0x80)) {
560 i++; /* octet 3a etc */
561 if (in_len < i)
562 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800563 bcap->speech_ver[s++] = lv[i] & 0x0f;
564 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800565 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800566 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800567 if (s == 7) /* maximum speech versions + end of list */
568 return 0;
569 }
570
571 return 0;
572}
573
574/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800575static int encode_bearer_cap(struct msgb *msg, int lv_only,
576 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800577{
578 u_int8_t lv[32 + 1];
579 int i, s;
580
Harald Welte4bfdfe72009-06-10 23:11:52 +0800581 lv[1] = bcap->transfer;
582 lv[1] |= bcap->mode << 3;
583 lv[1] |= bcap->coding << 4;
584 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800585
586 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800588 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800589 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800590 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800591 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800592 }
593 lv[i] |= 0x80; /* last IE of octet 3 etc */
594
595 lv[0] = i;
596 if (lv_only)
597 msgb_lv_put(msg, lv[0], lv+1);
598 else
599 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
600
601 return 0;
602}
603
604/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800605static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800606{
607 u_int8_t in_len = lv[0];
608
609 if (in_len < 1)
610 return -EINVAL;
611
612 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800613 ccap->dtmf = lv[1] & 0x01;
614 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800615
616 return 0;
617}
618
619/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800620static int decode_called(struct gsm_mncc_number *called,
621 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800622{
623 u_int8_t in_len = lv[0];
624
625 if (in_len < 1)
626 return -EINVAL;
627
628 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800629 called->plan = lv[1] & 0x0f;
630 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800631
632 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800633 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800634
635 return 0;
636}
637
638/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800639static int encode_called(struct msgb *msg,
640 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800641{
642 u_int8_t lv[18];
643 int ret;
644
645 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800646 lv[1] = called->plan;
647 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800648
649 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800650 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800651 if (ret < 0)
652 return ret;
653
654 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
655
656 return 0;
657}
658
659/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800660static int encode_callerid(struct msgb *msg, int ie,
661 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800662{
663 u_int8_t lv[13];
664 int h_len = 1;
665 int ret;
666
667 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800668 lv[1] = callerid->plan;
669 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800670
Harald Welte4bfdfe72009-06-10 23:11:52 +0800671 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800672 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800673 lv[2] = callerid->screen;
674 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800675 lv[2] |= 0x80;
676 h_len++;
677 } else
678 lv[1] |= 0x80;
679
680 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800681 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800682 if (ret < 0)
683 return ret;
684
685 msgb_tlv_put(msg, ie, lv[0], lv+1);
686
687 return 0;
688}
689
690/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800691static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800692 const u_int8_t *lv)
693{
694 u_int8_t in_len = lv[0];
695 int i;
696
697 if (in_len < 2)
698 return -EINVAL;
699
Harald Welte4bfdfe72009-06-10 23:11:52 +0800700 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800701
702 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800703 cause->location = lv[1] & 0x0f;
704 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800705
706 i = 1;
707 if (!(lv[i] & 0x80)) {
708 i++; /* octet 3a */
709 if (in_len < i+1)
710 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800711 cause->rec = 1;
712 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800713
714 }
715 i++;
716
717 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800718 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800719 i++;
720
721 if (in_len < i) /* no diag */
722 return 0;
723
724 if (in_len - (i-1) > 32) /* maximum 32 octets */
725 return 0;
726
727 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800728 memcpy(cause->diag, lv + i, in_len - (i-1));
729 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800730
731 return 0;
732}
733
734/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800735static int encode_cause(struct msgb *msg, int lv_only,
736 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800737{
738 u_int8_t lv[32+4];
739 int i;
740
Harald Welte4bfdfe72009-06-10 23:11:52 +0800741 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800742 return -EINVAL;
743
744 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 lv[1] = cause->location;
746 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800747
748 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800749 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800750 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800751 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800752 }
753 lv[i] |= 0x80; /* end of octet 3 */
754
755 /* octet 4 */
756 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800757 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800758
759 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800760 if (cause->diag_len) {
761 memcpy(lv + i, cause->diag, cause->diag_len);
762 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800763 }
764
765 lv[0] = i;
766 if (lv_only)
767 msgb_lv_put(msg, lv[0], lv+1);
768 else
769 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
770
771 return 0;
772}
773
774/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800775static int encode_calling(struct msgb *msg,
776 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800777{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800778 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800779}
780
781/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800782static int encode_connected(struct msgb *msg,
783 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800784{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800785 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800786}
787
788/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800789static int encode_redirecting(struct msgb *msg,
790 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800791{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800792 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800793}
794
795/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800796static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800797 const u_int8_t *lv)
798{
799 u_int8_t in_len = lv[0];
800
801 if (in_len < 1)
802 return -EINVAL;
803
Harald Welte4bfdfe72009-06-10 23:11:52 +0800804 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800805 return -EINVAL;
806
Harald Welte4bfdfe72009-06-10 23:11:52 +0800807 memcpy(facility->info, lv+1, in_len);
808 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800809
810 return 0;
811}
812
813/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800814static int encode_facility(struct msgb *msg, int lv_only,
815 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800816{
817 u_int8_t lv[GSM_MAX_FACILITY + 1];
818
Harald Welte4bfdfe72009-06-10 23:11:52 +0800819 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800820 return -EINVAL;
821
Harald Welte4bfdfe72009-06-10 23:11:52 +0800822 memcpy(lv+1, facility->info, facility->len);
823 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800824 if (lv_only)
825 msgb_lv_put(msg, lv[0], lv+1);
826 else
827 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
828
829 return 0;
830}
831
832/* decode 'notify' */
833static int decode_notify(int *notify, const u_int8_t *v)
834{
835 *notify = v[0] & 0x7f;
836
837 return 0;
838}
839
840/* encode 'notify' */
841static int encode_notify(struct msgb *msg, int notify)
842{
843 msgb_v_put(msg, notify | 0x80);
844
845 return 0;
846}
847
848/* encode 'signal' */
849static int encode_signal(struct msgb *msg, int signal)
850{
851 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
852
853 return 0;
854}
855
856/* decode 'keypad' */
857static int decode_keypad(int *keypad, const u_int8_t *lv)
858{
859 u_int8_t in_len = lv[0];
860
861 if (in_len < 1)
862 return -EINVAL;
863
864 *keypad = lv[1] & 0x7f;
865
866 return 0;
867}
868
869/* encode 'keypad' */
870static int encode_keypad(struct msgb *msg, int keypad)
871{
872 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
873
874 return 0;
875}
876
877/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800878static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800879 const u_int8_t *lv)
880{
881 u_int8_t in_len = lv[0];
882
883 if (in_len < 2)
884 return -EINVAL;
885
Harald Welte4bfdfe72009-06-10 23:11:52 +0800886 progress->coding = (lv[1] & 0x60) >> 5;
887 progress->location = lv[1] & 0x0f;
888 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800889
890 return 0;
891}
892
893/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800894static int encode_progress(struct msgb *msg, int lv_only,
895 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800896{
897 u_int8_t lv[3];
898
899 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800900 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
901 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800902 if (lv_only)
903 msgb_lv_put(msg, lv[0], lv+1);
904 else
905 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
906
907 return 0;
908}
909
910/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800911static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800912 const u_int8_t *lv)
913{
914 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800915 char *info = uu->info;
916 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800917 int i;
918
919 if (in_len < 1)
920 return -EINVAL;
921
Harald Welte4bfdfe72009-06-10 23:11:52 +0800922 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800923
924 for (i = 2; i <= in_len; i++) {
925 info_len--;
926 if (info_len <= 1)
927 break;
928 *info++ = lv[i];
929 }
930 if (info_len >= 1)
931 *info++ = '\0';
932
933 return 0;
934}
935
936/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800937static int encode_useruser(struct msgb *msg, int lv_only,
938 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800939{
940 u_int8_t lv[GSM_MAX_USERUSER + 2];
941
Harald Welte4bfdfe72009-06-10 23:11:52 +0800942 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800943 return -EINVAL;
944
Harald Welte4bfdfe72009-06-10 23:11:52 +0800945 lv[0] = 1 + strlen(uu->info);
946 lv[1] = uu->proto;
947 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800948 if (lv_only)
949 msgb_lv_put(msg, lv[0], lv+1);
950 else
951 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
952
953 return 0;
954}
955
956/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800957static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800958 const u_int8_t *lv)
959{
960 u_int8_t in_len = lv[0];
961
Harald Welte4bfdfe72009-06-10 23:11:52 +0800962 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800963 return -EINVAL;
964
Harald Welte4bfdfe72009-06-10 23:11:52 +0800965 memcpy(ssv->info, lv + 1, in_len);
966 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800967
968 return 0;
969}
970
971/* encode 'more data' */
972static int encode_more(struct msgb *msg)
973{
974 u_int8_t *ie;
975
976 ie = msgb_put(msg, 1);
977 ie[0] = GSM48_IE_MORE_DATA;
978
979 return 0;
980}
981
Holger Freyther819dd202009-01-04 03:52:50 +0000982struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000983{
Harald Welte966636f2009-06-26 19:39:35 +0200984 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
985 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000986}
987
Harald Welte39e2ead2009-07-23 21:13:03 +0200988int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000989{
Harald Welte39e2ead2009-07-23 21:13:03 +0200990 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
991
992 /* if we get passed a transaction reference, do some common
993 * work that the caller no longer has to do */
994 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200995 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200996 msg->lchan = trans->lchan;
997 }
998
Harald Welte65e74cc2008-12-29 01:55:35 +0000999 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +00001000 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +00001001
Harald Welte4bfdfe72009-06-10 23:11:52 +08001002 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1003 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1004 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1005 msg->trx->nr, msg->lchan->ts->nr,
1006 gh->proto_discr & 0xf0,
1007 cc_msg_names[gh->msg_type & 0x3f]);
1008 else
1009 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1010 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1011 msg->trx->nr, msg->lchan->ts->nr,
1012 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001013 }
1014
Harald Welte4b634542008-12-27 01:55:51 +00001015 msg->l3h = msg->data;
1016
Harald Welte8470bf22008-12-25 23:28:35 +00001017 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001018}
1019
Holger Freyther429e7762008-12-30 13:28:30 +00001020/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001021int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001022{
Harald Welte8470bf22008-12-25 23:28:35 +00001023 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001024 struct gsm48_hdr *gh;
1025
Harald Welte8470bf22008-12-25 23:28:35 +00001026 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001027
1028 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1029 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001030 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001031 gh->data[0] = cause;
1032
Harald Weltedb253af2008-12-30 17:56:55 +00001033 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1034
Harald Welte39e2ead2009-07-23 21:13:03 +02001035 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001036}
1037
1038/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001039int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001040{
Harald Welte8470bf22008-12-25 23:28:35 +00001041 struct gsm_bts *bts = lchan->ts->trx->bts;
1042 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001043 struct gsm48_hdr *gh;
1044 struct gsm48_loc_area_id *lai;
1045 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001046 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001047
Harald Welte8470bf22008-12-25 23:28:35 +00001048 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001049
1050 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1051 gh->proto_discr = GSM48_PDISC_MM;
1052 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1053
1054 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001055 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001056 bts->network->network_code, bts->location_area_code);
1057
1058 mid = msgb_put(msg, MID_TMSI_LEN);
1059 generate_mid_from_tmsi(mid, tmsi);
1060
1061 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1062
Harald Welte39e2ead2009-07-23 21:13:03 +02001063 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001064
Harald Welteee5ad162009-08-09 19:07:00 +02001065 /* send MM INFO with network name */
Harald Weltedb253af2008-12-30 17:56:55 +00001066 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001067
Holger Freyther07cc8d82008-12-29 06:23:46 +00001068 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001069}
1070
Harald Weltefc977a82008-12-27 10:19:37 +00001071static char bcd2char(u_int8_t bcd)
1072{
1073 if (bcd < 0xa)
1074 return '0' + bcd;
1075 else
1076 return 'A' + (bcd - 0xa);
1077}
1078
Harald Weltebf5e8df2009-02-03 12:59:45 +00001079/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001080static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1081{
1082 int i;
1083 u_int8_t mi_type;
1084 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001085 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001086
1087 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1088
1089 switch (mi_type) {
1090 case GSM_MI_TYPE_NONE:
1091 break;
1092 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001093 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1094 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1095 memcpy(&tmsi, &mi[1], 4);
1096 tmsi = ntohl(tmsi);
1097 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001098 }
1099 break;
1100 case GSM_MI_TYPE_IMSI:
1101 case GSM_MI_TYPE_IMEI:
1102 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001103 *str_cur++ = bcd2char(mi[0] >> 4);
1104
1105 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001106 if (str_cur + 2 >= string + str_len)
1107 return str_cur - string;
1108 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001109 /* skip last nibble in last input byte when GSM_EVEN */
1110 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1111 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001112 }
1113 break;
1114 default:
1115 break;
1116 }
Harald Weltefc977a82008-12-27 10:19:37 +00001117 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001118
Harald Weltefc977a82008-12-27 10:19:37 +00001119 return str_cur - string;
1120}
1121
Harald Weltebf5e8df2009-02-03 12:59:45 +00001122/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001123static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1124{
1125 struct msgb *msg = gsm48_msgb_alloc();
1126 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001127
Harald Welte231ad4f2008-12-27 11:15:38 +00001128 msg->lchan = lchan;
1129
1130 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1131 gh->proto_discr = GSM48_PDISC_MM;
1132 gh->msg_type = GSM48_MT_MM_ID_REQ;
1133 gh->data[0] = id_type;
1134
Harald Welte39e2ead2009-07-23 21:13:03 +02001135 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001136}
1137
1138#define MI_SIZE 32
1139
Harald Weltebf5e8df2009-02-03 12:59:45 +00001140/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001141static int mm_rx_id_resp(struct msgb *msg)
1142{
1143 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001144 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001145 struct gsm_bts *bts = lchan->ts->trx->bts;
1146 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001147 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1148 char mi_string[MI_SIZE];
1149
1150 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001151 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001152 mi_type, mi_string);
1153
Harald Welte75a983f2008-12-27 21:34:06 +00001154 switch (mi_type) {
1155 case GSM_MI_TYPE_IMSI:
Jan Luebbe370b41d2009-08-12 10:19:34 +02001156 /* look up subscriber based on IMSI, create if not found */
1157 if (!lchan->subscr) {
1158 lchan->subscr = subscr_get_by_imsi(net, mi_string);
Harald Welte (local)aa9dc192009-08-13 13:49:51 +02001159 if (!lchan->subscr)
1160 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001161 }
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 }
Harald Welte4b634542008-12-27 01:55:51 +00001257 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001258 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001259 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001260 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001261 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001262 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001263
Harald Welte52b1f982008-12-23 20:25:15 +00001264 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte9176bd42009-07-23 18:46:00 +02001265 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001266 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001267 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001268 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001269 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001270 }
1271 break;
1272 case GSM_MI_TYPE_IMEI:
1273 case GSM_MI_TYPE_IMEISV:
1274 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001275 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001276 break;
1277 default:
Harald Weltea0368542009-06-27 02:58:43 +02001278 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001279 break;
1280 }
1281
Harald Welte24516ea2009-07-04 10:18:00 +02001282 /* schedule the reject timer */
1283 schedule_reject(lchan);
1284
Harald Welte4bfdfe72009-06-10 23:11:52 +08001285 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001286 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001287 /* FIXME: request id? close channel? */
1288 return -EINVAL;
1289 }
1290
Harald Welte255539c2008-12-28 02:26:27 +00001291 lchan->subscr = subscr;
1292
Harald Welte24516ea2009-07-04 10:18:00 +02001293 /* check if we can let the subscriber into our network immediately
1294 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001295 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001296}
1297
Harald Welte13cac662009-07-29 12:10:35 +02001298/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte7584aea2009-02-11 11:44:12 +00001299int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1300{
1301 struct msgb *msg = gsm48_msgb_alloc();
1302 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1303 struct gsm48_chan_mode_modify *cmm =
1304 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001305 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001306
Harald Welte4a543e82009-02-28 13:17:55 +00001307 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001308
Harald Welte45b407a2009-05-23 15:51:12 +00001309 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001310 msg->lchan = lchan;
1311 gh->proto_discr = GSM48_PDISC_RR;
1312 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1313
1314 /* fill the channel information element, this code
1315 * should probably be shared with rsl_rx_chan_rqd() */
1316 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001317 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001318 cmm->chan_desc.h0.h = 0;
1319 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1320 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1321 cmm->mode = mode;
1322
Harald Welte39e2ead2009-07-23 21:13:03 +02001323 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001324}
1325
Harald Welte4bfdfe72009-06-10 23:11:52 +08001326#if 0
1327static u_int8_t to_bcd8(u_int8_t val)
1328{
1329 return ((val / 10) << 4) | (val % 10);
1330}
1331#endif
1332
Harald Weltedb253af2008-12-30 17:56:55 +00001333/* Section 9.2.15a */
1334int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1335{
1336 struct msgb *msg = gsm48_msgb_alloc();
1337 struct gsm48_hdr *gh;
1338 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001339 u_int8_t *ptr8;
1340 u_int16_t *ptr16;
Daniel Willmanneea93372009-08-13 03:42:07 +02001341 int name_len, name_pad;
Harald Weltedb253af2008-12-30 17:56:55 +00001342 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001343#if 0
1344 time_t cur_t;
1345 struct tm* cur_time;
1346 int tz15min;
1347#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001348
1349 msg->lchan = lchan;
1350
1351 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1352 gh->proto_discr = GSM48_PDISC_MM;
1353 gh->msg_type = GSM48_MT_MM_INFO;
1354
1355 if (net->name_long) {
Daniel Willmanneea93372009-08-13 03:42:07 +02001356#if 0
Harald Weltedb253af2008-12-30 17:56:55 +00001357 name_len = strlen(net->name_long);
1358 /* 10.5.3.5a */
1359 ptr8 = msgb_put(msg, 3);
1360 ptr8[0] = GSM48_IE_NAME_LONG;
1361 ptr8[1] = name_len*2 +1;
1362 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1363
1364 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1365 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001366 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001367
1368 /* FIXME: Use Cell Broadcast, not UCS-2, since
1369 * UCS-2 is only supported by later revisions of the spec */
Daniel Willmanneea93372009-08-13 03:42:07 +02001370#endif
1371 name_len = (strlen(net->name_long)*7)/8;
1372 name_pad = (8 - strlen(net->name_long)*7)%8;
1373 if (name_pad > 0)
1374 name_len++;
1375 /* 10.5.3.5a */
1376 ptr8 = msgb_put(msg, 3);
1377 ptr8[0] = GSM48_IE_NAME_LONG;
1378 ptr8[1] = name_len +1;
1379 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1380
1381 ptr8 = msgb_put(msg, name_len);
1382 gsm_7bit_encode(ptr8, net->name_long);
1383
Harald Weltedb253af2008-12-30 17:56:55 +00001384 }
1385
1386 if (net->name_short) {
Daniel Willmanneea93372009-08-13 03:42:07 +02001387#if 0
Harald Weltedb253af2008-12-30 17:56:55 +00001388 name_len = strlen(net->name_short);
1389 /* 10.5.3.5a */
1390 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001391 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001392 ptr8[1] = name_len*2 + 1;
1393 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1394
Harald Weltee872cb12009-01-01 00:33:37 +00001395 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001396 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001397 ptr16[i] = htons(net->name_short[i]);
Daniel Willmanneea93372009-08-13 03:42:07 +02001398#endif
1399 name_len = (strlen(net->name_short)*7)/8;
1400 name_pad = (8 - strlen(net->name_short)*7)%8;
1401 if (name_pad > 0)
1402 name_len++;
1403 /* 10.5.3.5a */
1404 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1405 ptr8[0] = GSM48_IE_NAME_SHORT;
1406 ptr8[1] = name_len +1;
1407 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1408
1409 ptr8 = msgb_put(msg, name_len);
1410 gsm_7bit_encode(ptr8, net->name_short);
1411
Harald Weltedb253af2008-12-30 17:56:55 +00001412 }
1413
1414#if 0
1415 /* Section 10.5.3.9 */
1416 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001417 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001418 ptr8 = msgb_put(msg, 8);
1419 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1420 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1421 ptr8[2] = to_bcd8(cur_time->tm_mon);
1422 ptr8[3] = to_bcd8(cur_time->tm_mday);
1423 ptr8[4] = to_bcd8(cur_time->tm_hour);
1424 ptr8[5] = to_bcd8(cur_time->tm_min);
1425 ptr8[6] = to_bcd8(cur_time->tm_sec);
1426 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1427 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001428 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001429 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001430 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001431#endif
1432
Daniel Willmanneea93372009-08-13 03:42:07 +02001433 DEBUGP(DMM, "-> MM INFO\n");
1434
Harald Welte39e2ead2009-07-23 21:13:03 +02001435 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001436}
1437
Harald Welte7984d5c2009-08-12 22:56:50 +02001438/* Section 9.2.2 */
1439int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
1440{
1441 struct msgb *msg = gsm48_msgb_alloc();
1442 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1443 u_int8_t *r;
1444
1445 DEBUGP(DMM, "-> AUTH REQ\n");
1446
1447 msg->lchan = lchan;
1448 gh->proto_discr = GSM48_PDISC_MM;
1449 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
1450
1451 /* 16 bytes RAND parameters */
1452 r = msgb_put(msg, 16);
1453 if (rand)
1454 memcpy(r, rand, 16);
1455
1456 return gsm48_sendmsg(msg, NULL);
1457}
1458
1459/* Section 9.2.1 */
1460int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
1461{
1462 DEBUGP(DMM, "-> AUTH REJECT\n");
1463 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
1464}
1465
Harald Welte4b634542008-12-27 01:55:51 +00001466static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1467{
Harald Welte4b634542008-12-27 01:55:51 +00001468 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001469 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001470}
Harald Welteba4cf162009-01-10 01:49:35 +00001471
1472/* 9.2.6 CM service reject */
1473static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1474 enum gsm48_reject_value value)
1475{
1476 struct msgb *msg = gsm48_msgb_alloc();
1477 struct gsm48_hdr *gh;
1478
1479 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1480
1481 msg->lchan = lchan;
1482 use_lchan(lchan);
1483
1484 gh->proto_discr = GSM48_PDISC_MM;
1485 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1486 gh->data[0] = value;
1487 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1488
Harald Welte39e2ead2009-07-23 21:13:03 +02001489 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001490}
1491
Harald Welte3ac7f102009-08-10 10:12:45 +02001492static int send_siemens_mrpci(struct gsm_lchan *lchan,
1493 u_int8_t *classmark2_lv)
1494{
1495 struct rsl_mrpci mrpci;
1496
1497 if (classmark2_lv[0] < 2)
1498 return -EINVAL;
1499
1500 mrpci.power_class = classmark2_lv[1] & 0x7;
1501 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1502 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1503 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1504
1505 return rsl_siemens_mrpci(lchan, &mrpci);
1506}
Harald Welte4ed0e922009-01-10 03:17:30 +00001507
1508/*
1509 * Handle CM Service Requests
1510 * a) Verify that the packet is long enough to contain the information
1511 * we require otherwsie reject with INCORRECT_MESSAGE
1512 * b) Try to parse the TMSI. If we do not have one reject
1513 * c) Check that we know the subscriber with the TMSI otherwise reject
1514 * with a HLR cause
1515 * d) Set the subscriber on the gsm_lchan and accept
1516 */
Harald Welte4b634542008-12-27 01:55:51 +00001517static int gsm48_rx_mm_serv_req(struct msgb *msg)
1518{
Harald Welteba4cf162009-01-10 01:49:35 +00001519 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001520 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001521
Harald Welte9176bd42009-07-23 18:46:00 +02001522 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001523 struct gsm_subscriber *subscr;
1524 struct gsm48_hdr *gh = msgb_l3(msg);
1525 struct gsm48_service_request *req =
1526 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001527 /* unfortunately in Phase1 the classmar2 length is variable */
1528 u_int8_t classmark2_len = gh->data[1];
1529 u_int8_t *classmark2 = gh->data+2;
1530 u_int8_t mi_len = *(classmark2 + classmark2_len);
1531 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001532
Harald Weltec9e02182009-05-01 19:07:53 +00001533 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001534 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001535 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001536 return gsm48_tx_mm_serv_rej(msg->lchan,
1537 GSM48_REJECT_INCORRECT_MESSAGE);
1538 }
1539
1540 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001541 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001542 return gsm48_tx_mm_serv_rej(msg->lchan,
1543 GSM48_REJECT_INCORRECT_MESSAGE);
1544 }
1545
Harald Weltec9e02182009-05-01 19:07:53 +00001546 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001547 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001548 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001549 return gsm48_tx_mm_serv_rej(msg->lchan,
1550 GSM48_REJECT_INCORRECT_MESSAGE);
1551 }
1552
Harald Weltec9e02182009-05-01 19:07:53 +00001553 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001554 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001555 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001556
Harald Welte3ac7f102009-08-10 10:12:45 +02001557 if (is_siemens_bts(bts))
1558 send_siemens_mrpci(msg->lchan, classmark2-1);
1559
Harald Welte9176bd42009-07-23 18:46:00 +02001560 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001561
Harald Welte2a139372009-02-22 21:14:55 +00001562 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001563 if (!subscr)
1564 return gsm48_tx_mm_serv_rej(msg->lchan,
1565 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1566
1567 if (!msg->lchan->subscr)
1568 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001569 else if (msg->lchan->subscr != subscr) {
1570 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1571 subscr_put(subscr);
1572 }
1573
Harald Weltec2e302d2009-07-05 14:08:13 +02001574 subscr->equipment.classmark2_len = classmark2_len;
1575 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1576 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001577
Harald Welte4b634542008-12-27 01:55:51 +00001578 return gsm48_tx_mm_serv_ack(msg->lchan);
1579}
1580
Harald Welte2a139372009-02-22 21:14:55 +00001581static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1582{
Harald Welte9176bd42009-07-23 18:46:00 +02001583 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001584 struct gsm48_hdr *gh = msgb_l3(msg);
1585 struct gsm48_imsi_detach_ind *idi =
1586 (struct gsm48_imsi_detach_ind *) gh->data;
1587 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1588 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001589 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001590
1591 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1592 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1593 mi_type, mi_string);
1594
1595 switch (mi_type) {
1596 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001597 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001598 break;
1599 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001600 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001601 break;
1602 case GSM_MI_TYPE_IMEI:
1603 case GSM_MI_TYPE_IMEISV:
1604 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001605 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001606 break;
1607 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001608 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001609 break;
1610 }
1611
Holger Freyther4a49e772009-04-12 05:37:29 +00001612 if (subscr) {
1613 subscr_update(subscr, msg->trx->bts,
1614 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001615 DEBUGP(DMM, "Subscriber: %s\n",
1616 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001617 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001618 } else
Harald Welte2a139372009-02-22 21:14:55 +00001619 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1620
Harald Welte2a139372009-02-22 21:14:55 +00001621 return 0;
1622}
1623
Harald Welted2a7f5a2009-06-05 20:08:20 +00001624static int gsm48_rx_mm_status(struct msgb *msg)
1625{
1626 struct gsm48_hdr *gh = msgb_l3(msg);
1627
1628 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1629
1630 return 0;
1631}
1632
Harald Weltebf5e8df2009-02-03 12:59:45 +00001633/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001634static int gsm0408_rcv_mm(struct msgb *msg)
1635{
1636 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001637 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001638
1639 switch (gh->msg_type & 0xbf) {
1640 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001641 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001642 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001643 break;
1644 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001645 rc = mm_rx_id_resp(msg);
1646 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001647 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001648 rc = gsm48_rx_mm_serv_req(msg);
1649 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001650 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001651 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001652 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001653 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001654 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1655 msg->lchan->subscr ?
1656 msg->lchan->subscr->imsi :
1657 "unknown subscriber");
1658 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001659 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001660 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1661 break;
1662 case GSM48_MT_MM_CM_REEST_REQ:
1663 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1664 break;
1665 case GSM48_MT_MM_AUTH_RESP:
1666 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001667 break;
1668 default:
1669 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1670 gh->msg_type);
1671 break;
1672 }
1673
1674 return rc;
1675}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001676
Harald Welte2d35ae62009-02-06 12:02:13 +00001677/* Receive a PAGING RESPONSE message from the MS */
1678static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1679{
Harald Welte9176bd42009-07-23 18:46:00 +02001680 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001681 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001682 u_int8_t *classmark2_lv = gh->data + 1;
1683 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1684 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001685 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001686 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001687 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001688 int rc = 0;
1689
Harald Welte61548982009-02-22 21:26:29 +00001690 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001691 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1692 mi_type, mi_string);
Harald Welte3ac7f102009-08-10 10:12:45 +02001693
1694 if (is_siemens_bts(bts))
1695 send_siemens_mrpci(msg->lchan, classmark2_lv);
1696
Harald Weltefe18d8f2009-02-22 21:14:24 +00001697 switch (mi_type) {
1698 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001699 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001700 break;
1701 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001702 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001703 break;
1704 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001705
1706 if (!subscr) {
1707 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001708 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001709 return -EINVAL;
1710 }
1711 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte76042182009-08-08 16:03:15 +02001712 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001713
Harald Weltec2e302d2009-07-05 14:08:13 +02001714 subscr->equipment.classmark2_len = *classmark2_lv;
1715 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1716 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001717
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001718 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001719 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001720 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001721 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1722 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001723 return -EINVAL;
1724 } else {
1725 DEBUGP(DRR, "<- Channel already owned by us\n");
1726 subscr_put(subscr);
1727 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001728 }
1729
Harald Welte595ad7b2009-02-16 22:05:44 +00001730 sig_data.subscr = subscr;
1731 sig_data.bts = msg->lchan->ts->trx->bts;
1732 sig_data.lchan = msg->lchan;
1733
1734 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001735
1736 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001737 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001738
Harald Welte7584aea2009-02-11 11:44:12 +00001739 /* FIXME: somehow signal the completion of the PAGING to
1740 * the entity that requested the paging */
1741
Harald Welte2d35ae62009-02-06 12:02:13 +00001742 return rc;
1743}
1744
Harald Weltef7c43522009-06-09 20:24:21 +00001745static int gsm48_rx_rr_classmark(struct msgb *msg)
1746{
1747 struct gsm48_hdr *gh = msgb_l3(msg);
1748 struct gsm_subscriber *subscr = msg->lchan->subscr;
1749 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1750 u_int8_t cm2_len, cm3_len = 0;
1751 u_int8_t *cm2, *cm3 = NULL;
1752
1753 DEBUGP(DRR, "CLASSMARK CHANGE ");
1754
1755 /* classmark 2 */
1756 cm2_len = gh->data[0];
1757 cm2 = &gh->data[1];
1758 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1759
1760 if (payload_len > cm2_len + 1) {
1761 /* we must have a classmark3 */
1762 if (gh->data[cm2_len+1] != 0x20) {
1763 DEBUGPC(DRR, "ERR CM3 TAG\n");
1764 return -EINVAL;
1765 }
1766 if (cm2_len > 3) {
1767 DEBUGPC(DRR, "CM2 too long!\n");
1768 return -EINVAL;
1769 }
1770
1771 cm3_len = gh->data[cm2_len+2];
1772 cm3 = &gh->data[cm2_len+3];
1773 if (cm3_len > 14) {
1774 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1775 return -EINVAL;
1776 }
1777 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1778 }
1779 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001780 subscr->equipment.classmark2_len = cm2_len;
1781 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001782 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001783 subscr->equipment.classmark3_len = cm3_len;
1784 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001785 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001786 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001787 }
1788
Harald Weltef7c43522009-06-09 20:24:21 +00001789 return 0;
1790}
1791
Harald Weltecf5b3592009-05-01 18:28:42 +00001792static int gsm48_rx_rr_status(struct msgb *msg)
1793{
1794 struct gsm48_hdr *gh = msgb_l3(msg);
1795
1796 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1797 rr_cause_name(gh->data[0]));
1798
1799 return 0;
1800}
1801
Harald Weltef7c43522009-06-09 20:24:21 +00001802static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1803{
1804 struct gsm48_hdr *gh = msgb_l3(msg);
1805 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1806 static struct gsm_meas_rep meas_rep;
1807
Harald Welte10d0e672009-06-27 02:53:10 +02001808 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001809 parse_meas_rep(&meas_rep, gh->data, payload_len);
1810 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001811 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001812 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001813 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001814 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001815 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001816 else
Harald Welte10d0e672009-06-27 02:53:10 +02001817 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001818 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1819 meas_rep.rxqual_sub);
1820
Harald Welte10d0e672009-06-27 02:53:10 +02001821 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001822
1823 /* FIXME: put the results somwhere */
1824
1825 return 0;
1826}
1827
Harald Weltebf5e8df2009-02-03 12:59:45 +00001828/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001829static int gsm0408_rcv_rr(struct msgb *msg)
1830{
1831 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001832 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001833
1834 switch (gh->msg_type) {
1835 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001836 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001837 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001838 case GSM48_MT_RR_GPRS_SUSP_REQ:
1839 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1840 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001841 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001842 rc = gsm48_rr_rx_pag_resp(msg);
1843 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001844 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1845 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte13cac662009-07-29 12:10:35 +02001846 /* We've successfully modified the MS side of the channel,
1847 * now go on to modify the BTS side of the channel */
Harald Welte9943c5b2009-07-29 15:41:29 +02001848 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte2c38aa82009-02-18 03:44:24 +00001849 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001850 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001851 case GSM48_MT_RR_STATUS:
1852 rc = gsm48_rx_rr_status(msg);
1853 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001854 case GSM48_MT_RR_MEAS_REP:
1855 rc = gsm48_rx_rr_meas_rep(msg);
1856 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001857 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001858 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001859 gh->msg_type);
1860 break;
1861 }
1862
Harald Welte2d35ae62009-02-06 12:02:13 +00001863 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001864}
1865
Harald Welte115d1032009-08-10 11:43:22 +02001866/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Holger Freythere64a7a32009-02-06 21:55:37 +00001867int gsm48_send_rr_release(struct gsm_lchan *lchan)
1868{
1869 struct msgb *msg = gsm48_msgb_alloc();
1870 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1871 u_int8_t *cause;
1872
1873 msg->lchan = lchan;
1874 gh->proto_discr = GSM48_PDISC_RR;
1875 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1876
1877 cause = msgb_put(msg, 1);
1878 cause[0] = GSM48_RR_CAUSE_NORMAL;
1879
1880 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1881 lchan->nr, lchan->type);
1882
Harald Welteae0f2362009-07-19 18:36:49 +02001883 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001884 gsm48_sendmsg(msg, NULL);
Harald Welte76042182009-08-08 16:03:15 +02001885 /* FIXME: Start Timer T3109 */
Harald Welteae0f2362009-07-19 18:36:49 +02001886
1887 /* Deactivate the SACCH on the BTS side */
1888 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001889}
1890
Harald Welte4bc90a12008-12-27 16:32:52 +00001891/* Call Control */
1892
Harald Welte7584aea2009-02-11 11:44:12 +00001893/* The entire call control code is written in accordance with Figure 7.10c
1894 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1895 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1896 * it for voice */
1897
Harald Welte4bfdfe72009-06-10 23:11:52 +08001898static void new_cc_state(struct gsm_trans *trans, int state)
1899{
1900 if (state > 31 || state < 0)
1901 return;
1902
1903 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltedcaf5652009-07-23 18:56:43 +02001904 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001905
Harald Weltedcaf5652009-07-23 18:56:43 +02001906 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001907}
1908
1909static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001910{
1911 struct msgb *msg = gsm48_msgb_alloc();
1912 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1913 u_int8_t *cause, *call_state;
1914
Harald Welte4bc90a12008-12-27 16:32:52 +00001915 gh->msg_type = GSM48_MT_CC_STATUS;
1916
1917 cause = msgb_put(msg, 3);
1918 cause[0] = 2;
1919 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1920 cause[2] = 0x80 | 30; /* response to status inquiry */
1921
1922 call_state = msgb_put(msg, 1);
1923 call_state[0] = 0xc0 | 0x00;
1924
Harald Welte39e2ead2009-07-23 21:13:03 +02001925 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001926}
1927
Harald Welte6f4b7532008-12-29 00:39:37 +00001928static int gsm48_tx_simple(struct gsm_lchan *lchan,
1929 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001930{
1931 struct msgb *msg = gsm48_msgb_alloc();
1932 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1933
1934 msg->lchan = lchan;
1935
Harald Welte6f4b7532008-12-29 00:39:37 +00001936 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001937 gh->msg_type = msg_type;
1938
Harald Welte39e2ead2009-07-23 21:13:03 +02001939 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001940}
1941
Harald Welte4bfdfe72009-06-10 23:11:52 +08001942static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1943{
Harald Weltedcaf5652009-07-23 18:56:43 +02001944 if (bsc_timer_pending(&trans->cc.timer)) {
1945 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1946 bsc_del_timer(&trans->cc.timer);
1947 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001948 }
1949}
1950
1951static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1952 int msg_type, struct gsm_mncc *mncc)
1953{
1954 struct msgb *msg;
1955
1956 if (trans)
1957 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001958 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001959 "Sending '%s' to MNCC.\n",
1960 trans->lchan->ts->trx->bts->nr,
1961 trans->lchan->ts->trx->nr,
1962 trans->lchan->ts->nr, trans->transaction_id,
1963 (trans->subscr)?(trans->subscr->extension):"-",
1964 get_mncc_name(msg_type));
1965 else
1966 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1967 "Sending '%s' to MNCC.\n",
1968 (trans->subscr)?(trans->subscr->extension):"-",
1969 get_mncc_name(msg_type));
1970 else
1971 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1972 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1973
1974 mncc->msg_type = msg_type;
1975
Harald Welte966636f2009-06-26 19:39:35 +02001976 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001977 if (!msg)
1978 return -ENOMEM;
1979 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
1980 msgb_enqueue(&net->upqueue, msg);
1981
1982 return 0;
1983}
1984
1985int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
1986 u_int32_t callref, int location, int value)
1987{
1988 struct gsm_mncc rel;
1989
Harald Welte92f70c52009-06-12 01:54:08 +08001990 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001991 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001992 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001993 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1994}
1995
Harald Weltedcaf5652009-07-23 18:56:43 +02001996/* Call Control Specific transaction release.
1997 * gets called by trans_free, DO NOT CALL YOURSELF! */
1998void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001999{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002000 gsm48_stop_cc_timer(trans);
2001
2002 /* send release to L4, if callref still exists */
2003 if (trans->callref) {
2004 /* Ressource unavailable */
Harald Welte596fed42009-07-23 19:06:52 +02002005 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002006 GSM48_CAUSE_LOC_PRN_S_LU,
2007 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002008 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002009 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002010 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltedcaf5652009-07-23 18:56:43 +02002011 if (trans->lchan)
2012 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002013}
2014
2015static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
2016
Harald Welte09e38af2009-02-16 22:52:23 +00002017/* call-back from paging the B-end of the connection */
2018static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00002019 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00002020{
Harald Welte7ccf7782009-02-17 01:43:01 +00002021 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022 struct gsm_subscriber *subscr = param;
2023 struct gsm_trans *transt, *tmp;
2024 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02002025
Harald Welte09e38af2009-02-16 22:52:23 +00002026 if (hooknum != GSM_HOOK_RR_PAGING)
2027 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002028
2029 if (!subscr)
2030 return -EINVAL;
2031 net = subscr->net;
2032 if (!net) {
2033 DEBUGP(DCC, "Error Network not set!\n");
2034 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00002035 }
Harald Welte7584aea2009-02-11 11:44:12 +00002036
Harald Welte4bfdfe72009-06-10 23:11:52 +08002037 /* check all tranactions (without lchan) for subscriber */
2038 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
2039 if (transt->subscr != subscr || transt->lchan)
2040 continue;
2041 switch (event) {
2042 case GSM_PAGING_SUCCEEDED:
2043 if (!lchan) // paranoid
2044 break;
2045 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
2046 subscr->extension);
2047 /* Assign lchan */
2048 if (!transt->lchan) {
2049 transt->lchan = lchan;
2050 use_lchan(lchan);
2051 }
2052 /* send SETUP request to called party */
Harald Weltedcaf5652009-07-23 18:56:43 +02002053 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002054 break;
2055 case GSM_PAGING_EXPIRED:
2056 DEBUGP(DCC, "Paging subscr %s expired!\n",
2057 subscr->extension);
2058 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002059 mncc_release_ind(transt->subscr->net, transt,
2060 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002061 GSM48_CAUSE_LOC_PRN_S_LU,
2062 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002063 transt->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002064 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002065 break;
2066 }
2067 }
Harald Welte09e38af2009-02-16 22:52:23 +00002068 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00002069}
Harald Welte7584aea2009-02-11 11:44:12 +00002070
Harald Welte805f6442009-07-28 18:25:29 +02002071/* some other part of the code sends us a signal */
2072static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2073 void *handler_data, void *signal_data)
2074{
2075 struct gsm_lchan *lchan = signal_data;
2076 struct gsm_bts_trx_ts *ts;
2077 int rc;
2078
2079 if (subsys != SS_ABISIP)
2080 return 0;
2081
2082 /* in case we use direct BTS-to-BTS RTP */
2083 if (ipacc_rtp_direct)
2084 return 0;
2085
2086 ts = lchan->ts;
2087
2088 switch (signal) {
2089 case S_ABISIP_BIND_ACK:
2090 /* the BTS has successfully bound a TCH to a local ip/port,
2091 * which means we can connect our UDP socket to it */
2092 if (ts->abis_ip.rtp_socket) {
2093 rtp_socket_free(ts->abis_ip.rtp_socket);
2094 ts->abis_ip.rtp_socket = NULL;
2095 }
2096
2097 ts->abis_ip.rtp_socket = rtp_socket_create();
2098 if (!ts->abis_ip.rtp_socket)
2099 goto out_err;
2100
2101 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2102 ts->abis_ip.bound_ip,
2103 ts->abis_ip.bound_port);
2104 if (rc < 0)
2105 goto out_err;
2106 break;
2107 case S_ABISIP_DISC_IND:
2108 /* the BTS tells us a RTP stream has been disconnected */
2109 if (ts->abis_ip.rtp_socket) {
2110 rtp_socket_free(ts->abis_ip.rtp_socket);
2111 ts->abis_ip.rtp_socket = NULL;
2112 }
2113 break;
2114 }
2115
2116 return 0;
2117out_err:
2118 /* FIXME: do something */
2119 return 0;
2120}
2121
2122/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2123static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2124{
2125 struct gsm_bts_trx_ts *ts = lchan->ts;
2126 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2127 int rc;
2128
2129 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2130 ntohs(rs->rtp.sin_local.sin_port),
2131 ts->abis_ip.conn_id,
2132 /* FIXME: use RTP payload of bound socket, not BTS*/
2133 ts->abis_ip.rtp_payload2);
2134
2135 return rc;
2136}
2137
Harald Welte49f48b82009-02-17 15:29:33 +00002138/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00002139static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00002140{
Harald Welte11fa29c2009-02-19 17:24:39 +00002141 struct gsm_bts *bts = lchan->ts->trx->bts;
2142 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00002143 struct gsm_bts_trx_ts *ts;
Harald Welte805f6442009-07-28 18:25:29 +02002144 int rc;
Harald Welte49f48b82009-02-17 15:29:33 +00002145
Harald Welte11fa29c2009-02-19 17:24:39 +00002146 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2147 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2148 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2149
2150 if (bts->type != remote_bts->type) {
2151 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2152 return -EINVAL;
2153 }
Harald Welte49f48b82009-02-17 15:29:33 +00002154
Harald Welte11fa29c2009-02-19 17:24:39 +00002155 switch (bts->type) {
2156 case GSM_BTS_TYPE_NANOBTS_900:
2157 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte805f6442009-07-28 18:25:29 +02002158 if (!ipacc_rtp_direct) {
2159 /* connect the TCH's to our RTP proxy */
2160 rc = ipacc_connect_proxy_bind(lchan);
2161 if (rc < 0)
2162 return rc;
2163 rc = ipacc_connect_proxy_bind(remote_lchan);
2164
2165 /* connect them with each other */
2166 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2167 remote_lchan->ts->abis_ip.rtp_socket);
2168 } else {
2169 /* directly connect TCH RTP streams to each other */
2170 ts = remote_lchan->ts;
2171 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2172 ts->abis_ip.bound_port,
2173 lchan->ts->abis_ip.conn_id,
2174 ts->abis_ip.rtp_payload2);
2175 if (rc < 0)
2176 return rc;
2177 ts = lchan->ts;
2178 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2179 ts->abis_ip.bound_port,
2180 remote_lchan->ts->abis_ip.conn_id,
2181 ts->abis_ip.rtp_payload2);
2182 }
Harald Welte11fa29c2009-02-19 17:24:39 +00002183 break;
2184 case GSM_BTS_TYPE_BS11:
2185 trau_mux_map_lchan(lchan, remote_lchan);
2186 break;
2187 default:
2188 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte805f6442009-07-28 18:25:29 +02002189 rc = -EINVAL;
Harald Welte11fa29c2009-02-19 17:24:39 +00002190 break;
2191 }
Harald Welte49f48b82009-02-17 15:29:33 +00002192
2193 return 0;
2194}
2195
Harald Welte4bfdfe72009-06-10 23:11:52 +08002196/* bridge channels of two transactions */
2197static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002198{
Harald Weltedcaf5652009-07-23 18:56:43 +02002199 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2200 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002201
Harald Welte4bfdfe72009-06-10 23:11:52 +08002202 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002203 return -EIO;
2204
Harald Welte4bfdfe72009-06-10 23:11:52 +08002205 if (!trans1->lchan || !trans2->lchan)
2206 return -EIO;
2207
2208 /* through-connect channel */
2209 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002210}
2211
Harald Welte4bfdfe72009-06-10 23:11:52 +08002212/* enable receive of channels to upqueue */
2213static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2214{
2215 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002216
Harald Welte4bfdfe72009-06-10 23:11:52 +08002217 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002218 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002219 if (!trans)
2220 return -EIO;
2221 if (!trans->lchan)
2222 return 0;
2223
2224 // todo IPACCESS
2225 if (enable)
2226 return trau_recv_lchan(trans->lchan, data->callref);
2227 return trau_mux_unmap(NULL, data->callref);
2228}
2229
2230/* send a frame to channel */
2231static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2232{
2233 struct gsm_trans *trans;
2234
2235 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002236 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002237 if (!trans)
2238 return -EIO;
2239 if (!trans->lchan)
2240 return 0;
2241 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2242 trans->lchan->type != GSM_LCHAN_TCH_H)
2243 return 0;
2244
2245 // todo IPACCESS
2246 return trau_send_lchan(trans->lchan,
2247 (struct decoded_trau_frame *)frame->data);
2248}
2249
2250
2251static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2252{
2253 DEBUGP(DCC, "-> STATUS ENQ\n");
2254 return gsm48_cc_tx_status(trans, msg);
2255}
2256
2257static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2258static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2259
2260static void gsm48_cc_timeout(void *arg)
2261{
2262 struct gsm_trans *trans = arg;
2263 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002264 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2265 int mo_location = GSM48_CAUSE_LOC_USER;
2266 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2267 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002268 struct gsm_mncc mo_rel, l4_rel;
2269
2270 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2271 mo_rel.callref = trans->callref;
2272 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2273 l4_rel.callref = trans->callref;
2274
Harald Weltedcaf5652009-07-23 18:56:43 +02002275 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002276 case 0x303:
2277 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002278 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002279 break;
2280 case 0x310:
2281 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002282 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002283 break;
2284 case 0x313:
2285 disconnect = 1;
2286 /* unknown, did not find it in the specs */
2287 break;
2288 case 0x301:
2289 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002290 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002291 break;
2292 case 0x308:
Harald Weltedcaf5652009-07-23 18:56:43 +02002293 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002294 /* restart T308 a second time */
Harald Weltedcaf5652009-07-23 18:56:43 +02002295 gsm48_cc_tx_release(trans, &trans->cc.msg);
2296 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002297 break; /* stay in release state */
2298 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002299 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002300 return;
2301// release = 1;
2302// l4_cause = 14;
2303// break;
2304 case 0x306:
2305 release = 1;
Harald Weltedcaf5652009-07-23 18:56:43 +02002306 mo_cause = trans->cc.msg.cause.value;
2307 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002308 break;
2309 case 0x323:
2310 disconnect = 1;
2311 break;
2312 default:
2313 release = 1;
2314 }
2315
2316 if (release && trans->callref) {
2317 /* process release towards layer 4 */
Harald Welte596fed42009-07-23 19:06:52 +02002318 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002319 l4_location, l4_cause);
2320 trans->callref = 0;
2321 }
2322
2323 if (disconnect && trans->callref) {
2324 /* process disconnect towards layer 4 */
2325 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte596fed42009-07-23 19:06:52 +02002326 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002327 }
2328
2329 /* process disconnect towards mobile station */
2330 if (disconnect || release) {
2331 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltedcaf5652009-07-23 18:56:43 +02002332 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2333 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2334 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002335 mo_rel.cause.diag_len = 3;
2336
2337 if (disconnect)
2338 gsm48_cc_tx_disconnect(trans, &mo_rel);
2339 if (release)
2340 gsm48_cc_tx_release(trans, &mo_rel);
2341 }
2342
2343}
2344
2345static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2346 int sec, int micro)
2347{
2348 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltedcaf5652009-07-23 18:56:43 +02002349 trans->cc.timer.cb = gsm48_cc_timeout;
2350 trans->cc.timer.data = trans;
2351 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2352 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002353}
2354
2355static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2356{
2357 struct gsm48_hdr *gh = msgb_l3(msg);
2358 u_int8_t msg_type = gh->msg_type & 0xbf;
2359 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2360 struct tlv_parsed tp;
2361 struct gsm_mncc setup;
2362
2363 memset(&setup, 0, sizeof(struct gsm_mncc));
2364 setup.callref = trans->callref;
2365 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2366 /* emergency setup is identified by msg_type */
2367 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2368 setup.emergency = 1;
2369
2370 /* use subscriber as calling party number */
2371 if (trans->subscr) {
2372 setup.fields |= MNCC_F_CALLING;
2373 strncpy(setup.calling.number, trans->subscr->extension,
2374 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002375 strncpy(setup.imsi, trans->subscr->imsi,
2376 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002377 }
2378 /* bearer capability */
2379 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2380 setup.fields |= MNCC_F_BEARER_CAP;
2381 decode_bearer_cap(&setup.bearer_cap,
2382 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2383 }
2384 /* facility */
2385 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2386 setup.fields |= MNCC_F_FACILITY;
2387 decode_facility(&setup.facility,
2388 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2389 }
2390 /* called party bcd number */
2391 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2392 setup.fields |= MNCC_F_CALLED;
2393 decode_called(&setup.called,
2394 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2395 }
2396 /* user-user */
2397 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2398 setup.fields |= MNCC_F_USERUSER;
2399 decode_useruser(&setup.useruser,
2400 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2401 }
2402 /* ss-version */
2403 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2404 setup.fields |= MNCC_F_SSVERSION;
2405 decode_ssversion(&setup.ssversion,
2406 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2407 }
2408 /* CLIR suppression */
2409 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2410 setup.clir.sup = 1;
2411 /* CLIR invocation */
2412 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2413 setup.clir.inv = 1;
2414 /* cc cap */
2415 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2416 setup.fields |= MNCC_F_CCCAP;
2417 decode_cccap(&setup.cccap,
2418 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2419 }
2420
Harald Welte4bfdfe72009-06-10 23:11:52 +08002421 new_cc_state(trans, GSM_CSTATE_INITIATED);
2422
2423 /* indicate setup to MNCC */
Harald Welte596fed42009-07-23 19:06:52 +02002424 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002425
Harald Welte13cac662009-07-29 12:10:35 +02002426 /* MNCC code will modify the channel asynchronously, we should
2427 * ipaccess-bind only after the modification has been made to the
2428 * lchan->tch_mode */
Harald Welte4bfdfe72009-06-10 23:11:52 +08002429 return 0;
2430}
2431
2432static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002433{
2434 struct msgb *msg = gsm48_msgb_alloc();
2435 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002436 struct gsm_mncc *setup = arg;
Harald Welte78283ef2009-07-23 21:36:44 +02002437 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00002438
Harald Welte7ccf7782009-02-17 01:43:01 +00002439 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002440
Harald Welte4bfdfe72009-06-10 23:11:52 +08002441 /* transaction id must not be assigned */
2442 if (trans->transaction_id != 0xff) { /* unasssigned */
2443 DEBUGP(DCC, "TX Setup with assigned transaction. "
2444 "This is not allowed!\n");
2445 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002446 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002447 GSM48_CAUSE_LOC_PRN_S_LU,
2448 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002449 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002450 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002451 return rc;
2452 }
2453
2454 /* Get free transaction_id */
Harald Welte78283ef2009-07-23 21:36:44 +02002455 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2456 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002457 /* no free transaction ID */
Harald Welte596fed42009-07-23 19:06:52 +02002458 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002459 GSM48_CAUSE_LOC_PRN_S_LU,
2460 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002461 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002462 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002463 return rc;
2464 }
Harald Welte78283ef2009-07-23 21:36:44 +02002465 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00002466
Harald Welte65e74cc2008-12-29 01:55:35 +00002467 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002468
Harald Welte4bfdfe72009-06-10 23:11:52 +08002469 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002470
Harald Welte4bfdfe72009-06-10 23:11:52 +08002471 /* bearer capability */
2472 if (setup->fields & MNCC_F_BEARER_CAP)
2473 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2474 /* facility */
2475 if (setup->fields & MNCC_F_FACILITY)
2476 encode_facility(msg, 0, &setup->facility);
2477 /* progress */
2478 if (setup->fields & MNCC_F_PROGRESS)
2479 encode_progress(msg, 0, &setup->progress);
2480 /* calling party BCD number */
2481 if (setup->fields & MNCC_F_CALLING)
2482 encode_calling(msg, &setup->calling);
2483 /* called party BCD number */
2484 if (setup->fields & MNCC_F_CALLED)
2485 encode_called(msg, &setup->called);
2486 /* user-user */
2487 if (setup->fields & MNCC_F_USERUSER)
2488 encode_useruser(msg, 0, &setup->useruser);
2489 /* redirecting party BCD number */
2490 if (setup->fields & MNCC_F_REDIRECTING)
2491 encode_redirecting(msg, &setup->redirecting);
2492 /* signal */
2493 if (setup->fields & MNCC_F_SIGNAL)
2494 encode_signal(msg, setup->signal);
2495
2496 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002497
Harald Welte39e2ead2009-07-23 21:13:03 +02002498 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002499}
2500
Harald Welte4bfdfe72009-06-10 23:11:52 +08002501static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2502{
2503 struct gsm48_hdr *gh = msgb_l3(msg);
2504 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2505 struct tlv_parsed tp;
2506 struct gsm_mncc call_conf;
2507
2508 gsm48_stop_cc_timer(trans);
2509 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2510
2511 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2512 call_conf.callref = trans->callref;
2513 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2514#if 0
2515 /* repeat */
2516 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2517 call_conf.repeat = 1;
2518 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2519 call_conf.repeat = 2;
2520#endif
2521 /* bearer capability */
2522 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2523 call_conf.fields |= MNCC_F_BEARER_CAP;
2524 decode_bearer_cap(&call_conf.bearer_cap,
2525 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2526 }
2527 /* cause */
2528 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2529 call_conf.fields |= MNCC_F_CAUSE;
2530 decode_cause(&call_conf.cause,
2531 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2532 }
2533 /* cc cap */
2534 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2535 call_conf.fields |= MNCC_F_CCCAP;
2536 decode_cccap(&call_conf.cccap,
2537 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2538 }
2539
2540 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2541
Harald Welte596fed42009-07-23 19:06:52 +02002542 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2543 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002544}
2545
2546static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2547{
2548 struct gsm_mncc *proceeding = arg;
2549 struct msgb *msg = gsm48_msgb_alloc();
2550 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2551
Harald Welte4bfdfe72009-06-10 23:11:52 +08002552 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2553
2554 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2555
2556 /* bearer capability */
2557 if (proceeding->fields & MNCC_F_BEARER_CAP)
2558 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2559 /* facility */
2560 if (proceeding->fields & MNCC_F_FACILITY)
2561 encode_facility(msg, 0, &proceeding->facility);
2562 /* progress */
2563 if (proceeding->fields & MNCC_F_PROGRESS)
2564 encode_progress(msg, 0, &proceeding->progress);
2565
Harald Welte39e2ead2009-07-23 21:13:03 +02002566 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002567}
2568
2569static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2570{
2571 struct gsm48_hdr *gh = msgb_l3(msg);
2572 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2573 struct tlv_parsed tp;
2574 struct gsm_mncc alerting;
2575
2576 gsm48_stop_cc_timer(trans);
2577 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2578
2579 memset(&alerting, 0, sizeof(struct gsm_mncc));
2580 alerting.callref = trans->callref;
2581 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2582 /* facility */
2583 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2584 alerting.fields |= MNCC_F_FACILITY;
2585 decode_facility(&alerting.facility,
2586 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2587 }
2588
2589 /* progress */
2590 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2591 alerting.fields |= MNCC_F_PROGRESS;
2592 decode_progress(&alerting.progress,
2593 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2594 }
2595 /* ss-version */
2596 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2597 alerting.fields |= MNCC_F_SSVERSION;
2598 decode_ssversion(&alerting.ssversion,
2599 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2600 }
2601
2602 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2603
Harald Welte596fed42009-07-23 19:06:52 +02002604 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2605 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002606}
2607
2608static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2609{
2610 struct gsm_mncc *alerting = arg;
2611 struct msgb *msg = gsm48_msgb_alloc();
2612 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2613
Harald Welte4bfdfe72009-06-10 23:11:52 +08002614 gh->msg_type = GSM48_MT_CC_ALERTING;
2615
2616 /* facility */
2617 if (alerting->fields & MNCC_F_FACILITY)
2618 encode_facility(msg, 0, &alerting->facility);
2619 /* progress */
2620 if (alerting->fields & MNCC_F_PROGRESS)
2621 encode_progress(msg, 0, &alerting->progress);
2622 /* user-user */
2623 if (alerting->fields & MNCC_F_USERUSER)
2624 encode_useruser(msg, 0, &alerting->useruser);
2625
2626 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2627
Harald Welte39e2ead2009-07-23 21:13:03 +02002628 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002629}
2630
2631static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2632{
2633 struct gsm_mncc *progress = arg;
2634 struct msgb *msg = gsm48_msgb_alloc();
2635 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2636
Harald Welte4bfdfe72009-06-10 23:11:52 +08002637 gh->msg_type = GSM48_MT_CC_PROGRESS;
2638
2639 /* progress */
2640 encode_progress(msg, 1, &progress->progress);
2641 /* user-user */
2642 if (progress->fields & MNCC_F_USERUSER)
2643 encode_useruser(msg, 0, &progress->useruser);
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_tx_connect(struct gsm_trans *trans, void *arg)
2649{
2650 struct gsm_mncc *connect = arg;
2651 struct msgb *msg = gsm48_msgb_alloc();
2652 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2653
Harald Welte4bfdfe72009-06-10 23:11:52 +08002654 gh->msg_type = GSM48_MT_CC_CONNECT;
2655
2656 gsm48_stop_cc_timer(trans);
2657 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2658
2659 /* facility */
2660 if (connect->fields & MNCC_F_FACILITY)
2661 encode_facility(msg, 0, &connect->facility);
2662 /* progress */
2663 if (connect->fields & MNCC_F_PROGRESS)
2664 encode_progress(msg, 0, &connect->progress);
2665 /* connected number */
2666 if (connect->fields & MNCC_F_CONNECTED)
2667 encode_connected(msg, &connect->connected);
2668 /* user-user */
2669 if (connect->fields & MNCC_F_USERUSER)
2670 encode_useruser(msg, 0, &connect->useruser);
2671
2672 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2673
Harald Welte39e2ead2009-07-23 21:13:03 +02002674 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002675}
2676
2677static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2678{
2679 struct gsm48_hdr *gh = msgb_l3(msg);
2680 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2681 struct tlv_parsed tp;
2682 struct gsm_mncc connect;
2683
2684 gsm48_stop_cc_timer(trans);
2685
2686 memset(&connect, 0, sizeof(struct gsm_mncc));
2687 connect.callref = trans->callref;
2688 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2689 /* use subscriber as connected party number */
2690 if (trans->subscr) {
2691 connect.fields |= MNCC_F_CONNECTED;
2692 strncpy(connect.connected.number, trans->subscr->extension,
2693 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002694 strncpy(connect.imsi, trans->subscr->imsi,
2695 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002696 }
2697 /* facility */
2698 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2699 connect.fields |= MNCC_F_FACILITY;
2700 decode_facility(&connect.facility,
2701 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2702 }
2703 /* user-user */
2704 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2705 connect.fields |= MNCC_F_USERUSER;
2706 decode_useruser(&connect.useruser,
2707 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2708 }
2709 /* ss-version */
2710 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2711 connect.fields |= MNCC_F_SSVERSION;
2712 decode_ssversion(&connect.ssversion,
2713 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2714 }
2715
2716 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2717
Harald Welte596fed42009-07-23 19:06:52 +02002718 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002719}
2720
2721
2722static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2723{
2724 struct gsm_mncc connect_ack;
2725
2726 gsm48_stop_cc_timer(trans);
2727
2728 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2729
2730 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2731 connect_ack.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002732 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002733 &connect_ack);
2734}
2735
2736static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2737{
2738 struct msgb *msg = gsm48_msgb_alloc();
2739 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2740
Harald Welte4bfdfe72009-06-10 23:11:52 +08002741 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2742
2743 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2744
Harald Welte39e2ead2009-07-23 21:13:03 +02002745 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002746}
2747
2748static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2749{
2750 struct gsm48_hdr *gh = msgb_l3(msg);
2751 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2752 struct tlv_parsed tp;
2753 struct gsm_mncc disc;
2754
2755 gsm48_stop_cc_timer(trans);
2756
2757 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2758
2759 memset(&disc, 0, sizeof(struct gsm_mncc));
2760 disc.callref = trans->callref;
2761 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2762 /* cause */
2763 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2764 disc.fields |= MNCC_F_CAUSE;
2765 decode_cause(&disc.cause,
2766 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2767 }
2768 /* facility */
2769 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2770 disc.fields |= MNCC_F_FACILITY;
2771 decode_facility(&disc.facility,
2772 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2773 }
2774 /* user-user */
2775 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2776 disc.fields |= MNCC_F_USERUSER;
2777 decode_useruser(&disc.useruser,
2778 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2779 }
2780 /* ss-version */
2781 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2782 disc.fields |= MNCC_F_SSVERSION;
2783 decode_ssversion(&disc.ssversion,
2784 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2785 }
2786
Harald Welte596fed42009-07-23 19:06:52 +02002787 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002788
2789}
2790
Harald Weltec66b71c2009-06-11 14:23:20 +08002791static struct gsm_mncc_cause default_cause = {
2792 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2793 .coding = 0,
2794 .rec = 0,
2795 .rec_val = 0,
2796 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2797 .diag_len = 0,
2798 .diag = { 0 },
2799};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002800
2801static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2802{
2803 struct gsm_mncc *disc = arg;
2804 struct msgb *msg = gsm48_msgb_alloc();
2805 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2806
Harald Welte4bfdfe72009-06-10 23:11:52 +08002807 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2808
2809 gsm48_stop_cc_timer(trans);
2810 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2811
2812 /* cause */
2813 if (disc->fields & MNCC_F_CAUSE)
2814 encode_cause(msg, 1, &disc->cause);
2815 else
2816 encode_cause(msg, 1, &default_cause);
2817
2818 /* facility */
2819 if (disc->fields & MNCC_F_FACILITY)
2820 encode_facility(msg, 0, &disc->facility);
2821 /* progress */
2822 if (disc->fields & MNCC_F_PROGRESS)
2823 encode_progress(msg, 0, &disc->progress);
2824 /* user-user */
2825 if (disc->fields & MNCC_F_USERUSER)
2826 encode_useruser(msg, 0, &disc->useruser);
2827
2828 /* store disconnect cause for T306 expiry */
Harald Weltedcaf5652009-07-23 18:56:43 +02002829 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002830
2831 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2832
Harald Welte39e2ead2009-07-23 21:13:03 +02002833 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002834}
2835
2836static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2837{
2838 struct gsm48_hdr *gh = msgb_l3(msg);
2839 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2840 struct tlv_parsed tp;
2841 struct gsm_mncc rel;
2842 int rc;
2843
2844 gsm48_stop_cc_timer(trans);
2845
2846 memset(&rel, 0, sizeof(struct gsm_mncc));
2847 rel.callref = trans->callref;
2848 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2849 /* cause */
2850 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2851 rel.fields |= MNCC_F_CAUSE;
2852 decode_cause(&rel.cause,
2853 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2854 }
2855 /* facility */
2856 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2857 rel.fields |= MNCC_F_FACILITY;
2858 decode_facility(&rel.facility,
2859 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2860 }
2861 /* user-user */
2862 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2863 rel.fields |= MNCC_F_USERUSER;
2864 decode_useruser(&rel.useruser,
2865 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2866 }
2867 /* ss-version */
2868 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2869 rel.fields |= MNCC_F_SSVERSION;
2870 decode_ssversion(&rel.ssversion,
2871 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2872 }
2873
Harald Weltedcaf5652009-07-23 18:56:43 +02002874 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002875 /* release collision 5.4.5 */
Harald Welte596fed42009-07-23 19:06:52 +02002876 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002877 } else {
Harald Welte596fed42009-07-23 19:06:52 +02002878 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002879 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte596fed42009-07-23 19:06:52 +02002880 GSM48_MT_CC_RELEASE_COMPL);
2881 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002882 }
2883
2884 new_cc_state(trans, GSM_CSTATE_NULL);
2885
2886 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002887 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002888
2889 return rc;
2890}
2891
2892static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2893{
2894 struct gsm_mncc *rel = arg;
2895 struct msgb *msg = gsm48_msgb_alloc();
2896 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2897
Harald Welte4bfdfe72009-06-10 23:11:52 +08002898 gh->msg_type = GSM48_MT_CC_RELEASE;
2899
2900 trans->callref = 0;
2901
2902 gsm48_stop_cc_timer(trans);
2903 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2904
2905 /* cause */
2906 if (rel->fields & MNCC_F_CAUSE)
2907 encode_cause(msg, 0, &rel->cause);
2908 /* facility */
2909 if (rel->fields & MNCC_F_FACILITY)
2910 encode_facility(msg, 0, &rel->facility);
2911 /* user-user */
2912 if (rel->fields & MNCC_F_USERUSER)
2913 encode_useruser(msg, 0, &rel->useruser);
2914
Harald Weltedcaf5652009-07-23 18:56:43 +02002915 trans->cc.T308_second = 0;
2916 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002917
Harald Weltedcaf5652009-07-23 18:56:43 +02002918 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002919 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2920
Harald Welte39e2ead2009-07-23 21:13:03 +02002921 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002922}
2923
2924static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2925{
2926 struct gsm48_hdr *gh = msgb_l3(msg);
2927 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2928 struct tlv_parsed tp;
2929 struct gsm_mncc rel;
2930 int rc = 0;
2931
2932 gsm48_stop_cc_timer(trans);
2933
2934 memset(&rel, 0, sizeof(struct gsm_mncc));
2935 rel.callref = trans->callref;
2936 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2937 /* cause */
2938 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2939 rel.fields |= MNCC_F_CAUSE;
2940 decode_cause(&rel.cause,
2941 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2942 }
2943 /* facility */
2944 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2945 rel.fields |= MNCC_F_FACILITY;
2946 decode_facility(&rel.facility,
2947 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2948 }
2949 /* user-user */
2950 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2951 rel.fields |= MNCC_F_USERUSER;
2952 decode_useruser(&rel.useruser,
2953 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2954 }
2955 /* ss-version */
2956 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2957 rel.fields |= MNCC_F_SSVERSION;
2958 decode_ssversion(&rel.ssversion,
2959 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2960 }
2961
2962 if (trans->callref) {
Harald Weltedcaf5652009-07-23 18:56:43 +02002963 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002964 case GSM_CSTATE_CALL_PRESENT:
Harald Welte596fed42009-07-23 19:06:52 +02002965 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002966 MNCC_REJ_IND, &rel);
2967 break;
2968 case GSM_CSTATE_RELEASE_REQ:
Harald Welte596fed42009-07-23 19:06:52 +02002969 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002970 MNCC_REL_CNF, &rel);
2971 break;
2972 default:
Harald Welte596fed42009-07-23 19:06:52 +02002973 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002974 MNCC_REL_IND, &rel);
2975 }
2976 }
2977
2978 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002979 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002980
2981 return rc;
2982}
2983
2984static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2985{
2986 struct gsm_mncc *rel = arg;
2987 struct msgb *msg = gsm48_msgb_alloc();
2988 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2989
Harald Welte4bfdfe72009-06-10 23:11:52 +08002990 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2991
2992 trans->callref = 0;
2993
2994 gsm48_stop_cc_timer(trans);
2995
2996 /* cause */
2997 if (rel->fields & MNCC_F_CAUSE)
2998 encode_cause(msg, 0, &rel->cause);
2999 /* facility */
3000 if (rel->fields & MNCC_F_FACILITY)
3001 encode_facility(msg, 0, &rel->facility);
3002 /* user-user */
3003 if (rel->fields & MNCC_F_USERUSER)
3004 encode_useruser(msg, 0, &rel->useruser);
3005
Harald Weltedcaf5652009-07-23 18:56:43 +02003006 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003007
Harald Welte39e2ead2009-07-23 21:13:03 +02003008 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003009}
3010
3011static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
3012{
3013 struct gsm48_hdr *gh = msgb_l3(msg);
3014 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3015 struct tlv_parsed tp;
3016 struct gsm_mncc fac;
3017
3018 memset(&fac, 0, sizeof(struct gsm_mncc));
3019 fac.callref = trans->callref;
3020 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
3021 /* facility */
3022 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
3023 fac.fields |= MNCC_F_FACILITY;
3024 decode_facility(&fac.facility,
3025 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
3026 }
3027 /* ss-version */
3028 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3029 fac.fields |= MNCC_F_SSVERSION;
3030 decode_ssversion(&fac.ssversion,
3031 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3032 }
3033
Harald Welte596fed42009-07-23 19:06:52 +02003034 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003035}
3036
3037static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
3038{
3039 struct gsm_mncc *fac = arg;
3040 struct msgb *msg = gsm48_msgb_alloc();
3041 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3042
Harald Welte4bfdfe72009-06-10 23:11:52 +08003043 gh->msg_type = GSM48_MT_CC_FACILITY;
3044
3045 /* facility */
3046 encode_facility(msg, 1, &fac->facility);
3047
Harald Welte39e2ead2009-07-23 21:13:03 +02003048 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003049}
3050
3051static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
3052{
3053 struct gsm_mncc hold;
3054
3055 memset(&hold, 0, sizeof(struct gsm_mncc));
3056 hold.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003057 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003058}
3059
3060static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3061{
3062 struct msgb *msg = gsm48_msgb_alloc();
3063 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3064
Harald Welte4bfdfe72009-06-10 23:11:52 +08003065 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3066
Harald Welte39e2ead2009-07-23 21:13:03 +02003067 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003068}
3069
3070static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3071{
3072 struct gsm_mncc *hold_rej = arg;
3073 struct msgb *msg = gsm48_msgb_alloc();
3074 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3075
Harald Welte4bfdfe72009-06-10 23:11:52 +08003076 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3077
3078 /* cause */
3079 if (hold_rej->fields & MNCC_F_CAUSE)
3080 encode_cause(msg, 1, &hold_rej->cause);
3081 else
3082 encode_cause(msg, 1, &default_cause);
3083
Harald Welte39e2ead2009-07-23 21:13:03 +02003084 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003085}
3086
3087static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3088{
3089 struct gsm_mncc retrieve;
3090
3091 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3092 retrieve.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003093 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3094 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003095}
3096
3097static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3098{
3099 struct msgb *msg = gsm48_msgb_alloc();
3100 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3101
Harald Welte4bfdfe72009-06-10 23:11:52 +08003102 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3103
Harald Welte39e2ead2009-07-23 21:13:03 +02003104 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003105}
3106
3107static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3108{
3109 struct gsm_mncc *retrieve_rej = arg;
3110 struct msgb *msg = gsm48_msgb_alloc();
3111 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3112
Harald Welte4bfdfe72009-06-10 23:11:52 +08003113 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3114
3115 /* cause */
3116 if (retrieve_rej->fields & MNCC_F_CAUSE)
3117 encode_cause(msg, 1, &retrieve_rej->cause);
3118 else
3119 encode_cause(msg, 1, &default_cause);
3120
Harald Welte39e2ead2009-07-23 21:13:03 +02003121 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003122}
3123
3124static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3125{
3126 struct gsm48_hdr *gh = msgb_l3(msg);
3127 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3128 struct tlv_parsed tp;
3129 struct gsm_mncc dtmf;
3130
3131 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3132 dtmf.callref = trans->callref;
3133 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3134 /* keypad facility */
3135 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3136 dtmf.fields |= MNCC_F_KEYPAD;
3137 decode_keypad(&dtmf.keypad,
3138 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3139 }
3140
Harald Welte596fed42009-07-23 19:06:52 +02003141 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003142}
3143
3144static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3145{
3146 struct gsm_mncc *dtmf = arg;
3147 struct msgb *msg = gsm48_msgb_alloc();
3148 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3149
Harald Welte4bfdfe72009-06-10 23:11:52 +08003150 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3151
3152 /* keypad */
3153 if (dtmf->fields & MNCC_F_KEYPAD)
3154 encode_keypad(msg, dtmf->keypad);
3155
Harald Welte39e2ead2009-07-23 21:13:03 +02003156 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003157}
3158
3159static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3160{
3161 struct gsm_mncc *dtmf = arg;
3162 struct msgb *msg = gsm48_msgb_alloc();
3163 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3164
Harald Welte4bfdfe72009-06-10 23:11:52 +08003165 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3166
3167 /* cause */
3168 if (dtmf->fields & MNCC_F_CAUSE)
3169 encode_cause(msg, 1, &dtmf->cause);
3170 else
3171 encode_cause(msg, 1, &default_cause);
3172
Harald Welte39e2ead2009-07-23 21:13:03 +02003173 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003174}
3175
3176static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3177{
3178 struct msgb *msg = gsm48_msgb_alloc();
3179 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3180
Harald Welte4bfdfe72009-06-10 23:11:52 +08003181 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3182
Harald Welte39e2ead2009-07-23 21:13:03 +02003183 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003184}
3185
3186static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3187{
3188 struct gsm_mncc dtmf;
3189
3190 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3191 dtmf.callref = trans->callref;
3192
Harald Welte596fed42009-07-23 19:06:52 +02003193 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003194}
3195
3196static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3197{
3198 struct gsm48_hdr *gh = msgb_l3(msg);
3199 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3200 struct tlv_parsed tp;
3201 struct gsm_mncc modify;
3202
3203 memset(&modify, 0, sizeof(struct gsm_mncc));
3204 modify.callref = trans->callref;
3205 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3206 /* bearer capability */
3207 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3208 modify.fields |= MNCC_F_BEARER_CAP;
3209 decode_bearer_cap(&modify.bearer_cap,
3210 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3211 }
3212
3213 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3214
Harald Welte596fed42009-07-23 19:06:52 +02003215 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003216}
3217
3218static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3219{
3220 struct gsm_mncc *modify = arg;
3221 struct msgb *msg = gsm48_msgb_alloc();
3222 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3223
Harald Welte4bfdfe72009-06-10 23:11:52 +08003224 gh->msg_type = GSM48_MT_CC_MODIFY;
3225
3226 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3227
3228 /* bearer capability */
3229 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3230
3231 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3232
Harald Welte39e2ead2009-07-23 21:13:03 +02003233 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003234}
3235
3236static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3237{
3238 struct gsm48_hdr *gh = msgb_l3(msg);
3239 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3240 struct tlv_parsed tp;
3241 struct gsm_mncc modify;
3242
3243 gsm48_stop_cc_timer(trans);
3244
3245 memset(&modify, 0, sizeof(struct gsm_mncc));
3246 modify.callref = trans->callref;
3247 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3248 /* bearer capability */
3249 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3250 modify.fields |= MNCC_F_BEARER_CAP;
3251 decode_bearer_cap(&modify.bearer_cap,
3252 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3253 }
3254
3255 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3256
Harald Welte596fed42009-07-23 19:06:52 +02003257 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003258}
3259
3260static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3261{
3262 struct gsm_mncc *modify = arg;
3263 struct msgb *msg = gsm48_msgb_alloc();
3264 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3265
Harald Welte4bfdfe72009-06-10 23:11:52 +08003266 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3267
3268 /* bearer capability */
3269 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3270
3271 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3272
Harald Welte39e2ead2009-07-23 21:13:03 +02003273 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003274}
3275
3276static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3277{
3278 struct gsm48_hdr *gh = msgb_l3(msg);
3279 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3280 struct tlv_parsed tp;
3281 struct gsm_mncc modify;
3282
3283 gsm48_stop_cc_timer(trans);
3284
3285 memset(&modify, 0, sizeof(struct gsm_mncc));
3286 modify.callref = trans->callref;
3287 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3288 /* bearer capability */
3289 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3290 modify.fields |= GSM48_IE_BEARER_CAP;
3291 decode_bearer_cap(&modify.bearer_cap,
3292 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3293 }
3294 /* cause */
3295 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3296 modify.fields |= MNCC_F_CAUSE;
3297 decode_cause(&modify.cause,
3298 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3299 }
3300
3301 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3302
Harald Welte596fed42009-07-23 19:06:52 +02003303 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003304}
3305
3306static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3307{
3308 struct gsm_mncc *modify = arg;
3309 struct msgb *msg = gsm48_msgb_alloc();
3310 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3311
Harald Welte4bfdfe72009-06-10 23:11:52 +08003312 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3313
3314 /* bearer capability */
3315 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3316 /* cause */
3317 encode_cause(msg, 1, &modify->cause);
3318
3319 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3320
Harald Welte39e2ead2009-07-23 21:13:03 +02003321 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003322}
3323
3324static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3325{
3326 struct gsm_mncc *notify = arg;
3327 struct msgb *msg = gsm48_msgb_alloc();
3328 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3329
Harald Welte4bfdfe72009-06-10 23:11:52 +08003330 gh->msg_type = GSM48_MT_CC_NOTIFY;
3331
3332 /* notify */
3333 encode_notify(msg, notify->notify);
3334
Harald Welte39e2ead2009-07-23 21:13:03 +02003335 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003336}
3337
3338static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3339{
3340 struct gsm48_hdr *gh = msgb_l3(msg);
3341 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3342// struct tlv_parsed tp;
3343 struct gsm_mncc notify;
3344
3345 memset(&notify, 0, sizeof(struct gsm_mncc));
3346 notify.callref = trans->callref;
3347// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3348 if (payload_len >= 1)
3349 decode_notify(&notify.notify, gh->data);
3350
Harald Welte596fed42009-07-23 19:06:52 +02003351 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003352}
3353
3354static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3355{
3356 struct gsm_mncc *user = arg;
3357 struct msgb *msg = gsm48_msgb_alloc();
3358 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3359
Harald Welte4bfdfe72009-06-10 23:11:52 +08003360 gh->msg_type = GSM48_MT_CC_USER_INFO;
3361
3362 /* user-user */
3363 if (user->fields & MNCC_F_USERUSER)
3364 encode_useruser(msg, 1, &user->useruser);
3365 /* more data */
3366 if (user->more)
3367 encode_more(msg);
3368
Harald Welte39e2ead2009-07-23 21:13:03 +02003369 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003370}
3371
3372static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3373{
3374 struct gsm48_hdr *gh = msgb_l3(msg);
3375 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3376 struct tlv_parsed tp;
3377 struct gsm_mncc user;
3378
3379 memset(&user, 0, sizeof(struct gsm_mncc));
3380 user.callref = trans->callref;
3381 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3382 /* user-user */
3383 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3384 user.fields |= MNCC_F_USERUSER;
3385 decode_useruser(&user.useruser,
3386 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3387 }
3388 /* more data */
3389 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3390 user.more = 1;
3391
Harald Welte596fed42009-07-23 19:06:52 +02003392 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003393}
3394
3395static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3396{
3397 struct gsm_mncc *mode = arg;
Harald Welte13cac662009-07-29 12:10:35 +02003398 int rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003399
Harald Welte13cac662009-07-29 12:10:35 +02003400 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3401 if (rc < 0)
3402 return rc;
3403
3404 /* FIXME: we not only need to do this after mode modify, but
3405 * also after channel activation */
3406 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3407 mode->lchan_mode != GSM48_CMODE_SIGN)
3408 rc = rsl_ipacc_bind(trans->lchan);
3409
3410 return rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003411}
3412
3413static struct downstate {
3414 u_int32_t states;
3415 int type;
3416 int (*rout) (struct gsm_trans *trans, void *arg);
3417} downstatelist[] = {
3418 /* mobile originating call establishment */
3419 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3420 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3421 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3422 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3423 {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 */
3424 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3425 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3426 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3427 /* mobile terminating call establishment */
3428 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3429 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3430 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3431 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3432 /* signalling during call */
3433 {SBIT(GSM_CSTATE_ACTIVE),
3434 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3435 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3436 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3437 {ALL_STATES,
3438 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3439 {ALL_STATES,
3440 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3441 {ALL_STATES,
3442 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3443 {SBIT(GSM_CSTATE_ACTIVE),
3444 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3445 {SBIT(GSM_CSTATE_ACTIVE),
3446 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3447 {SBIT(GSM_CSTATE_ACTIVE),
3448 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3449 {SBIT(GSM_CSTATE_ACTIVE),
3450 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3451 {SBIT(GSM_CSTATE_ACTIVE),
3452 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3453 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3454 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3455 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3456 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3457 {SBIT(GSM_CSTATE_ACTIVE),
3458 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3459 /* clearing */
3460 {SBIT(GSM_CSTATE_INITIATED),
3461 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3462 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3463 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3464 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3465 MNCC_REL_REQ, gsm48_cc_tx_release},
3466 /* special */
3467 {ALL_STATES,
3468 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3469};
3470
3471#define DOWNSLLEN \
3472 (sizeof(downstatelist) / sizeof(struct downstate))
3473
3474
3475int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3476{
Harald Welte1a6f7982009-08-09 18:52:33 +02003477 int i, rc = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003478 struct gsm_trans *trans = NULL, *transt;
3479 struct gsm_subscriber *subscr;
Harald Welte1a6f7982009-08-09 18:52:33 +02003480 struct gsm_lchan *lchan = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003481 struct gsm_bts *bts = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003482 struct gsm_mncc *data = arg, rel;
3483
3484 /* handle special messages */
3485 switch(msg_type) {
3486 case MNCC_BRIDGE:
3487 return tch_bridge(net, arg);
3488 case MNCC_FRAME_DROP:
3489 return tch_recv(net, arg, 0);
3490 case MNCC_FRAME_RECV:
3491 return tch_recv(net, arg, 1);
3492 case GSM_TRAU_FRAME:
3493 return tch_frame(net, arg);
3494 }
3495
3496 memset(&rel, 0, sizeof(struct gsm_mncc));
3497 rel.callref = data->callref;
3498
3499 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02003500 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003501
3502 /* Callref unknown */
3503 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003504 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003505 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3506 "Received '%s' from MNCC with "
3507 "unknown callref %d\n", data->called.number,
3508 get_mncc_name(msg_type), data->callref);
3509 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003510 return mncc_release_ind(net, NULL, data->callref,
3511 GSM48_CAUSE_LOC_PRN_S_LU,
3512 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003513 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003514 if (!data->called.number[0] && !data->imsi[0]) {
3515 DEBUGP(DCC, "(bts - trx - ts - ti) "
3516 "Received '%s' from MNCC with "
3517 "no number or IMSI\n", get_mncc_name(msg_type));
3518 /* Invalid number */
3519 return mncc_release_ind(net, NULL, data->callref,
3520 GSM48_CAUSE_LOC_PRN_S_LU,
3521 GSM48_CC_CAUSE_INV_NR_FORMAT);
3522 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003523 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003524 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02003525 subscr = subscr_get_by_extension(net,
3526 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003527 else
Harald Welte9176bd42009-07-23 18:46:00 +02003528 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003529 /* If subscriber is not found */
3530 if (!subscr) {
3531 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3532 "Received '%s' from MNCC with "
3533 "unknown subscriber %s\n", data->called.number,
3534 get_mncc_name(msg_type), data->called.number);
3535 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003536 return mncc_release_ind(net, NULL, data->callref,
3537 GSM48_CAUSE_LOC_PRN_S_LU,
3538 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003539 }
3540 /* If subscriber is not "attached" */
3541 if (!subscr->lac) {
3542 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3543 "Received '%s' from MNCC with "
3544 "detached subscriber %s\n", data->called.number,
3545 get_mncc_name(msg_type), data->called.number);
3546 subscr_put(subscr);
3547 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003548 return mncc_release_ind(net, NULL, data->callref,
3549 GSM48_CAUSE_LOC_PRN_S_LU,
3550 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003551 }
3552 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003553 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3554 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003555 DEBUGP(DCC, "No memory for trans.\n");
3556 subscr_put(subscr);
3557 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003558 mncc_release_ind(net, NULL, data->callref,
3559 GSM48_CAUSE_LOC_PRN_S_LU,
3560 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003561 return -ENOMEM;
3562 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003563 /* Find lchan */
Harald Welte1a6f7982009-08-09 18:52:33 +02003564 lchan = lchan_for_subscr(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003565 /* If subscriber has no lchan */
3566 if (!lchan) {
3567 /* find transaction with this subscriber already paging */
3568 llist_for_each_entry(transt, &net->trans_list, entry) {
3569 /* Transaction of our lchan? */
3570 if (transt == trans ||
3571 transt->subscr != subscr)
3572 continue;
3573 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3574 "Received '%s' from MNCC with "
3575 "unallocated channel, paging already "
3576 "started.\n", bts->nr,
3577 data->called.number,
3578 get_mncc_name(msg_type));
3579 return 0;
3580 }
3581 /* store setup informations until paging was successfull */
Harald Weltedcaf5652009-07-23 18:56:43 +02003582 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Weltea1b28582009-08-01 19:31:47 +02003583 /* Trigger paging */
3584 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3585 setup_trig_pag_evt, subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003586 return 0;
3587 }
3588 /* Assign lchan */
3589 trans->lchan = lchan;
3590 use_lchan(lchan);
3591 }
3592 lchan = trans->lchan;
3593
3594 /* if paging did not respond yet */
3595 if (!lchan) {
3596 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3597 "Received '%s' from MNCC in paging state\n",
3598 (trans->subscr)?(trans->subscr->extension):"-",
3599 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003600 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3601 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003602 if (msg_type == MNCC_REL_REQ)
3603 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3604 else
3605 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3606 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003607 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003608 return rc;
3609 }
3610
3611 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3612 "Received '%s' from MNCC in state %d (%s)\n",
3613 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3614 trans->transaction_id,
3615 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003616 get_mncc_name(msg_type), trans->cc.state,
3617 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003618
3619 /* Find function for current state and message */
3620 for (i = 0; i < DOWNSLLEN; i++)
3621 if ((msg_type == downstatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003622 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003623 break;
3624 if (i == DOWNSLLEN) {
3625 DEBUGP(DCC, "Message unhandled at this state.\n");
3626 return 0;
3627 }
3628
3629 rc = downstatelist[i].rout(trans, arg);
3630
3631 return rc;
3632}
3633
3634
3635static struct datastate {
3636 u_int32_t states;
3637 int type;
3638 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3639} datastatelist[] = {
3640 /* mobile originating call establishment */
3641 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3642 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3643 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3644 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3645 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3646 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3647 /* mobile terminating call establishment */
3648 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3649 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3650 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3651 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3652 {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 */
3653 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3654 /* signalling during call */
3655 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3656 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3657 {SBIT(GSM_CSTATE_ACTIVE),
3658 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3659 {ALL_STATES,
3660 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3661 {ALL_STATES,
3662 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3663 {ALL_STATES,
3664 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3665 {SBIT(GSM_CSTATE_ACTIVE),
3666 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3667 {SBIT(GSM_CSTATE_ACTIVE),
3668 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3669 {SBIT(GSM_CSTATE_ACTIVE),
3670 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3671 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3672 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3673 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3674 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3675 {SBIT(GSM_CSTATE_ACTIVE),
3676 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3677 /* clearing */
3678 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3679 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3680 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3681 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3682 {ALL_STATES, /* 5.4.3.4 */
3683 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3684};
3685
3686#define DATASLLEN \
3687 (sizeof(datastatelist) / sizeof(struct datastate))
3688
Harald Welte4bc90a12008-12-27 16:32:52 +00003689static int gsm0408_rcv_cc(struct msgb *msg)
3690{
3691 struct gsm48_hdr *gh = msgb_l3(msg);
3692 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003693 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003694 struct gsm_lchan *lchan = msg->lchan;
Harald Weltedcaf5652009-07-23 18:56:43 +02003695 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003696 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003697
Harald Welte4bfdfe72009-06-10 23:11:52 +08003698 if (msg_type & 0x80) {
3699 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3700 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003701 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003702
3703 /* Find transaction */
Harald Welteb8b40732009-07-23 21:58:40 +02003704 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltedcaf5652009-07-23 18:56:43 +02003705
Harald Welte6f5aee02009-07-23 21:21:14 +02003706 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003707 "Received '%s' from MS in state %d (%s)\n",
3708 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3709 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003710 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3711 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003712
3713 /* Create transaction */
3714 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003715 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003716 "creating new trans.\n", transaction_id);
3717 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003718 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3719 transaction_id, new_callref++);
3720 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003721 DEBUGP(DCC, "No memory for trans.\n");
3722 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003723 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003724 GSM48_MT_CC_RELEASE_COMPL);
3725 return -ENOMEM;
3726 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003727 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003728 trans->lchan = lchan;
3729 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003730 }
3731
3732 /* find function for current state and message */
3733 for (i = 0; i < DATASLLEN; i++)
3734 if ((msg_type == datastatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003735 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003736 break;
3737 if (i == DATASLLEN) {
3738 DEBUGP(DCC, "Message unhandled at this state.\n");
3739 return 0;
3740 }
3741
3742 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003743
3744 return rc;
3745}
3746
Harald Welte52b1f982008-12-23 20:25:15 +00003747/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
Harald Welte (local)daef6062009-08-14 11:41:12 +02003748int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +00003749{
3750 struct gsm48_hdr *gh = msgb_l3(msg);
3751 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003752 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003753
3754 switch (pdisc) {
3755 case GSM48_PDISC_CC:
3756 rc = gsm0408_rcv_cc(msg);
3757 break;
3758 case GSM48_PDISC_MM:
3759 rc = gsm0408_rcv_mm(msg);
3760 break;
3761 case GSM48_PDISC_RR:
3762 rc = gsm0408_rcv_rr(msg);
3763 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003764 case GSM48_PDISC_SMS:
Harald Welte (local)daef6062009-08-14 11:41:12 +02003765 rc = gsm0411_rcv_sms(msg, link_id);
Harald Weltebcae43f2008-12-27 21:45:37 +00003766 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003767 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003768 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003769 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3770 pdisc);
3771 break;
3772 default:
3773 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3774 pdisc);
3775 break;
3776 }
3777
3778 return rc;
3779}
Harald Welte8470bf22008-12-25 23:28:35 +00003780
Harald Welte8470bf22008-12-25 23:28:35 +00003781/* Section 9.1.8 / Table 9.9 */
3782struct chreq {
3783 u_int8_t val;
3784 u_int8_t mask;
3785 enum chreq_type type;
3786};
3787
3788/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3789static const struct chreq chreq_type_neci1[] = {
3790 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3791 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3792 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3793 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3794 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3795 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3796 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3797 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3798 { 0x10, 0xf0, CHREQ_T_SDCCH },
3799 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3800 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3801 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3802};
3803
3804/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3805static const struct chreq chreq_type_neci0[] = {
3806 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3807 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3808 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3809 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3810 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3811 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3812 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3813 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3814};
3815
3816static const enum gsm_chan_t ctype_by_chreq[] = {
3817 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3818 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3819 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3820 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3821 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3822 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3823 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3824 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3825 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3826 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3827 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3828 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3829};
3830
Harald Weltee14a57c2008-12-29 04:08:28 +00003831static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3832 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3833 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3834 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3835 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3836 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3837 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3838 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3839 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3840 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3841 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3842 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3843 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3844};
3845
Harald Welte8470bf22008-12-25 23:28:35 +00003846enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3847{
3848 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003849 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte8470bf22008-12-25 23:28:35 +00003850
Harald Weltee58ca7c2009-08-10 02:14:46 +02003851 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3852 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte8470bf22008-12-25 23:28:35 +00003853 if ((ra & chr->mask) == chr->val)
3854 return ctype_by_chreq[chr->type];
3855 }
3856 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3857 return GSM_LCHAN_SDCCH;
3858}
Harald Weltee14a57c2008-12-29 04:08:28 +00003859
3860enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3861{
3862 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003863 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Weltee14a57c2008-12-29 04:08:28 +00003864
Harald Weltee58ca7c2009-08-10 02:14:46 +02003865 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3866 const struct chreq *chr = &chreq_type_neci0[i];
Harald Weltee14a57c2008-12-29 04:08:28 +00003867 if ((ra & chr->mask) == chr->val)
3868 return reason_by_chreq[chr->type];
3869 }
3870 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3871 return GSM_CHREQ_REASON_OTHER;
3872}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003873
3874/* dequeue messages to layer 4 */
3875int bsc_upqueue(struct gsm_network *net)
3876{
3877 struct gsm_mncc *mncc;
3878 struct msgb *msg;
3879 int work = 0;
3880
3881 if (net)
3882 while ((msg = msgb_dequeue(&net->upqueue))) {
3883 mncc = (struct gsm_mncc *)msg->data;
3884 if (net->mncc_recv)
3885 net->mncc_recv(net, mncc->msg_type, mncc);
3886 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003887 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003888 }
3889
3890 return work;
3891}
Harald Weltedcaf5652009-07-23 18:56:43 +02003892
Harald Welte805f6442009-07-28 18:25:29 +02003893/*
3894 * This will be ran by the linker when loading the DSO. We use it to
3895 * do system initialization, e.g. registration of signal handlers.
3896 */
3897static __attribute__((constructor)) void on_dso_load_0408(void)
3898{
3899 tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
3900 "loc_updating_oper");
3901 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3902 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3903}