blob: 63603934b6c29ba0f0095b6018fb41a542c11236 [file] [log] [blame]
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
Harald Welte52b1f982008-12-23 20:25:15 +00002 * 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>
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01005 * (C) 2008-2012 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
Harald Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Welte52b1f982008-12-23 20:25:15 +000012 * (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
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte52b1f982008-12-23 20:25:15 +000018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte52b1f982008-12-23 20:25:15 +000021 *
22 */
23
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <errno.h>
Harald Weltedb253af2008-12-30 17:56:55 +000029#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000030#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000031
Harald Welte9c3dc902012-04-08 16:59:24 +020032#include "bscconfig.h"
33
Sylvain Munaut30a15382009-12-24 00:27:26 +010034#include <openbsc/auth.h>
Harald Welte75a983f2008-12-27 21:34:06 +000035#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000040#include <openbsc/gsm_04_08.h>
Holger Hans Peter Freythere0009f12010-08-12 01:41:57 +080041#include <openbsc/gsm_04_80.h>
Harald Welte8470bf22008-12-25 23:28:35 +000042#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>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020046#include <osmocom/abis/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 Weltedcaf5652009-07-23 18:56:43 +020049#include <openbsc/transaction.h>
Harald Welte6eafe912009-10-16 08:32:58 +020050#include <openbsc/ussd.h>
Harald Welte51008772009-12-29 11:49:12 +010051#include <openbsc/silent_call.h>
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +080052#include <openbsc/bsc_api.h>
Holger Hans Peter Freyther88519ea2010-06-30 12:44:07 +080053#include <openbsc/osmo_msc.h>
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +010054#include <openbsc/handover.h>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020055#include <osmocom/abis/e1_input.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010056#include <osmocom/core/bitvec.h>
Holger Hans Peter Freyther841c2002010-09-30 18:52:23 +080057
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010058#include <osmocom/gsm/gsm48.h>
59#include <osmocom/gsm/gsm0480.h>
60#include <osmocom/gsm/gsm_utils.h>
61#include <osmocom/core/msgb.h>
62#include <osmocom/core/talloc.h>
63#include <osmocom/gsm/tlv.h>
Harald Welte52b1f982008-12-23 20:25:15 +000064
Holger Hans Peter Freyther1e61b252013-07-06 11:45:38 +020065#include <assert.h>
66
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020067void *tall_locop_ctx;
Sylvain Munaut30a15382009-12-24 00:27:26 +010068void *tall_authciphop_ctx;
Harald Welte2cf161b2009-06-20 22:36:41 +020069
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020070int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, uint32_t tmsi);
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +080071static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020072 uint8_t pdisc, uint8_t msg_type);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +010073static void schedule_reject(struct gsm_subscriber_connection *conn);
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +080074static void release_anchor(struct gsm_subscriber_connection *conn);
Harald Welte65e74cc2008-12-29 01:55:35 +000075
Harald Welte52b1f982008-12-23 20:25:15 +000076struct gsm_lai {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020077 uint16_t mcc;
78 uint16_t mnc;
79 uint16_t lac;
Harald Welte52b1f982008-12-23 20:25:15 +000080};
81
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020082static uint32_t new_callref = 0x80000001;
Harald Welte4bfdfe72009-06-10 23:11:52 +080083
Harald Welte31c00f72011-03-03 23:29:05 +010084void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg)
85{
86 net->mncc_recv(net, msg);
87}
88
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +080089static int gsm48_conn_sendmsg(struct msgb *msg, struct gsm_subscriber_connection *conn,
90 struct gsm_trans *trans)
91{
92 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
93
94 /* if we get passed a transaction reference, do some common
95 * work that the caller no longer has to do */
96 if (trans) {
97 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
98 msg->lchan = trans->conn->lchan;
99 }
100
101
102 if (msg->lchan) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200103 struct e1inp_sign_link *sign_link =
104 msg->lchan->ts->trx->rsl_link;
105
106 msg->dst = sign_link;
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +0800107 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
108 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200109 "Sending '%s' to MS.\n",
110 sign_link->trx->bts->nr,
111 sign_link->trx->nr, msg->lchan->ts->nr,
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +0800112 gh->proto_discr & 0xf0,
113 gsm48_cc_msg_name(gh->msg_type));
114 else
115 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200116 "Sending 0x%02x to MS.\n",
117 sign_link->trx->bts->nr,
118 sign_link->trx->nr, msg->lchan->ts->nr,
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +0800119 gh->proto_discr, gh->msg_type);
120 }
121
Holger Hans Peter Freyther8d380dc2010-11-10 10:16:02 +0100122 return gsm0808_submit_dtap(conn, msg, 0, 0);
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +0800123}
Sylvain Munaut30a15382009-12-24 00:27:26 +0100124
Holger Hans Peter Freythere0009f12010-08-12 01:41:57 +0800125int gsm48_cc_tx_notify_ss(struct gsm_trans *trans, const char *message)
126{
127 struct gsm48_hdr *gh;
128 struct msgb *ss_notify;
129
130 ss_notify = gsm0480_create_notifySS(message);
131 if (!ss_notify)
132 return -1;
133
134 gsm0480_wrap_invoke(ss_notify, GSM0480_OP_CODE_NOTIFY_SS, 0);
135 uint8_t *data = msgb_push(ss_notify, 1);
136 data[0] = ss_notify->len - 1;
137 gh = (struct gsm48_hdr *) msgb_push(ss_notify, sizeof(*gh));
138 gh->msg_type = GSM48_MT_CC_FACILITY;
139 return gsm48_conn_sendmsg(ss_notify, trans->conn, trans);
140}
141
Harald Weltecf149ee2012-01-23 16:40:24 +0100142void release_security_operation(struct gsm_subscriber_connection *conn)
Sylvain Munaut30a15382009-12-24 00:27:26 +0100143{
144 if (!conn->sec_operation)
145 return;
146
147 talloc_free(conn->sec_operation);
148 conn->sec_operation = NULL;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800149 msc_release_connection(conn);
Sylvain Munaut30a15382009-12-24 00:27:26 +0100150}
151
Harald Weltecf149ee2012-01-23 16:40:24 +0100152void allocate_security_operation(struct gsm_subscriber_connection *conn)
Sylvain Munaut30a15382009-12-24 00:27:26 +0100153{
Sylvain Munaut30a15382009-12-24 00:27:26 +0100154 conn->sec_operation = talloc_zero(tall_authciphop_ctx,
155 struct gsm_security_operation);
156}
157
Sylvain Munaut0fbfd1b2010-12-01 22:37:05 +0100158int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
159 gsm_cbfn *cb, void *cb_data)
Sylvain Munaut30a15382009-12-24 00:27:26 +0100160{
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800161 struct gsm_network *net = conn->bts->network;
162 struct gsm_subscriber *subscr = conn->subscr;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100163 struct gsm_security_operation *op;
164 struct gsm_auth_tuple atuple;
165 int status = -1, rc;
166
167 /* Check if we _can_ enable encryption. Cases where we can't:
168 * - Encryption disabled in config
169 * - Channel already secured (nothing to do)
170 * - Subscriber equipment doesn't support configured encryption
171 */
172 if (!net->a5_encryption) {
173 status = GSM_SECURITY_NOAVAIL;
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800174 } else if (conn->lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Sylvain Munaut30a15382009-12-24 00:27:26 +0100175 DEBUGP(DMM, "Requesting to secure an already secure channel");
Andreas Eversberg641475c2013-07-10 08:58:03 +0200176 status = GSM_SECURITY_ALREADY;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100177 } else if (!ms_cm2_a5n_support(subscr->equipment.classmark2,
178 net->a5_encryption)) {
179 DEBUGP(DMM, "Subscriber equipment doesn't support requested encryption");
180 status = GSM_SECURITY_NOAVAIL;
181 }
182
183 /* If not done yet, try to get info for this user */
184 if (status < 0) {
185 rc = auth_get_tuple_for_subscr(&atuple, subscr, key_seq);
186 if (rc <= 0)
187 status = GSM_SECURITY_NOAVAIL;
188 }
189
190 /* Are we done yet ? */
191 if (status >= 0)
192 return cb ?
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800193 cb(GSM_HOOK_RR_SECURITY, status, NULL, conn, cb_data) :
Sylvain Munaut30a15382009-12-24 00:27:26 +0100194 0;
195
196 /* Start an operation (can't have more than one pending !!!) */
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800197 if (conn->sec_operation)
Sylvain Munaut30a15382009-12-24 00:27:26 +0100198 return -EBUSY;
199
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800200 allocate_security_operation(conn);
201 op = conn->sec_operation;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100202 op->cb = cb;
203 op->cb_data = cb_data;
204 memcpy(&op->atuple, &atuple, sizeof(struct gsm_auth_tuple));
205
206 /* FIXME: Should start a timer for completion ... */
207
208 /* Then do whatever is needed ... */
Harald Welte86dda082010-12-23 18:07:49 +0100209 if (rc == AUTH_DO_AUTH_THAN_CIPH) {
Sylvain Munaut30a15382009-12-24 00:27:26 +0100210 /* Start authentication */
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800211 return gsm48_tx_mm_auth_req(conn, op->atuple.rand, op->atuple.key_seq);
Harald Welte86dda082010-12-23 18:07:49 +0100212 } else if (rc == AUTH_DO_CIPH) {
Sylvain Munaut30a15382009-12-24 00:27:26 +0100213 /* Start ciphering directly */
Sylvain Munaut67706df2010-11-29 08:19:04 +0100214 return gsm0808_cipher_mode(conn, net->a5_encryption,
215 op->atuple.kc, 8, 0);
Sylvain Munaut30a15382009-12-24 00:27:26 +0100216 }
217
218 return -EINVAL; /* not reached */
219}
220
Holger Freyther73487a22008-12-31 18:53:57 +0000221static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
222 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000223{
224 if (!subscriber)
225 return 0;
226
Holger Freyther73487a22008-12-31 18:53:57 +0000227 /*
228 * Do not send accept yet as more information should arrive. Some
229 * phones will not send us the information and we will have to check
230 * what we want to do with that.
231 */
232 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
233 return 0;
234
Jan Luebbe06513f22009-08-12 12:48:00 +0200235 switch (subscriber->net->auth_policy) {
236 case GSM_AUTH_POLICY_CLOSED:
237 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200238 case GSM_AUTH_POLICY_TOKEN:
Harald Welte (local)ee9afe32009-08-13 20:44:23 +0200239 if (subscriber->authorized)
240 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200241 return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT);
Jan Luebbe06513f22009-08-12 12:48:00 +0200242 case GSM_AUTH_POLICY_ACCEPT_ALL:
Holger Freyther89824fc2008-12-30 16:18:18 +0000243 return 1;
Jan Luebbe06513f22009-08-12 12:48:00 +0200244 default:
245 return 0;
246 }
Holger Freyther89824fc2008-12-30 16:18:18 +0000247}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000248
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100249static void release_loc_updating_req(struct gsm_subscriber_connection *conn)
Holger Freyther73487a22008-12-31 18:53:57 +0000250{
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100251 if (!conn->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000252 return;
253
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +0800254 /* No need to keep the connection up */
255 release_anchor(conn);
256
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200257 osmo_timer_del(&conn->loc_operation->updating_timer);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100258 talloc_free(conn->loc_operation);
Holger Hans Peter Freytherf93e8fa2010-12-22 08:53:28 +0100259 conn->loc_operation = NULL;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800260 msc_release_connection(conn);
Holger Freyther73487a22008-12-31 18:53:57 +0000261}
262
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100263static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn)
Holger Freyther73487a22008-12-31 18:53:57 +0000264{
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800265 if (conn->loc_operation)
266 LOGP(DMM, LOGL_ERROR, "Connection already had operation.\n");
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100267 release_loc_updating_req(conn);
Holger Freyther73487a22008-12-31 18:53:57 +0000268
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100269 conn->loc_operation = talloc_zero(tall_locop_ctx,
Harald Welte470ec292009-06-26 20:25:23 +0200270 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000271}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000272
Sylvain Munaut267fba02009-12-24 00:28:01 +0100273static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event,
274 struct msgb *msg, void *data, void *param)
275{
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800276 struct gsm_subscriber_connection *conn = data;
Sylvain Munaut267fba02009-12-24 00:28:01 +0100277 int rc = 0;
278
279 switch (event) {
280 case GSM_SECURITY_AUTH_FAILED:
281 release_loc_updating_req(conn);
282 break;
283
Andreas Eversberga874b8d2013-07-10 08:58:03 +0200284 case GSM_SECURITY_ALREADY:
285 LOGP(DMM, LOGL_ERROR, "We don't expect LOCATION "
286 "UPDATING after CM SERVICE REQUEST\n");
287 /* fall through */
288
Sylvain Munaut267fba02009-12-24 00:28:01 +0100289 case GSM_SECURITY_NOAVAIL:
290 case GSM_SECURITY_SUCCEEDED:
291 /* We're all good */
292 db_subscriber_alloc_tmsi(conn->subscr);
Holger Hans Peter Freytherdc5db242010-06-15 14:07:27 +0800293 rc = gsm0408_loc_upd_acc(conn, conn->subscr->tmsi);
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800294 if (conn->bts->network->send_mm_info) {
Sylvain Munaut267fba02009-12-24 00:28:01 +0100295 /* send MM INFO with network name */
Holger Hans Peter Freyther91401742010-06-15 14:16:02 +0800296 rc = gsm48_tx_mm_info(conn);
Sylvain Munaut267fba02009-12-24 00:28:01 +0100297 }
298
299 /* call subscr_update after putting the loc_upd_acc
300 * in the transmit queue, since S_SUBSCR_ATTACHED might
301 * trigger further action like SMS delivery */
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800302 subscr_update(conn->subscr, conn->bts,
Sylvain Munaut267fba02009-12-24 00:28:01 +0100303 GSM_SUBSCRIBER_UPDATE_ATTACHED);
304
Holger Hans Peter Freytherd4e68722010-12-22 12:11:01 +0100305 /*
306 * The gsm0408_loc_upd_acc sends a MI with the TMSI. The
307 * MS needs to respond with a TMSI REALLOCATION COMPLETE
308 * (even if the TMSI is the same).
309 */
Sylvain Munaut267fba02009-12-24 00:28:01 +0100310 break;
311
312 default:
313 rc = -EINVAL;
314 };
315
316 return rc;
317}
318
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100319static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg)
Holger Freytherd51524f2009-06-09 08:27:07 +0000320{
Sylvain Munaut267fba02009-12-24 00:28:01 +0100321 if (authorize_subscriber(conn->loc_operation, conn->subscr))
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800322 return gsm48_secure_channel(conn,
Sylvain Munaut267fba02009-12-24 00:28:01 +0100323 conn->loc_operation->key_seq,
324 _gsm0408_authorize_sec_cb, NULL);
Holger Freytherd51524f2009-06-09 08:27:07 +0000325 return 0;
326}
327
Holger Hans Peter Freytheradb6e1c2010-09-18 06:44:24 +0800328void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
Holger Freyther7c19f742009-06-06 13:54:35 +0000329{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800330 struct gsm_trans *trans, *temp;
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800331
332 /* avoid someone issuing a clear */
333 conn->in_release = 1;
334
Holger Freyther7c19f742009-06-06 13:54:35 +0000335 /*
336 * Cancel any outstanding location updating request
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +0800337 * operation taking place on the subscriber connection.
Holger Freyther7c19f742009-06-06 13:54:35 +0000338 */
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +0800339 release_loc_updating_req(conn);
Holger Hans Peter Freytherc29043e2010-12-28 14:57:20 +0100340
341 /* We might need to cancel the paging response or such. */
342 if (conn->sec_operation && conn->sec_operation->cb) {
343 conn->sec_operation->cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
344 NULL, conn, conn->sec_operation->cb_data);
345 }
346
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +0800347 release_security_operation(conn);
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +0800348 release_anchor(conn);
Holger Freyther7c19f742009-06-06 13:54:35 +0000349
Holger Hans Peter Freyther3e9b2ec2012-12-22 18:45:27 +0100350 /*
351 * Free all transactions that are associated with the released
352 * connection. The transaction code will inform the CC or SMS
353 * facilities that will send the release indications. As part of
354 * the CC REL_IND the remote leg might be released and this will
355 * trigger the call to trans_free. This is something the llist
356 * macro can not handle and we will need to re-iterate the list.
357 *
358 * TODO: Move the trans_list into the subscriber connection and
359 * create a pending list for MT transactions. These exist before
360 * we have a subscriber connection.
361 */
362restart:
Holger Hans Peter Freytherf6fb3ef2010-06-15 13:16:52 +0800363 llist_for_each_entry_safe(trans, temp, &conn->bts->network->trans_list, entry) {
Holger Hans Peter Freyther3e9b2ec2012-12-22 18:45:27 +0100364 if (trans->conn == conn) {
Harald Weltedcaf5652009-07-23 18:56:43 +0200365 trans_free(trans);
Holger Hans Peter Freyther3e9b2ec2012-12-22 18:45:27 +0100366 goto restart;
367 }
Harald Welte4bfdfe72009-06-10 23:11:52 +0800368 }
Holger Freyther7c19f742009-06-06 13:54:35 +0000369}
370
Harald Welte371efe52010-12-22 23:17:50 +0100371void gsm0408_clear_all_trans(struct gsm_network *net, int protocol)
372{
373 struct gsm_trans *trans, *temp;
374
375 LOGP(DCC, LOGL_NOTICE, "Clearing all currently active transactions!!!\n");
376
377 llist_for_each_entry_safe(trans, temp, &net->trans_list, entry) {
Harald Welteeb76c7a2010-12-23 02:47:53 +0100378 if (trans->protocol == protocol) {
379 trans->callref = 0;
Harald Welte371efe52010-12-22 23:17:50 +0100380 trans_free(trans);
Harald Welteeb76c7a2010-12-23 02:47:53 +0100381 }
Harald Welte371efe52010-12-22 23:17:50 +0100382 }
383}
384
Holger Freyther429e7762008-12-30 13:28:30 +0000385/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200386int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +0000387{
Holger Hans Peter Freyther7bc5ba32010-06-15 14:09:34 +0800388 struct gsm_bts *bts = conn->bts;
Holger Hans Peter Freyther230a4d82010-06-15 19:40:05 +0800389 struct msgb *msg;
390
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200391 osmo_counter_inc(bts->network->stats.loc_upd_resp.reject);
Holger Hans Peter Freyther230a4d82010-06-15 19:40:05 +0800392
393 msg = gsm48_create_loc_upd_rej(cause);
394 if (!msg) {
395 LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n");
396 return -1;
397 }
Harald Welte52b1f982008-12-23 20:25:15 +0000398
Holger Hans Peter Freyther7bc5ba32010-06-15 14:09:34 +0800399 msg->lchan = conn->lchan;
Harald Welte52b1f982008-12-23 20:25:15 +0000400
Harald Welte (local)198d5ad2009-12-26 22:15:28 +0100401 LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100402 "LAC=%u BTS=%u\n", conn->subscr ?
403 subscr_name(conn->subscr) : "unknown",
Holger Hans Peter Freyther7bc5ba32010-06-15 14:09:34 +0800404 bts->location_area_code, bts->nr);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100405
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +0800406 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +0000407}
408
409/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200410int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, uint32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000411{
Holger Hans Peter Freytherdc5db242010-06-15 14:07:27 +0800412 struct gsm_bts *bts = conn->bts;
Harald Welte8470bf22008-12-25 23:28:35 +0000413 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000414 struct gsm48_hdr *gh;
415 struct gsm48_loc_area_id *lai;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200416 uint8_t *mid;
Harald Welte52b1f982008-12-23 20:25:15 +0000417
Holger Hans Peter Freytherdc5db242010-06-15 14:07:27 +0800418 msg->lchan = conn->lchan;
Harald Welte52b1f982008-12-23 20:25:15 +0000419
420 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
421 gh->proto_discr = GSM48_PDISC_MM;
422 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
423
424 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Harald Welteafedeab2010-03-04 10:55:40 +0100425 gsm48_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +0000426 bts->network->network_code, bts->location_area_code);
427
Holger Hans Peter Freyther1494a762009-08-01 07:26:59 +0200428 mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200429 gsm48_generate_mid_from_tmsi(mid, tmsi);
Harald Welte52b1f982008-12-23 20:25:15 +0000430
431 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
432
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200433 osmo_counter_inc(bts->network->stats.loc_upd_resp.accept);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100434
Holger Hans Peter Freytherdc5db242010-06-15 14:07:27 +0800435 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +0000436}
437
Harald Weltebf5e8df2009-02-03 12:59:45 +0000438/* Transmit Chapter 9.2.10 Identity Request */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200439static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id_type)
Harald Welte231ad4f2008-12-27 11:15:38 +0000440{
441 struct msgb *msg = gsm48_msgb_alloc();
442 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +0000443
Holger Hans Peter Freytherd521d972010-06-15 14:11:01 +0800444 msg->lchan = conn->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +0000445
446 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
447 gh->proto_discr = GSM48_PDISC_MM;
448 gh->msg_type = GSM48_MT_MM_ID_REQ;
449 gh->data[0] = id_type;
450
Holger Hans Peter Freytherd521d972010-06-15 14:11:01 +0800451 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +0000452}
453
Harald Welte231ad4f2008-12-27 11:15:38 +0000454
Harald Weltebf5e8df2009-02-03 12:59:45 +0000455/* Parse Chapter 9.2.11 Identity Response */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800456static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte231ad4f2008-12-27 11:15:38 +0000457{
458 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +0000459 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +0200460 struct gsm_bts *bts = lchan->ts->trx->bts;
461 struct gsm_network *net = bts->network;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200462 uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200463 char mi_string[GSM48_MI_SIZE];
Harald Welte231ad4f2008-12-27 11:15:38 +0000464
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200465 gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +0000466 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +0000467 mi_type, mi_string);
468
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200469 osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
Harald Welte7659de12009-12-13 12:39:18 +0100470
Harald Welte75a983f2008-12-27 21:34:06 +0000471 switch (mi_type) {
472 case GSM_MI_TYPE_IMSI:
Jan Luebbe370b41d2009-08-12 10:19:34 +0200473 /* look up subscriber based on IMSI, create if not found */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100474 if (!conn->subscr) {
475 conn->subscr = subscr_get_by_imsi(net, mi_string);
476 if (!conn->subscr)
Holger Hans Peter Freyther7634ec12013-10-04 08:35:11 +0200477 conn->subscr = subscr_create_subscriber(net, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +0200478 }
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100479 if (conn->loc_operation)
480 conn->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +0000481 break;
482 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +0000483 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +0000484 /* update subscribe <-> IMEI mapping */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100485 if (conn->subscr) {
486 db_subscriber_assoc_imei(conn->subscr, mi_string);
487 db_sync_equipment(&conn->subscr->equipment);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200488 }
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100489 if (conn->loc_operation)
490 conn->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +0000491 break;
492 }
Holger Freyther73487a22008-12-31 18:53:57 +0000493
494 /* Check if we can let the mobile station enter */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100495 return gsm0408_authorize(conn, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +0000496}
497
Harald Welte255539c2008-12-28 02:26:27 +0000498
499static void loc_upd_rej_cb(void *data)
500{
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100501 struct gsm_subscriber_connection *conn = data;
502 struct gsm_lchan *lchan = conn->lchan;
Harald Welte1085c092009-11-18 20:33:19 +0100503 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte255539c2008-12-28 02:26:27 +0000504
Holger Hans Peter Freyther2692e3b2011-11-07 12:26:29 +0100505 LOGP(DMM, LOGL_DEBUG, "Location Updating Request procedure timedout.\n");
Holger Hans Peter Freyther7bc5ba32010-06-15 14:09:34 +0800506 gsm0408_loc_upd_rej(conn, bts->network->reject_cause);
Holger Hans Peter Freyther01288432010-06-16 12:52:28 +0800507 release_loc_updating_req(conn);
Harald Welte255539c2008-12-28 02:26:27 +0000508}
509
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100510static void schedule_reject(struct gsm_subscriber_connection *conn)
Holger Freytherb7193e42008-12-29 17:44:08 +0000511{
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100512 conn->loc_operation->updating_timer.cb = loc_upd_rej_cb;
513 conn->loc_operation->updating_timer.data = conn;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200514 osmo_timer_schedule(&conn->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +0000515}
516
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200517static const char *lupd_name(uint8_t type)
Harald Welte2a139372009-02-22 21:14:55 +0000518{
519 switch (type) {
520 case GSM48_LUPD_NORMAL:
521 return "NORMAL";
522 case GSM48_LUPD_PERIODIC:
Alexander Chemerisa3d41c92013-10-04 02:42:26 +0200523 return "PERIODIC";
Harald Welte2a139372009-02-22 21:14:55 +0000524 case GSM48_LUPD_IMSI_ATT:
525 return "IMSI ATTACH";
526 default:
527 return "UNKNOWN";
528 }
529}
530
Harald Weltebf5e8df2009-02-03 12:59:45 +0000531/* Chapter 9.2.15: Receive Location Updating Request */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800532static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000533{
Harald Welte8470bf22008-12-25 23:28:35 +0000534 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000535 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800536 struct gsm_subscriber *subscr = NULL;
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800537 struct gsm_bts *bts = conn->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200538 uint8_t mi_type;
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200539 char mi_string[GSM48_MI_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000540
Harald Welte8470bf22008-12-25 23:28:35 +0000541 lu = (struct gsm48_loc_upd_req *) gh->data;
542
543 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +0000544
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200545 gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
Harald Weltefc977a82008-12-27 10:19:37 +0000546
Harald Weltea0368542009-06-27 02:58:43 +0200547 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +0000548 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +0000549
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200550 osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, &lu->mi_len);
Harald Welte7659de12009-12-13 12:39:18 +0100551
Harald Welte24ff6ee2009-12-22 00:41:05 +0100552 switch (lu->type) {
553 case GSM48_LUPD_NORMAL:
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200554 osmo_counter_inc(bts->network->stats.loc_upd_type.normal);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100555 break;
556 case GSM48_LUPD_IMSI_ATT:
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200557 osmo_counter_inc(bts->network->stats.loc_upd_type.attach);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100558 break;
559 case GSM48_LUPD_PERIODIC:
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200560 osmo_counter_inc(bts->network->stats.loc_upd_type.periodic);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100561 break;
562 }
563
Holger Freythereaf04692009-06-06 13:54:44 +0000564 /*
565 * Pseudo Spoof detection: Just drop a second/concurrent
566 * location updating request.
567 */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100568 if (conn->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +0200569 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100570 conn->loc_operation);
Holger Hans Peter Freyther7bc5ba32010-06-15 14:09:34 +0800571 gsm0408_loc_upd_rej(conn, GSM48_REJECT_PROTOCOL_ERROR);
Holger Freythereaf04692009-06-06 13:54:44 +0000572 return 0;
573 }
574
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800575 allocate_loc_updating_req(conn);
Holger Freyther73487a22008-12-31 18:53:57 +0000576
Sylvain Munaut2030a2a2010-06-10 13:36:59 +0200577 conn->loc_operation->key_seq = lu->key_seq;
578
Harald Welte52b1f982008-12-23 20:25:15 +0000579 switch (mi_type) {
580 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +0200581 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +0000582 /* we always want the IMEI, too */
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +0200583 mm_tx_identity_req(conn, GSM_MI_TYPE_IMEI);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100584 conn->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000585
Jan Luebbe370b41d2009-08-12 10:19:34 +0200586 /* look up subscriber based on IMSI, create if not found */
587 subscr = subscr_get_by_imsi(bts->network, mi_string);
588 if (!subscr) {
Holger Hans Peter Freyther7634ec12013-10-04 08:35:11 +0200589 subscr = subscr_create_subscriber(bts->network, mi_string);
Jan Luebbe370b41d2009-08-12 10:19:34 +0200590 }
Harald Welte4b634542008-12-27 01:55:51 +0000591 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000592 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +0200593 DEBUGPC(DMM, "\n");
Harald Welte52b1f982008-12-23 20:25:15 +0000594 /* look up the subscriber based on TMSI, request IMSI if it fails */
Holger Hans Peter Freyther22230252009-08-19 12:53:57 +0200595 subscr = subscr_get_by_tmsi(bts->network,
596 tmsi_from_string(mi_string));
Harald Welte52b1f982008-12-23 20:25:15 +0000597 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +0000598 /* send IDENTITY REQUEST message to get IMSI */
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +0200599 mm_tx_identity_req(conn, GSM_MI_TYPE_IMSI);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100600 conn->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +0000601 }
Harald Weltef5f512c2010-06-07 17:56:32 +0200602 /* we always want the IMEI, too */
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +0200603 mm_tx_identity_req(conn, GSM_MI_TYPE_IMEI);
Harald Weltef5f512c2010-06-07 17:56:32 +0200604 conn->loc_operation->waiting_for_imei = 1;
Harald Welte52b1f982008-12-23 20:25:15 +0000605 break;
606 case GSM_MI_TYPE_IMEI:
607 case GSM_MI_TYPE_IMEISV:
608 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +0200609 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +0000610 break;
611 default:
Harald Weltea0368542009-06-27 02:58:43 +0200612 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +0000613 break;
614 }
615
Harald Welte24516ea2009-07-04 10:18:00 +0200616 /* schedule the reject timer */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100617 schedule_reject(conn);
Harald Welte24516ea2009-07-04 10:18:00 +0200618
Harald Welte4bfdfe72009-06-10 23:11:52 +0800619 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +0200620 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +0800621 /* FIXME: request id? close channel? */
622 return -EINVAL;
623 }
624
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100625 conn->subscr = subscr;
626 conn->subscr->equipment.classmark1 = lu->classmark1;
Harald Welte255539c2008-12-28 02:26:27 +0000627
Harald Welte24516ea2009-07-04 10:18:00 +0200628 /* check if we can let the subscriber into our network immediately
629 * or if we need to wait for identity responses. */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100630 return gsm0408_authorize(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000631}
632
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100633/* Turn int into semi-octet representation: 98 => 0x89 */
634static uint8_t bcdify(uint8_t value)
Harald Welte4bfdfe72009-06-10 23:11:52 +0800635{
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100636 uint8_t ret;
637
638 ret = value / 10;
639 ret |= (value % 10) << 4;
640
641 return ret;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800642}
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100643
Harald Welte4bfdfe72009-06-10 23:11:52 +0800644
Harald Weltedb253af2008-12-30 17:56:55 +0000645/* Section 9.2.15a */
Holger Hans Peter Freyther91401742010-06-15 14:16:02 +0800646int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
Harald Weltedb253af2008-12-30 17:56:55 +0000647{
648 struct msgb *msg = gsm48_msgb_alloc();
649 struct gsm48_hdr *gh;
Holger Hans Peter Freyther91401742010-06-15 14:16:02 +0800650 struct gsm_network *net = conn->bts->network;
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100651 struct gsm_bts *bts = conn->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200652 uint8_t *ptr8;
Daniel Willmanneea93372009-08-13 03:42:07 +0200653 int name_len, name_pad;
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100654
Harald Welte4bfdfe72009-06-10 23:11:52 +0800655 time_t cur_t;
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100656 struct tm* gmt_time;
657 struct tm* local_time;
658 int tzunits;
Harald Weltedb253af2008-12-30 17:56:55 +0000659
Holger Hans Peter Freyther91401742010-06-15 14:16:02 +0800660 msg->lchan = conn->lchan;
Harald Weltedb253af2008-12-30 17:56:55 +0000661
662 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
663 gh->proto_discr = GSM48_PDISC_MM;
664 gh->msg_type = GSM48_MT_MM_INFO;
665
666 if (net->name_long) {
Daniel Willmanneea93372009-08-13 03:42:07 +0200667#if 0
Harald Weltedb253af2008-12-30 17:56:55 +0000668 name_len = strlen(net->name_long);
669 /* 10.5.3.5a */
670 ptr8 = msgb_put(msg, 3);
671 ptr8[0] = GSM48_IE_NAME_LONG;
672 ptr8[1] = name_len*2 +1;
673 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
674
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200675 ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +0000676 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +0000677 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +0000678
679 /* FIXME: Use Cell Broadcast, not UCS-2, since
680 * UCS-2 is only supported by later revisions of the spec */
Daniel Willmanneea93372009-08-13 03:42:07 +0200681#endif
682 name_len = (strlen(net->name_long)*7)/8;
683 name_pad = (8 - strlen(net->name_long)*7)%8;
684 if (name_pad > 0)
685 name_len++;
686 /* 10.5.3.5a */
687 ptr8 = msgb_put(msg, 3);
688 ptr8[0] = GSM48_IE_NAME_LONG;
689 ptr8[1] = name_len +1;
690 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
691
692 ptr8 = msgb_put(msg, name_len);
693 gsm_7bit_encode(ptr8, net->name_long);
694
Harald Weltedb253af2008-12-30 17:56:55 +0000695 }
696
697 if (net->name_short) {
Daniel Willmanneea93372009-08-13 03:42:07 +0200698#if 0
Harald Weltedb253af2008-12-30 17:56:55 +0000699 name_len = strlen(net->name_short);
700 /* 10.5.3.5a */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200701 ptr8 = (uint8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +0200702 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +0000703 ptr8[1] = name_len*2 + 1;
704 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
705
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200706 ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +0000707 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +0000708 ptr16[i] = htons(net->name_short[i]);
Daniel Willmanneea93372009-08-13 03:42:07 +0200709#endif
710 name_len = (strlen(net->name_short)*7)/8;
711 name_pad = (8 - strlen(net->name_short)*7)%8;
712 if (name_pad > 0)
713 name_len++;
714 /* 10.5.3.5a */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200715 ptr8 = (uint8_t *) msgb_put(msg, 3);
Daniel Willmanneea93372009-08-13 03:42:07 +0200716 ptr8[0] = GSM48_IE_NAME_SHORT;
717 ptr8[1] = name_len +1;
718 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
719
720 ptr8 = msgb_put(msg, name_len);
721 gsm_7bit_encode(ptr8, net->name_short);
722
Harald Weltedb253af2008-12-30 17:56:55 +0000723 }
724
Harald Weltedb253af2008-12-30 17:56:55 +0000725 /* Section 10.5.3.9 */
726 cur_t = time(NULL);
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100727 gmt_time = gmtime(&cur_t);
728
Harald Weltedb253af2008-12-30 17:56:55 +0000729 ptr8 = msgb_put(msg, 8);
730 ptr8[0] = GSM48_IE_NET_TIME_TZ;
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100731 ptr8[1] = bcdify(gmt_time->tm_year % 100);
732 ptr8[2] = bcdify(gmt_time->tm_mon + 1);
733 ptr8[3] = bcdify(gmt_time->tm_mday);
734 ptr8[4] = bcdify(gmt_time->tm_hour);
735 ptr8[5] = bcdify(gmt_time->tm_min);
736 ptr8[6] = bcdify(gmt_time->tm_sec);
737
Harald Welte45f91712012-07-08 16:48:11 +0200738 if (bts->tz.override) {
739 /* Convert tz.hr and tz.mn to units */
740 if (bts->tz.hr < 0) {
741 tzunits = ((bts->tz.hr/-1)*4);
742 tzunits = tzunits + (bts->tz.mn/15);
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100743 ptr8[7] = bcdify(tzunits);
744 /* Set negative time */
745 ptr8[7] |= 0x08;
746 }
747 else {
Harald Welte45f91712012-07-08 16:48:11 +0200748 tzunits = bts->tz.hr*4;
749 tzunits = tzunits + (bts->tz.mn/15);
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100750 ptr8[7] = bcdify(tzunits);
751 }
752 }
753 else {
754 /* Need to get GSM offset and convert into 15 min units */
755 /* This probably breaks if gmtoff returns a value not evenly divisible by 15? */
756 local_time = localtime(&cur_t);
Harald Welte9c3dc902012-04-08 16:59:24 +0200757#ifdef HAVE_TM_GMTOFF_IN_TM
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100758 tzunits = (local_time->tm_gmtoff/60)/15;
Harald Welte9c3dc902012-04-08 16:59:24 +0200759#else
760#warning find a portable way to obtain the timezone offset
761 tzunits = 0;
762#endif
Gus Bourg1c5dd2c2011-12-02 10:18:17 +0100763 if (tzunits < 0) {
764 tzunits = tzunits/-1;
765 ptr8[7] = bcdify(tzunits);
766 /* Flip it to negative */
767 ptr8[7] |= 0x08;
768 }
769 else
770 ptr8[7] = bcdify(tzunits);
771 }
Harald Weltedb253af2008-12-30 17:56:55 +0000772
Daniel Willmanneea93372009-08-13 03:42:07 +0200773 DEBUGP(DMM, "-> MM INFO\n");
774
Holger Hans Peter Freyther91401742010-06-15 14:16:02 +0800775 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +0000776}
777
Harald Welte7984d5c2009-08-12 22:56:50 +0200778/* Section 9.2.2 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200779int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq)
Harald Welte7984d5c2009-08-12 22:56:50 +0200780{
781 struct msgb *msg = gsm48_msgb_alloc();
782 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Sylvain Munaut849f5542009-09-27 11:10:17 +0200783 struct gsm48_auth_req *ar = (struct gsm48_auth_req *) msgb_put(msg, sizeof(*ar));
Harald Welte7984d5c2009-08-12 22:56:50 +0200784
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200785 DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", osmo_hexdump(rand, 16));
Harald Welte7984d5c2009-08-12 22:56:50 +0200786
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +0800787 msg->lchan = conn->lchan;
Harald Welte7984d5c2009-08-12 22:56:50 +0200788 gh->proto_discr = GSM48_PDISC_MM;
789 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
790
Sylvain Munautbd55a6d2009-12-24 00:23:46 +0100791 ar->key_seq = key_seq;
Sylvain Munaut849f5542009-09-27 11:10:17 +0200792
Harald Welte7984d5c2009-08-12 22:56:50 +0200793 /* 16 bytes RAND parameters */
Harald Welte7984d5c2009-08-12 22:56:50 +0200794 if (rand)
Sylvain Munaut849f5542009-09-27 11:10:17 +0200795 memcpy(ar->rand, rand, 16);
Harald Welte7984d5c2009-08-12 22:56:50 +0200796
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +0800797 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte7984d5c2009-08-12 22:56:50 +0200798}
799
800/* Section 9.2.1 */
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +0800801int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn)
Harald Welte7984d5c2009-08-12 22:56:50 +0200802{
803 DEBUGP(DMM, "-> AUTH REJECT\n");
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +0800804 return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
Harald Welte7984d5c2009-08-12 22:56:50 +0200805}
806
Sylvain Munautba87f452009-12-24 00:28:46 +0100807static int _gsm48_rx_mm_serv_req_sec_cb(
808 unsigned int hooknum, unsigned int event,
809 struct msgb *msg, void *data, void *param)
810{
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800811 struct gsm_subscriber_connection *conn = data;
Sylvain Munautba87f452009-12-24 00:28:46 +0100812 int rc = 0;
813
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200814 /* auth failed or succeeded, the timer was stopped */
815 conn->expire_timer_stopped = 1;
816
Sylvain Munautba87f452009-12-24 00:28:46 +0100817 switch (event) {
818 case GSM_SECURITY_AUTH_FAILED:
819 /* Nothing to do */
820 break;
821
822 case GSM_SECURITY_NOAVAIL:
Andreas Eversberg641475c2013-07-10 08:58:03 +0200823 case GSM_SECURITY_ALREADY:
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800824 rc = gsm48_tx_mm_serv_ack(conn);
Sylvain Munautba87f452009-12-24 00:28:46 +0100825 break;
826
827 case GSM_SECURITY_SUCCEEDED:
828 /* nothing to do. CIPHER MODE COMMAND is
829 * implicit CM SERV ACK */
830 break;
831
832 default:
833 rc = -EINVAL;
834 };
835
836 return rc;
837}
838
Harald Welte4ed0e922009-01-10 03:17:30 +0000839/*
840 * Handle CM Service Requests
841 * a) Verify that the packet is long enough to contain the information
842 * we require otherwsie reject with INCORRECT_MESSAGE
843 * b) Try to parse the TMSI. If we do not have one reject
844 * c) Check that we know the subscriber with the TMSI otherwise reject
845 * with a HLR cause
846 * d) Set the subscriber on the gsm_lchan and accept
847 */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800848static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte4b634542008-12-27 01:55:51 +0000849{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200850 uint8_t mi_type;
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200851 char mi_string[GSM48_MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +0000852
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800853 struct gsm_bts *bts = conn->bts;
Harald Welteba4cf162009-01-10 01:49:35 +0000854 struct gsm_subscriber *subscr;
855 struct gsm48_hdr *gh = msgb_l3(msg);
856 struct gsm48_service_request *req =
857 (struct gsm48_service_request *)gh->data;
Holger Hans Peter Freyther5d658062010-05-14 08:02:08 +0800858 /* unfortunately in Phase1 the classmark2 length is variable */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200859 uint8_t classmark2_len = gh->data[1];
860 uint8_t *classmark2 = gh->data+2;
861 uint8_t mi_len = *(classmark2 + classmark2_len);
862 uint8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +0000863
Harald Weltec9e02182009-05-01 19:07:53 +0000864 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +0000865 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +0000866 DEBUGPC(DMM, "wrong sized message\n");
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800867 return gsm48_tx_mm_serv_rej(conn,
Harald Welteba4cf162009-01-10 01:49:35 +0000868 GSM48_REJECT_INCORRECT_MESSAGE);
869 }
870
871 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +0000872 DEBUGPC(DMM, "does not fit in packet\n");
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800873 return gsm48_tx_mm_serv_rej(conn,
Harald Welteba4cf162009-01-10 01:49:35 +0000874 GSM48_REJECT_INCORRECT_MESSAGE);
875 }
876
Harald Weltec9e02182009-05-01 19:07:53 +0000877 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +0000878 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +0000879 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800880 return gsm48_tx_mm_serv_rej(conn,
Harald Welteba4cf162009-01-10 01:49:35 +0000881 GSM48_REJECT_INCORRECT_MESSAGE);
882 }
883
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200884 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +0000885 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +0000886 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +0000887
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200888 osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len));
Harald Welte7659de12009-12-13 12:39:18 +0100889
Harald Welte3ac7f102009-08-10 10:12:45 +0200890 if (is_siemens_bts(bts))
891 send_siemens_mrpci(msg->lchan, classmark2-1);
892
Holger Hans Peter Freyther22230252009-08-19 12:53:57 +0200893 subscr = subscr_get_by_tmsi(bts->network,
894 tmsi_from_string(mi_string));
Holger Freythereb443982009-06-04 13:58:42 +0000895
Harald Welte2a139372009-02-22 21:14:55 +0000896 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +0000897 if (!subscr)
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800898 return gsm48_tx_mm_serv_rej(conn,
Harald Welte4ed0e922009-01-10 03:17:30 +0000899 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
Holger Hans Peter Freyther4d2a68c2013-01-01 17:18:27 +0100900 if (subscr->lac == GSM_LAC_RESERVED_DETACHED)
Sylvain Munaut11c1b6e2012-12-28 00:33:04 +0100901 /* If the subscriber is not attached, reject service */
902 return gsm48_tx_mm_serv_rej(conn,
903 GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);
Harald Welte4ed0e922009-01-10 03:17:30 +0000904
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800905 if (!conn->subscr)
906 conn->subscr = subscr;
907 else if (conn->subscr == subscr)
Sylvain Munautea3f6742009-12-18 18:28:10 +0100908 subscr_put(subscr); /* lchan already has a ref, don't need another one */
909 else {
Harald Welte9bb7c702009-01-10 03:21:41 +0000910 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
911 subscr_put(subscr);
912 }
913
Harald Weltec2e302d2009-07-05 14:08:13 +0200914 subscr->equipment.classmark2_len = classmark2_len;
915 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
916 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +0000917
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +0200918 /* we will send a MM message soon */
919 conn->expire_timer_stopped = 1;
920
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800921 return gsm48_secure_channel(conn, req->cipher_key_seq,
Sylvain Munautba87f452009-12-24 00:28:46 +0100922 _gsm48_rx_mm_serv_req_sec_cb, NULL);
Harald Welte4b634542008-12-27 01:55:51 +0000923}
924
Holger Hans Peter Freyther153b13b2012-07-10 08:53:27 +0200925static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte2a139372009-02-22 21:14:55 +0000926{
Holger Hans Peter Freyther153b13b2012-07-10 08:53:27 +0200927 struct gsm_bts *bts = conn->bts;
Harald Welte2a139372009-02-22 21:14:55 +0000928 struct gsm48_hdr *gh = msgb_l3(msg);
929 struct gsm48_imsi_detach_ind *idi =
930 (struct gsm48_imsi_detach_ind *) gh->data;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200931 uint8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200932 char mi_string[GSM48_MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800933 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +0000934
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +0200935 gsm48_mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
Daniel Willmann977cd132012-12-28 19:29:44 +0100936 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s)",
Harald Welte2a139372009-02-22 21:14:55 +0000937 mi_type, mi_string);
938
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200939 osmo_counter_inc(bts->network->stats.loc_upd_type.detach);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100940
Harald Welte2a139372009-02-22 21:14:55 +0000941 switch (mi_type) {
942 case GSM_MI_TYPE_TMSI:
Daniel Willmann977cd132012-12-28 19:29:44 +0100943 DEBUGPC(DMM, "\n");
Holger Hans Peter Freyther22230252009-08-19 12:53:57 +0200944 subscr = subscr_get_by_tmsi(bts->network,
945 tmsi_from_string(mi_string));
Harald Welte2a139372009-02-22 21:14:55 +0000946 break;
947 case GSM_MI_TYPE_IMSI:
Daniel Willmann977cd132012-12-28 19:29:44 +0100948 DEBUGPC(DMM, "\n");
Harald Welte9176bd42009-07-23 18:46:00 +0200949 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +0000950 break;
951 case GSM_MI_TYPE_IMEI:
952 case GSM_MI_TYPE_IMEISV:
953 /* no sim card... FIXME: what to do ? */
Daniel Willmann977cd132012-12-28 19:29:44 +0100954 DEBUGPC(DMM, ": unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +0000955 break;
956 default:
Daniel Willmann977cd132012-12-28 19:29:44 +0100957 DEBUGPC(DMM, ": unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +0000958 break;
959 }
960
Holger Freyther4a49e772009-04-12 05:37:29 +0000961 if (subscr) {
Holger Hans Peter Freyther153b13b2012-07-10 08:53:27 +0200962 subscr_update(subscr, bts,
Holger Freyther4a49e772009-04-12 05:37:29 +0000963 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2e6d4682009-12-24 14:50:24 +0100964 DEBUGP(DMM, "Subscriber: %s\n", subscr_name(subscr));
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200965
966 subscr->equipment.classmark1 = idi->classmark1;
967 db_sync_equipment(&subscr->equipment);
968
Holger Freytherc21cfbc2009-06-02 02:54:57 +0000969 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +0000970 } else
Harald Welte2a139372009-02-22 21:14:55 +0000971 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
972
Harald Welte31981a02009-12-20 09:58:40 +0100973 /* FIXME: iterate over all transactions and release them,
974 * imagine an IMSI DETACH happening during an active call! */
975
Holger Hans Peter Freyther153b13b2012-07-10 08:53:27 +0200976 release_anchor(conn);
Harald Welte2a139372009-02-22 21:14:55 +0000977 return 0;
978}
979
Harald Welted2a7f5a2009-06-05 20:08:20 +0000980static int gsm48_rx_mm_status(struct msgb *msg)
981{
982 struct gsm48_hdr *gh = msgb_l3(msg);
983
984 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
985
986 return 0;
987}
988
Sylvain Munaut30a15382009-12-24 00:27:26 +0100989/* Chapter 9.2.3: Authentication Response */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +0800990static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
Sylvain Munaut30a15382009-12-24 00:27:26 +0100991{
992 struct gsm48_hdr *gh = msgb_l3(msg);
993 struct gsm48_auth_resp *ar = (struct gsm48_auth_resp*) gh->data;
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +0800994 struct gsm_network *net = conn->bts->network;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100995
Sylvain Munautc593cf12010-06-10 23:51:41 +0200996 DEBUGP(DMM, "MM AUTHENTICATION RESPONSE (sres = %s): ",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200997 osmo_hexdump(ar->sres, 4));
Sylvain Munaut30a15382009-12-24 00:27:26 +0100998
999 /* Safety check */
1000 if (!conn->sec_operation) {
1001 DEBUGP(DMM, "No authentication/cipher operation in progress !!!\n");
1002 return -EIO;
1003 }
1004
1005 /* Validate SRES */
1006 if (memcmp(conn->sec_operation->atuple.sres, ar->sres,4)) {
Holger Hans Peter Freyther59f787a2010-12-27 10:57:56 +01001007 int rc;
Sylvain Munaut30a15382009-12-24 00:27:26 +01001008 gsm_cbfn *cb = conn->sec_operation->cb;
Sylvain Munautc593cf12010-06-10 23:51:41 +02001009
1010 DEBUGPC(DMM, "Invalid (expected %s)\n",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +02001011 osmo_hexdump(conn->sec_operation->atuple.sres, 4));
Sylvain Munautc593cf12010-06-10 23:51:41 +02001012
Sylvain Munaut30a15382009-12-24 00:27:26 +01001013 if (cb)
1014 cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
Holger Hans Peter Freyther228c1052010-06-16 12:47:59 +08001015 NULL, conn, conn->sec_operation->cb_data);
Sylvain Munaut30a15382009-12-24 00:27:26 +01001016
Holger Hans Peter Freyther59f787a2010-12-27 10:57:56 +01001017 rc = gsm48_tx_mm_auth_rej(conn);
Sylvain Munaut30a15382009-12-24 00:27:26 +01001018 release_security_operation(conn);
Holger Hans Peter Freyther59f787a2010-12-27 10:57:56 +01001019 return rc;
Sylvain Munaut30a15382009-12-24 00:27:26 +01001020 }
1021
Sylvain Munautc593cf12010-06-10 23:51:41 +02001022 DEBUGPC(DMM, "OK\n");
1023
Sylvain Munaut30a15382009-12-24 00:27:26 +01001024 /* Start ciphering */
Sylvain Munaut67706df2010-11-29 08:19:04 +01001025 return gsm0808_cipher_mode(conn, net->a5_encryption,
1026 conn->sec_operation->atuple.kc, 8, 0);
Sylvain Munaut30a15382009-12-24 00:27:26 +01001027}
1028
Harald Weltebf5e8df2009-02-03 12:59:45 +00001029/* Receive a GSM 04.08 Mobility Management (MM) message */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001030static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001031{
1032 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001033 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001034
1035 switch (gh->msg_type & 0xbf) {
1036 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001037 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001038 rc = mm_rx_loc_upd_req(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001039 break;
1040 case GSM48_MT_MM_ID_RESP:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001041 rc = mm_rx_id_resp(conn, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001042 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001043 case GSM48_MT_MM_CM_SERV_REQ:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001044 rc = gsm48_rx_mm_serv_req(conn, msg);
Harald Welte4b634542008-12-27 01:55:51 +00001045 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001046 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001047 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001048 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001049 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001050 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001051 conn->subscr ?
1052 subscr_name(conn->subscr) :
Harald Welte69b2af22009-01-06 19:47:00 +00001053 "unknown subscriber");
Holger Hans Peter Freytherd4e68722010-12-22 12:11:01 +01001054 release_loc_updating_req(conn);
Harald Welte69b2af22009-01-06 19:47:00 +00001055 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001056 case GSM48_MT_MM_IMSI_DETACH_IND:
Holger Hans Peter Freyther153b13b2012-07-10 08:53:27 +02001057 rc = gsm48_rx_mm_imsi_detach_ind(conn, msg);
Harald Welte2a139372009-02-22 21:14:55 +00001058 break;
1059 case GSM48_MT_MM_CM_REEST_REQ:
1060 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1061 break;
1062 case GSM48_MT_MM_AUTH_RESP:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001063 rc = gsm48_rx_mm_auth_resp(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001064 break;
1065 default:
Harald Welte5d24ba12009-12-24 12:13:17 +01001066 LOGP(DMM, LOGL_NOTICE, "Unknown GSM 04.08 MM msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001067 gh->msg_type);
1068 break;
1069 }
1070
1071 return rc;
1072}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001073
Harald Welte2d35ae62009-02-06 12:02:13 +00001074/* Receive a PAGING RESPONSE message from the MS */
Holger Hans Peter Freytherdb4ef0d2010-06-21 10:46:44 +08001075static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte2d35ae62009-02-06 12:02:13 +00001076{
Holger Hans Peter Freytherdb4ef0d2010-06-21 10:46:44 +08001077 struct gsm_bts *bts = conn->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001078 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherf6903de2010-05-16 01:51:14 +08001079 struct gsm48_pag_resp *resp;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001080 uint8_t *classmark2_lv = gh->data + 1;
1081 uint8_t mi_type;
Holger Hans Peter Freytherd1862d72009-08-19 07:54:59 +02001082 char mi_string[GSM48_MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001083 struct gsm_subscriber *subscr = NULL;
Harald Welte2d35ae62009-02-06 12:02:13 +00001084 int rc = 0;
1085
Holger Hans Peter Freytherf6903de2010-05-16 01:51:14 +08001086 resp = (struct gsm48_pag_resp *) &gh->data[0];
1087 gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
1088 mi_string, &mi_type);
Harald Welte2d35ae62009-02-06 12:02:13 +00001089 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1090 mi_type, mi_string);
Harald Welte3ac7f102009-08-10 10:12:45 +02001091
Harald Weltefe18d8f2009-02-22 21:14:24 +00001092 switch (mi_type) {
1093 case GSM_MI_TYPE_TMSI:
Holger Hans Peter Freyther22230252009-08-19 12:53:57 +02001094 subscr = subscr_get_by_tmsi(bts->network,
1095 tmsi_from_string(mi_string));
Harald Weltefe18d8f2009-02-22 21:14:24 +00001096 break;
1097 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001098 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001099 break;
1100 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001101
1102 if (!subscr) {
1103 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001104 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001105 return -EINVAL;
1106 }
1107 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte76042182009-08-08 16:03:15 +02001108 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001109
Harald Weltec2e302d2009-07-05 14:08:13 +02001110 subscr->equipment.classmark2_len = *classmark2_lv;
1111 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1112 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001113
Holger Hans Peter Freythere7bd8632013-06-30 15:30:47 +02001114 /* We received a paging */
1115 conn->expire_timer_stopped = 1;
1116
Holger Hans Peter Freytherdb4ef0d2010-06-21 10:46:44 +08001117 rc = gsm48_handle_paging_resp(conn, msg, subscr);
Harald Welte2d35ae62009-02-06 12:02:13 +00001118 return rc;
1119}
1120
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001121static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001122{
1123 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001124 uint8_t apdu_id_flags;
1125 uint8_t apdu_len;
1126 uint8_t *apdu_data;
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001127
1128 apdu_id_flags = gh->data[0];
1129 apdu_len = gh->data[1];
1130 apdu_data = gh->data+2;
1131
Harald Welte70f92052012-07-16 13:22:19 +02001132 DEBUGP(DRR, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +02001133 apdu_id_flags, apdu_len, osmo_hexdump(apdu_data, apdu_len));
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001134
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001135 return db_apdu_blob_store(conn->subscr, apdu_id_flags, apdu_len, apdu_data);
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001136}
1137
Harald Weltebf5e8df2009-02-03 12:59:45 +00001138/* Receive a GSM 04.08 Radio Resource (RR) message */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001139static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001140{
1141 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001142 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001143
1144 switch (gh->msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001145 case GSM48_MT_RR_PAG_RESP:
Holger Hans Peter Freytherdb4ef0d2010-06-21 10:46:44 +08001146 rc = gsm48_rx_rr_pag_resp(conn, msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001147 break;
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001148 case GSM48_MT_RR_APP_INFO:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08001149 rc = gsm48_rx_rr_app_info(conn, msg);
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001150 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001151 default:
Harald Weltecf149ee2012-01-23 16:40:24 +01001152 LOGP(DRR, LOGL_NOTICE, "MSC: Unimplemented "
Harald Welte5d24ba12009-12-24 12:13:17 +01001153 "GSM 04.08 RR msg type 0x%02x\n", gh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001154 break;
1155 }
1156
Harald Welte2d35ae62009-02-06 12:02:13 +00001157 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001158}
1159
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001160int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id,
1161 uint8_t apdu_len, const uint8_t *apdu)
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001162{
1163 struct msgb *msg = gsm48_msgb_alloc();
1164 struct gsm48_hdr *gh;
1165
Holger Hans Peter Freyther9ce1b272010-06-16 13:52:55 +08001166 msg->lchan = conn->lchan;
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001167
1168 DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
1169 apdu_id, apdu_len);
1170
1171 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len);
1172 gh->proto_discr = GSM48_PDISC_RR;
1173 gh->msg_type = GSM48_MT_RR_APP_INFO;
1174 gh->data[0] = apdu_id;
1175 gh->data[1] = apdu_len;
1176 memcpy(gh->data+2, apdu, apdu_len);
1177
Holger Hans Peter Freyther9ce1b272010-06-16 13:52:55 +08001178 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001179}
1180
Harald Welte4bc90a12008-12-27 16:32:52 +00001181/* Call Control */
1182
Harald Welte7584aea2009-02-11 11:44:12 +00001183/* The entire call control code is written in accordance with Figure 7.10c
1184 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1185 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1186 * it for voice */
1187
Harald Welte4bfdfe72009-06-10 23:11:52 +08001188static void new_cc_state(struct gsm_trans *trans, int state)
1189{
1190 if (state > 31 || state < 0)
1191 return;
1192
1193 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltee95daf192010-03-25 12:13:02 +08001194 gsm48_cc_state_name(trans->cc.state),
1195 gsm48_cc_state_name(state));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001196
Harald Weltedcaf5652009-07-23 18:56:43 +02001197 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001198}
1199
1200static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001201{
1202 struct msgb *msg = gsm48_msgb_alloc();
1203 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001204 uint8_t *cause, *call_state;
Harald Welte4bc90a12008-12-27 16:32:52 +00001205
Harald Welte4bc90a12008-12-27 16:32:52 +00001206 gh->msg_type = GSM48_MT_CC_STATUS;
1207
1208 cause = msgb_put(msg, 3);
1209 cause[0] = 2;
1210 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1211 cause[2] = 0x80 | 30; /* response to status inquiry */
1212
1213 call_state = msgb_put(msg, 1);
1214 call_state[0] = 0xc0 | 0x00;
1215
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08001216 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001217}
1218
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +08001219static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001220 uint8_t pdisc, uint8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001221{
1222 struct msgb *msg = gsm48_msgb_alloc();
1223 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1224
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +08001225 msg->lchan = conn->lchan;
Harald Welte4bc90a12008-12-27 16:32:52 +00001226
Harald Welte6f4b7532008-12-29 00:39:37 +00001227 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001228 gh->msg_type = msg_type;
1229
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +08001230 return gsm48_conn_sendmsg(msg, conn, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001231}
1232
Harald Welte4bfdfe72009-06-10 23:11:52 +08001233static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1234{
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001235 if (osmo_timer_pending(&trans->cc.timer)) {
Harald Weltedcaf5652009-07-23 18:56:43 +02001236 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001237 osmo_timer_del(&trans->cc.timer);
Harald Weltedcaf5652009-07-23 18:56:43 +02001238 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001239 }
1240}
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001241
Harald Welte4bfdfe72009-06-10 23:11:52 +08001242static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1243 int msg_type, struct gsm_mncc *mncc)
1244{
1245 struct msgb *msg;
Harald Welte04dc88f2010-12-22 21:45:05 +01001246 unsigned char *data;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001247
1248 if (trans)
Harald Welteb854b292010-12-26 19:06:37 +01001249 if (trans->conn && trans->conn->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02001250 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08001251 "Sending '%s' to MNCC.\n",
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001252 trans->conn->lchan->ts->trx->bts->nr,
1253 trans->conn->lchan->ts->trx->nr,
1254 trans->conn->lchan->ts->nr, trans->transaction_id,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001255 (trans->subscr)?(trans->subscr->extension):"-",
1256 get_mncc_name(msg_type));
1257 else
1258 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
1259 "Sending '%s' to MNCC.\n",
1260 (trans->subscr)?(trans->subscr->extension):"-",
1261 get_mncc_name(msg_type));
1262 else
1263 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
1264 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
1265
1266 mncc->msg_type = msg_type;
1267
Harald Welte966636f2009-06-26 19:39:35 +02001268 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001269 if (!msg)
1270 return -ENOMEM;
Harald Welte04dc88f2010-12-22 21:45:05 +01001271
1272 data = msgb_put(msg, sizeof(struct gsm_mncc));
1273 memcpy(data, mncc, sizeof(struct gsm_mncc));
1274
Harald Welte54209c22010-12-22 23:43:29 +01001275 cc_tx_to_mncc(net, msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001276
1277 return 0;
1278}
1279
1280int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001281 uint32_t callref, int location, int value)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001282{
1283 struct gsm_mncc rel;
1284
Harald Welte92f70c52009-06-12 01:54:08 +08001285 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08001286 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001287 mncc_set_cause(&rel, location, value);
Andreas Eversberg15907272013-01-25 08:38:29 +01001288 if (trans && trans->cc.state == GSM_CSTATE_RELEASE_REQ)
1289 return mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001290 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
1291}
1292
Harald Weltedcaf5652009-07-23 18:56:43 +02001293/* Call Control Specific transaction release.
1294 * gets called by trans_free, DO NOT CALL YOURSELF! */
1295void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001296{
Harald Welte4bfdfe72009-06-10 23:11:52 +08001297 gsm48_stop_cc_timer(trans);
1298
1299 /* send release to L4, if callref still exists */
1300 if (trans->callref) {
1301 /* Ressource unavailable */
Harald Welte596fed42009-07-23 19:06:52 +02001302 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001303 GSM48_CAUSE_LOC_PRN_S_LU,
1304 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001305 }
Harald Weltedcaf5652009-07-23 18:56:43 +02001306 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001307 new_cc_state(trans, GSM_CSTATE_NULL);
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001308 if (trans->conn)
1309 trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001310}
1311
1312static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001313
Harald Welte09e38af2009-02-16 22:52:23 +00001314/* call-back from paging the B-end of the connection */
1315static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +08001316 struct msgb *msg, void *_conn, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00001317{
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001318 int found = 0;
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +08001319 struct gsm_subscriber_connection *conn = _conn;
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001320 struct gsm_network **paging_request = param, *net;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001321 struct gsm_trans *transt, *tmp;
Harald Weltec05677b2009-06-26 20:17:06 +02001322
Harald Welte09e38af2009-02-16 22:52:23 +00001323 if (hooknum != GSM_HOOK_RR_PAGING)
1324 return -EINVAL;
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001325
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001326 net = *paging_request;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001327 if (!net) {
1328 DEBUGP(DCC, "Error Network not set!\n");
1329 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00001330 }
Harald Welte7584aea2009-02-11 11:44:12 +00001331
Harald Welte4bfdfe72009-06-10 23:11:52 +08001332 /* check all tranactions (without lchan) for subscriber */
1333 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001334 if (transt->paging_request != paging_request || transt->conn)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001335 continue;
1336 switch (event) {
1337 case GSM_PAGING_SUCCEEDED:
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +08001338 if (!conn) // paranoid
Harald Welte4bfdfe72009-06-10 23:11:52 +08001339 break;
1340 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001341 transt->subscr->extension);
1342 found = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001343 /* Assign lchan */
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001344 if (!transt->conn) {
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001345 transt->paging_request = NULL;
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +08001346 transt->conn = conn;
Holger Hans Peter Freyther182c81f2010-12-29 16:28:33 +01001347 conn->put_channel = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001348 }
1349 /* send SETUP request to called party */
Harald Weltedcaf5652009-07-23 18:56:43 +02001350 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001351 break;
1352 case GSM_PAGING_EXPIRED:
Holger Hans Peter Freytherd3baf412010-12-23 18:19:17 +01001353 case GSM_PAGING_BUSY:
Harald Welte4bfdfe72009-06-10 23:11:52 +08001354 DEBUGP(DCC, "Paging subscr %s expired!\n",
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001355 transt->subscr->extension);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001356 /* Temporarily out of order */
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001357 found = 1;
Harald Welte596fed42009-07-23 19:06:52 +02001358 mncc_release_ind(transt->subscr->net, transt,
1359 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001360 GSM48_CAUSE_LOC_PRN_S_LU,
1361 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001362 transt->callref = 0;
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001363 transt->paging_request = NULL;
Harald Weltedcaf5652009-07-23 18:56:43 +02001364 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001365 break;
1366 }
1367 }
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01001368
1369 talloc_free(paging_request);
1370
1371 /*
1372 * FIXME: The queue needs to be kicked. This is likely to go through a RF
1373 * failure and then the subscr will be poke again. This needs a lot of fixing
1374 * in the subscriber queue code.
1375 */
1376 if (!found && conn)
1377 conn->put_channel = 1;
Harald Welte09e38af2009-02-16 22:52:23 +00001378 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00001379}
Harald Welte7584aea2009-02-11 11:44:12 +00001380
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001381static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable);
Harald Welteda7ab742009-12-19 22:23:05 +01001382
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001383/* handle audio path for handover */
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001384static int switch_for_handover(struct gsm_lchan *old_lchan,
1385 struct gsm_lchan *new_lchan)
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001386{
1387 struct rtp_socket *old_rs, *new_rs, *other_rs;
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001388
1389 if (ipacc_rtp_direct) {
1390 LOGP(DHO, LOGL_ERROR, "unable to handover in direct RTP mode\n");
1391 return 0;
1392 }
1393
1394 /* RTP Proxy mode */
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001395 new_rs = new_lchan->abis_ip.rtp_socket;
1396 old_rs = old_lchan->abis_ip.rtp_socket;
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001397
1398 if (!new_rs) {
1399 LOGP(DHO, LOGL_ERROR, "no RTP socket for new_lchan\n");
1400 return -EIO;
1401 }
1402
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001403 rsl_ipacc_mdcx_to_rtpsock(new_lchan);
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001404
1405 if (!old_rs) {
1406 LOGP(DHO, LOGL_ERROR, "no RTP socket for old_lchan\n");
1407 return -EIO;
1408 }
1409
1410 /* copy rx_action and reference to other sock */
1411 new_rs->rx_action = old_rs->rx_action;
1412 new_rs->tx_action = old_rs->tx_action;
1413 new_rs->transmit = old_rs->transmit;
1414
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001415 switch (old_lchan->abis_ip.rtp_socket->rx_action) {
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001416 case RTP_PROXY:
1417 other_rs = old_rs->proxy.other_sock;
1418 rtp_socket_proxy(new_rs, other_rs);
1419 /* delete reference to other end socket to prevent
1420 * rtp_socket_free() from removing the inverse reference */
1421 old_rs->proxy.other_sock = NULL;
1422 break;
1423 case RTP_RECV_UPSTREAM:
1424 new_rs->receive = old_rs->receive;
1425 break;
1426 case RTP_NONE:
1427 break;
1428 }
1429
1430 return 0;
1431}
1432
Harald Welte805f6442009-07-28 18:25:29 +02001433/* some other part of the code sends us a signal */
1434static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
1435 void *handler_data, void *signal_data)
1436{
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001437 struct gsm_lchan *lchan = signal_data, *old_lchan;
Harald Welte805f6442009-07-28 18:25:29 +02001438 int rc;
Harald Welteda7ab742009-12-19 22:23:05 +01001439 struct gsm_network *net;
1440 struct gsm_trans *trans;
Harald Welte805f6442009-07-28 18:25:29 +02001441
1442 if (subsys != SS_ABISIP)
1443 return 0;
1444
1445 /* in case we use direct BTS-to-BTS RTP */
1446 if (ipacc_rtp_direct)
1447 return 0;
1448
Harald Welte805f6442009-07-28 18:25:29 +02001449 switch (signal) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001450 case S_ABISIP_CRCX_ACK:
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001451 /* in case we don't use direct BTS-to-BTS RTP */
1452 /* the BTS has successfully bound a TCH to a local ip/port,
1453 * which means we can connect our UDP socket to it */
1454 if (lchan->abis_ip.rtp_socket) {
1455 rtp_socket_free(lchan->abis_ip.rtp_socket);
1456 lchan->abis_ip.rtp_socket = NULL;
1457 }
1458
1459 lchan->abis_ip.rtp_socket = rtp_socket_create();
1460 if (!lchan->abis_ip.rtp_socket)
1461 return -EIO;
1462
1463 rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
1464 lchan->abis_ip.bound_ip,
1465 lchan->abis_ip.bound_port);
1466 if (rc < 0)
1467 return -EIO;
1468
Harald Welteda7ab742009-12-19 22:23:05 +01001469 /* check if any transactions on this lchan still have
1470 * a tch_recv_mncc request pending */
1471 net = lchan->ts->trx->bts->network;
1472 llist_for_each_entry(trans, &net->trans_list, entry) {
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001473 if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) {
Harald Welteda7ab742009-12-19 22:23:05 +01001474 DEBUGP(DCC, "pending tch_recv_mncc request\n");
1475 tch_recv_mncc(net, trans->callref, 1);
1476 }
1477 }
Holger Hans Peter Freytherc121bb32012-12-26 10:17:42 +01001478
1479 /*
1480 * TODO: this appears to be too early? Why not until after
1481 * the handover detect or the handover complete?
1482 *
1483 * Do we have a handover pending for this new lchan? In that
1484 * case re-route the audio from the old channel to the new one.
1485 */
1486 old_lchan = bsc_handover_pending(lchan);
1487 if (old_lchan)
1488 switch_for_handover(old_lchan, lchan);
Harald Welte805f6442009-07-28 18:25:29 +02001489 break;
Holger Hans Peter Freyther6c4d2442011-01-06 13:31:41 +01001490 case S_ABISIP_DLCX_IND:
1491 /* the BTS tells us a RTP stream has been disconnected */
1492 if (lchan->abis_ip.rtp_socket) {
1493 rtp_socket_free(lchan->abis_ip.rtp_socket);
1494 lchan->abis_ip.rtp_socket = NULL;
1495 }
1496
1497 break;
Harald Welte805f6442009-07-28 18:25:29 +02001498 }
1499
1500 return 0;
Harald Welte805f6442009-07-28 18:25:29 +02001501}
1502
Harald Welte49f48b82009-02-17 15:29:33 +00001503/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00001504static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00001505{
Harald Welte11fa29c2009-02-19 17:24:39 +00001506 struct gsm_bts *bts = lchan->ts->trx->bts;
1507 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte805f6442009-07-28 18:25:29 +02001508 int rc;
Harald Welte49f48b82009-02-17 15:29:33 +00001509
Harald Welte11fa29c2009-02-19 17:24:39 +00001510 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
1511 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
1512 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
1513
1514 if (bts->type != remote_bts->type) {
Harald Weltee5215b52011-08-09 21:53:20 +02001515 LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n");
Harald Welte11fa29c2009-02-19 17:24:39 +00001516 return -EINVAL;
1517 }
Harald Welteda7ab742009-12-19 22:23:05 +01001518
1519 // todo: map between different bts types
Harald Welte11fa29c2009-02-19 17:24:39 +00001520 switch (bts->type) {
Mike Habene2d82272009-10-02 12:19:34 +01001521 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +02001522 case GSM_BTS_TYPE_OSMO_SYSMO:
Harald Welte805f6442009-07-28 18:25:29 +02001523 if (!ipacc_rtp_direct) {
1524 /* connect the TCH's to our RTP proxy */
Harald Weltea72273e2009-12-20 16:51:09 +01001525 rc = rsl_ipacc_mdcx_to_rtpsock(lchan);
Harald Welte805f6442009-07-28 18:25:29 +02001526 if (rc < 0)
1527 return rc;
Harald Weltea72273e2009-12-20 16:51:09 +01001528 rc = rsl_ipacc_mdcx_to_rtpsock(remote_lchan);
Harald Welte4d54d0b2011-02-19 16:48:17 +01001529 if (rc < 0)
1530 return rc;
Harald Welte805f6442009-07-28 18:25:29 +02001531 /* connect them with each other */
Harald Welte2c828992009-12-02 01:56:49 +05301532 rtp_socket_proxy(lchan->abis_ip.rtp_socket,
1533 remote_lchan->abis_ip.rtp_socket);
Harald Welte805f6442009-07-28 18:25:29 +02001534 } else {
1535 /* directly connect TCH RTP streams to each other */
Harald Welte2c828992009-12-02 01:56:49 +05301536 rc = rsl_ipacc_mdcx(lchan, remote_lchan->abis_ip.bound_ip,
1537 remote_lchan->abis_ip.bound_port,
Harald Welte2c828992009-12-02 01:56:49 +05301538 remote_lchan->abis_ip.rtp_payload2);
Harald Welte805f6442009-07-28 18:25:29 +02001539 if (rc < 0)
1540 return rc;
Harald Welte2c828992009-12-02 01:56:49 +05301541 rc = rsl_ipacc_mdcx(remote_lchan, lchan->abis_ip.bound_ip,
1542 lchan->abis_ip.bound_port,
Harald Welte2c828992009-12-02 01:56:49 +05301543 lchan->abis_ip.rtp_payload2);
Harald Welte805f6442009-07-28 18:25:29 +02001544 }
Harald Welte11fa29c2009-02-19 17:24:39 +00001545 break;
1546 case GSM_BTS_TYPE_BS11:
Harald Weltec76fb5d2011-03-20 06:27:31 -03001547 case GSM_BTS_TYPE_RBS2000:
Dieter Spaar16646022011-07-28 00:01:50 +02001548 case GSM_BTS_TYPE_NOKIA_SITE:
Harald Welte11fa29c2009-02-19 17:24:39 +00001549 trau_mux_map_lchan(lchan, remote_lchan);
1550 break;
1551 default:
Harald Weltee5215b52011-08-09 21:53:20 +02001552 LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
Harald Welteda7ab742009-12-19 22:23:05 +01001553 return -EINVAL;
Harald Welte11fa29c2009-02-19 17:24:39 +00001554 }
Harald Welte49f48b82009-02-17 15:29:33 +00001555
1556 return 0;
1557}
1558
Harald Welte4bfdfe72009-06-10 23:11:52 +08001559/* bridge channels of two transactions */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001560static int tch_bridge(struct gsm_network *net, uint32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00001561{
Harald Weltedcaf5652009-07-23 18:56:43 +02001562 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
1563 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00001564
Harald Welte4bfdfe72009-06-10 23:11:52 +08001565 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00001566 return -EIO;
1567
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001568 if (!trans1->conn || !trans2->conn)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001569 return -EIO;
1570
1571 /* through-connect channel */
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001572 return tch_map(trans1->conn->lchan, trans2->conn->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001573}
1574
Harald Welteda7ab742009-12-19 22:23:05 +01001575/* enable receive of channels to MNCC upqueue */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001576static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001577{
1578 struct gsm_trans *trans;
Harald Welteda7ab742009-12-19 22:23:05 +01001579 struct gsm_lchan *lchan;
1580 struct gsm_bts *bts;
1581 int rc;
Harald Welte7ccf7782009-02-17 01:43:01 +00001582
Harald Welte4bfdfe72009-06-10 23:11:52 +08001583 /* Find callref */
Harald Welteda7ab742009-12-19 22:23:05 +01001584 trans = trans_find_by_callref(net, callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001585 if (!trans)
1586 return -EIO;
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001587 if (!trans->conn)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001588 return 0;
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001589 lchan = trans->conn->lchan;
Harald Welteda7ab742009-12-19 22:23:05 +01001590 bts = lchan->ts->trx->bts;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001591
Harald Welteda7ab742009-12-19 22:23:05 +01001592 switch (bts->type) {
1593 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +02001594 case GSM_BTS_TYPE_OSMO_SYSMO:
Harald Welteda7ab742009-12-19 22:23:05 +01001595 if (ipacc_rtp_direct) {
Harald Weltee5215b52011-08-09 21:53:20 +02001596 LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n");
Harald Welteda7ab742009-12-19 22:23:05 +01001597 return -EINVAL;
1598 }
1599 /* in case, we don't have a RTP socket yet, we note this
1600 * in the transaction and try later */
1601 if (!lchan->abis_ip.rtp_socket) {
1602 trans->tch_recv = enable;
1603 DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", enable);
1604 return 0;
1605 }
1606 if (enable) {
1607 /* connect the TCH's to our RTP proxy */
Harald Weltea72273e2009-12-20 16:51:09 +01001608 rc = rsl_ipacc_mdcx_to_rtpsock(lchan);
Harald Welteda7ab742009-12-19 22:23:05 +01001609 if (rc < 0)
1610 return rc;
1611 /* assign socket to application interface */
1612 rtp_socket_upstream(lchan->abis_ip.rtp_socket,
1613 net, callref);
1614 } else
1615 rtp_socket_upstream(lchan->abis_ip.rtp_socket,
1616 net, 0);
1617 break;
1618 case GSM_BTS_TYPE_BS11:
Harald Weltec76fb5d2011-03-20 06:27:31 -03001619 case GSM_BTS_TYPE_RBS2000:
Harald Welte10456972011-08-05 20:11:18 +02001620 case GSM_BTS_TYPE_NOKIA_SITE:
Harald Welteda7ab742009-12-19 22:23:05 +01001621 if (enable)
1622 return trau_recv_lchan(lchan, callref);
1623 return trau_mux_unmap(NULL, callref);
1624 break;
1625 default:
Harald Weltee5215b52011-08-09 21:53:20 +02001626 LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
Harald Welteda7ab742009-12-19 22:23:05 +01001627 return -EINVAL;
1628 }
1629
1630 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001631}
1632
Harald Welte4bfdfe72009-06-10 23:11:52 +08001633static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
1634{
1635 DEBUGP(DCC, "-> STATUS ENQ\n");
1636 return gsm48_cc_tx_status(trans, msg);
1637}
1638
1639static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
1640static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
1641
1642static void gsm48_cc_timeout(void *arg)
1643{
1644 struct gsm_trans *trans = arg;
1645 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08001646 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
1647 int mo_location = GSM48_CAUSE_LOC_USER;
1648 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
1649 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001650 struct gsm_mncc mo_rel, l4_rel;
1651
1652 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
1653 mo_rel.callref = trans->callref;
1654 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
1655 l4_rel.callref = trans->callref;
1656
Harald Weltedcaf5652009-07-23 18:56:43 +02001657 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08001658 case 0x303:
1659 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08001660 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001661 break;
1662 case 0x310:
1663 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08001664 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001665 break;
1666 case 0x313:
1667 disconnect = 1;
1668 /* unknown, did not find it in the specs */
1669 break;
1670 case 0x301:
1671 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08001672 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001673 break;
1674 case 0x308:
Harald Weltedcaf5652009-07-23 18:56:43 +02001675 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08001676 /* restart T308 a second time */
Harald Weltedcaf5652009-07-23 18:56:43 +02001677 gsm48_cc_tx_release(trans, &trans->cc.msg);
1678 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001679 break; /* stay in release state */
1680 }
Harald Weltedcaf5652009-07-23 18:56:43 +02001681 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001682 return;
1683// release = 1;
1684// l4_cause = 14;
1685// break;
1686 case 0x306:
1687 release = 1;
Harald Weltedcaf5652009-07-23 18:56:43 +02001688 mo_cause = trans->cc.msg.cause.value;
1689 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001690 break;
1691 case 0x323:
1692 disconnect = 1;
1693 break;
1694 default:
1695 release = 1;
1696 }
1697
1698 if (release && trans->callref) {
1699 /* process release towards layer 4 */
Harald Welte596fed42009-07-23 19:06:52 +02001700 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001701 l4_location, l4_cause);
1702 trans->callref = 0;
1703 }
1704
1705 if (disconnect && trans->callref) {
1706 /* process disconnect towards layer 4 */
1707 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte596fed42009-07-23 19:06:52 +02001708 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001709 }
1710
1711 /* process disconnect towards mobile station */
1712 if (disconnect || release) {
1713 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltedcaf5652009-07-23 18:56:43 +02001714 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
1715 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
1716 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08001717 mo_rel.cause.diag_len = 3;
1718
1719 if (disconnect)
1720 gsm48_cc_tx_disconnect(trans, &mo_rel);
1721 if (release)
1722 gsm48_cc_tx_release(trans, &mo_rel);
1723 }
1724
1725}
1726
1727static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
1728 int sec, int micro)
1729{
1730 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltedcaf5652009-07-23 18:56:43 +02001731 trans->cc.timer.cb = gsm48_cc_timeout;
1732 trans->cc.timer.data = trans;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001733 osmo_timer_schedule(&trans->cc.timer, sec, micro);
Harald Weltedcaf5652009-07-23 18:56:43 +02001734 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001735}
1736
1737static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
1738{
1739 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001740 uint8_t msg_type = gh->msg_type & 0xbf;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001741 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1742 struct tlv_parsed tp;
1743 struct gsm_mncc setup;
1744
1745 memset(&setup, 0, sizeof(struct gsm_mncc));
1746 setup.callref = trans->callref;
Harald Welteab386e62011-09-01 18:18:43 +02001747 if (trans->conn && trans->conn->lchan)
1748 setup.lchan_type = trans->conn->lchan->type;
Harald Welte474d19f2010-03-02 23:18:30 +01001749 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001750 /* emergency setup is identified by msg_type */
1751 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
1752 setup.emergency = 1;
1753
1754 /* use subscriber as calling party number */
Holger Hans Peter Freyther1e61b252013-07-06 11:45:38 +02001755 setup.fields |= MNCC_F_CALLING;
1756 strncpy(setup.calling.number, trans->subscr->extension,
1757 sizeof(setup.calling.number)-1);
1758 strncpy(setup.imsi, trans->subscr->imsi,
1759 sizeof(setup.imsi)-1);
1760
Harald Welte4bfdfe72009-06-10 23:11:52 +08001761 /* bearer capability */
1762 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
1763 setup.fields |= MNCC_F_BEARER_CAP;
Harald Welte55c8f352010-03-07 23:40:35 +01001764 gsm48_decode_bearer_cap(&setup.bearer_cap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001765 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
1766 }
1767 /* facility */
1768 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
1769 setup.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01001770 gsm48_decode_facility(&setup.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001771 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
1772 }
1773 /* called party bcd number */
1774 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
1775 setup.fields |= MNCC_F_CALLED;
Harald Welte55c8f352010-03-07 23:40:35 +01001776 gsm48_decode_called(&setup.called,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001777 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
1778 }
1779 /* user-user */
1780 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
1781 setup.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01001782 gsm48_decode_useruser(&setup.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001783 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
1784 }
1785 /* ss-version */
1786 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
1787 setup.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01001788 gsm48_decode_ssversion(&setup.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001789 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
1790 }
1791 /* CLIR suppression */
1792 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
1793 setup.clir.sup = 1;
1794 /* CLIR invocation */
1795 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
1796 setup.clir.inv = 1;
1797 /* cc cap */
1798 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
1799 setup.fields |= MNCC_F_CCCAP;
Harald Welte55c8f352010-03-07 23:40:35 +01001800 gsm48_decode_cccap(&setup.cccap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001801 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
1802 }
1803
Harald Welte4bfdfe72009-06-10 23:11:52 +08001804 new_cc_state(trans, GSM_CSTATE_INITIATED);
1805
Harald Welte (local)47df3992009-12-26 19:45:03 +01001806 LOGP(DCC, LOGL_INFO, "Subscriber %s (%s) sends SETUP to %s\n",
1807 subscr_name(trans->subscr), trans->subscr->extension,
1808 setup.called.number);
1809
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001810 osmo_counter_inc(trans->subscr->net->stats.call.mo_setup);
Harald Weltea29e43a2010-12-24 16:06:33 +01001811
Harald Welte4bfdfe72009-06-10 23:11:52 +08001812 /* indicate setup to MNCC */
Harald Welte596fed42009-07-23 19:06:52 +02001813 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001814
Harald Welte13cac662009-07-29 12:10:35 +02001815 /* MNCC code will modify the channel asynchronously, we should
1816 * ipaccess-bind only after the modification has been made to the
1817 * lchan->tch_mode */
Harald Welte4bfdfe72009-06-10 23:11:52 +08001818 return 0;
1819}
1820
1821static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00001822{
1823 struct msgb *msg = gsm48_msgb_alloc();
1824 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001825 struct gsm_mncc *setup = arg;
Harald Welte78283ef2009-07-23 21:36:44 +02001826 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00001827
Harald Welte7ccf7782009-02-17 01:43:01 +00001828 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00001829
Harald Welte4bfdfe72009-06-10 23:11:52 +08001830 /* transaction id must not be assigned */
1831 if (trans->transaction_id != 0xff) { /* unasssigned */
1832 DEBUGP(DCC, "TX Setup with assigned transaction. "
1833 "This is not allowed!\n");
1834 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02001835 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001836 GSM48_CAUSE_LOC_PRN_S_LU,
1837 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001838 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02001839 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001840 return rc;
1841 }
1842
1843 /* Get free transaction_id */
Harald Welte78283ef2009-07-23 21:36:44 +02001844 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
1845 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08001846 /* no free transaction ID */
Harald Welte596fed42009-07-23 19:06:52 +02001847 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08001848 GSM48_CAUSE_LOC_PRN_S_LU,
1849 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001850 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02001851 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001852 return rc;
1853 }
Harald Welte78283ef2009-07-23 21:36:44 +02001854 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00001855
Harald Welte65e74cc2008-12-29 01:55:35 +00001856 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00001857
Harald Welte4bfdfe72009-06-10 23:11:52 +08001858 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00001859
Harald Welte4bfdfe72009-06-10 23:11:52 +08001860 /* bearer capability */
1861 if (setup->fields & MNCC_F_BEARER_CAP)
Harald Welte55c8f352010-03-07 23:40:35 +01001862 gsm48_encode_bearer_cap(msg, 0, &setup->bearer_cap);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001863 /* facility */
1864 if (setup->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01001865 gsm48_encode_facility(msg, 0, &setup->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001866 /* progress */
1867 if (setup->fields & MNCC_F_PROGRESS)
Harald Welte55c8f352010-03-07 23:40:35 +01001868 gsm48_encode_progress(msg, 0, &setup->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001869 /* calling party BCD number */
1870 if (setup->fields & MNCC_F_CALLING)
Harald Welte55c8f352010-03-07 23:40:35 +01001871 gsm48_encode_calling(msg, &setup->calling);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001872 /* called party BCD number */
1873 if (setup->fields & MNCC_F_CALLED)
Harald Welte55c8f352010-03-07 23:40:35 +01001874 gsm48_encode_called(msg, &setup->called);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001875 /* user-user */
1876 if (setup->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01001877 gsm48_encode_useruser(msg, 0, &setup->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001878 /* redirecting party BCD number */
1879 if (setup->fields & MNCC_F_REDIRECTING)
Harald Welte55c8f352010-03-07 23:40:35 +01001880 gsm48_encode_redirecting(msg, &setup->redirecting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001881 /* signal */
1882 if (setup->fields & MNCC_F_SIGNAL)
Harald Welte55c8f352010-03-07 23:40:35 +01001883 gsm48_encode_signal(msg, setup->signal);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001884
1885 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00001886
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001887 osmo_counter_inc(trans->subscr->net->stats.call.mt_setup);
Harald Weltea29e43a2010-12-24 16:06:33 +01001888
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08001889 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00001890}
1891
Harald Welte4bfdfe72009-06-10 23:11:52 +08001892static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
1893{
1894 struct gsm48_hdr *gh = msgb_l3(msg);
1895 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1896 struct tlv_parsed tp;
1897 struct gsm_mncc call_conf;
1898
1899 gsm48_stop_cc_timer(trans);
1900 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
1901
1902 memset(&call_conf, 0, sizeof(struct gsm_mncc));
1903 call_conf.callref = trans->callref;
Harald Welteab386e62011-09-01 18:18:43 +02001904 if (trans->conn && trans->conn->lchan)
1905 call_conf.lchan_type = trans->conn->lchan->type;
Harald Welte474d19f2010-03-02 23:18:30 +01001906 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001907#if 0
1908 /* repeat */
1909 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
1910 call_conf.repeat = 1;
1911 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
1912 call_conf.repeat = 2;
1913#endif
1914 /* bearer capability */
1915 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
1916 call_conf.fields |= MNCC_F_BEARER_CAP;
Harald Welte55c8f352010-03-07 23:40:35 +01001917 gsm48_decode_bearer_cap(&call_conf.bearer_cap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001918 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
1919 }
1920 /* cause */
1921 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
1922 call_conf.fields |= MNCC_F_CAUSE;
Harald Welte55c8f352010-03-07 23:40:35 +01001923 gsm48_decode_cause(&call_conf.cause,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001924 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
1925 }
1926 /* cc cap */
1927 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
1928 call_conf.fields |= MNCC_F_CCCAP;
Harald Welte55c8f352010-03-07 23:40:35 +01001929 gsm48_decode_cccap(&call_conf.cccap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001930 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
1931 }
1932
1933 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
1934
Harald Welte596fed42009-07-23 19:06:52 +02001935 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
1936 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001937}
1938
1939static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
1940{
1941 struct gsm_mncc *proceeding = arg;
1942 struct msgb *msg = gsm48_msgb_alloc();
1943 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1944
Harald Welte4bfdfe72009-06-10 23:11:52 +08001945 gh->msg_type = GSM48_MT_CC_CALL_PROC;
1946
1947 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
1948
1949 /* bearer capability */
1950 if (proceeding->fields & MNCC_F_BEARER_CAP)
Harald Welte55c8f352010-03-07 23:40:35 +01001951 gsm48_encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001952 /* facility */
1953 if (proceeding->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01001954 gsm48_encode_facility(msg, 0, &proceeding->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001955 /* progress */
1956 if (proceeding->fields & MNCC_F_PROGRESS)
Harald Welte55c8f352010-03-07 23:40:35 +01001957 gsm48_encode_progress(msg, 0, &proceeding->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001958
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08001959 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001960}
1961
1962static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
1963{
1964 struct gsm48_hdr *gh = msgb_l3(msg);
1965 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1966 struct tlv_parsed tp;
1967 struct gsm_mncc alerting;
1968
1969 gsm48_stop_cc_timer(trans);
1970 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
1971
1972 memset(&alerting, 0, sizeof(struct gsm_mncc));
1973 alerting.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01001974 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001975 /* facility */
1976 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
1977 alerting.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01001978 gsm48_decode_facility(&alerting.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001979 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
1980 }
1981
1982 /* progress */
1983 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
1984 alerting.fields |= MNCC_F_PROGRESS;
Harald Welte55c8f352010-03-07 23:40:35 +01001985 gsm48_decode_progress(&alerting.progress,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001986 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
1987 }
1988 /* ss-version */
1989 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
1990 alerting.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01001991 gsm48_decode_ssversion(&alerting.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08001992 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
1993 }
1994
1995 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
1996
Harald Welte596fed42009-07-23 19:06:52 +02001997 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
1998 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001999}
2000
2001static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2002{
2003 struct gsm_mncc *alerting = arg;
2004 struct msgb *msg = gsm48_msgb_alloc();
2005 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2006
Harald Welte4bfdfe72009-06-10 23:11:52 +08002007 gh->msg_type = GSM48_MT_CC_ALERTING;
2008
2009 /* facility */
2010 if (alerting->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01002011 gsm48_encode_facility(msg, 0, &alerting->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002012 /* progress */
2013 if (alerting->fields & MNCC_F_PROGRESS)
Harald Welte55c8f352010-03-07 23:40:35 +01002014 gsm48_encode_progress(msg, 0, &alerting->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002015 /* user-user */
2016 if (alerting->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002017 gsm48_encode_useruser(msg, 0, &alerting->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002018
2019 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2020
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002021 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002022}
2023
2024static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2025{
2026 struct gsm_mncc *progress = arg;
2027 struct msgb *msg = gsm48_msgb_alloc();
2028 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2029
Harald Welte4bfdfe72009-06-10 23:11:52 +08002030 gh->msg_type = GSM48_MT_CC_PROGRESS;
2031
2032 /* progress */
Harald Welte55c8f352010-03-07 23:40:35 +01002033 gsm48_encode_progress(msg, 1, &progress->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002034 /* user-user */
2035 if (progress->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002036 gsm48_encode_useruser(msg, 0, &progress->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002037
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002038 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002039}
2040
2041static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2042{
2043 struct gsm_mncc *connect = arg;
2044 struct msgb *msg = gsm48_msgb_alloc();
2045 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2046
Harald Welte4bfdfe72009-06-10 23:11:52 +08002047 gh->msg_type = GSM48_MT_CC_CONNECT;
2048
2049 gsm48_stop_cc_timer(trans);
2050 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2051
2052 /* facility */
2053 if (connect->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01002054 gsm48_encode_facility(msg, 0, &connect->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002055 /* progress */
2056 if (connect->fields & MNCC_F_PROGRESS)
Harald Welte55c8f352010-03-07 23:40:35 +01002057 gsm48_encode_progress(msg, 0, &connect->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002058 /* connected number */
2059 if (connect->fields & MNCC_F_CONNECTED)
Harald Welte55c8f352010-03-07 23:40:35 +01002060 gsm48_encode_connected(msg, &connect->connected);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002061 /* user-user */
2062 if (connect->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002063 gsm48_encode_useruser(msg, 0, &connect->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002064
2065 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2066
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002067 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002068}
2069
2070static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2071{
2072 struct gsm48_hdr *gh = msgb_l3(msg);
2073 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2074 struct tlv_parsed tp;
2075 struct gsm_mncc connect;
2076
2077 gsm48_stop_cc_timer(trans);
2078
2079 memset(&connect, 0, sizeof(struct gsm_mncc));
2080 connect.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002081 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002082 /* use subscriber as connected party number */
Holger Hans Peter Freyther1e61b252013-07-06 11:45:38 +02002083 connect.fields |= MNCC_F_CONNECTED;
2084 strncpy(connect.connected.number, trans->subscr->extension,
2085 sizeof(connect.connected.number)-1);
2086 strncpy(connect.imsi, trans->subscr->imsi,
2087 sizeof(connect.imsi)-1);
2088
Harald Welte4bfdfe72009-06-10 23:11:52 +08002089 /* facility */
2090 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2091 connect.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01002092 gsm48_decode_facility(&connect.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002093 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2094 }
2095 /* user-user */
2096 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2097 connect.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01002098 gsm48_decode_useruser(&connect.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002099 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2100 }
2101 /* ss-version */
2102 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2103 connect.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01002104 gsm48_decode_ssversion(&connect.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002105 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2106 }
2107
2108 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02002109 osmo_counter_inc(trans->subscr->net->stats.call.mt_connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002110
Harald Welte596fed42009-07-23 19:06:52 +02002111 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002112}
2113
2114
2115static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2116{
2117 struct gsm_mncc connect_ack;
2118
2119 gsm48_stop_cc_timer(trans);
2120
2121 new_cc_state(trans, GSM_CSTATE_ACTIVE);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02002122 osmo_counter_inc(trans->subscr->net->stats.call.mo_connect_ack);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002123
2124 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2125 connect_ack.callref = trans->callref;
Harald Weltea29e43a2010-12-24 16:06:33 +01002126
Harald Welte596fed42009-07-23 19:06:52 +02002127 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002128 &connect_ack);
2129}
2130
2131static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2132{
2133 struct msgb *msg = gsm48_msgb_alloc();
2134 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2135
Harald Welte4bfdfe72009-06-10 23:11:52 +08002136 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2137
2138 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2139
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002140 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002141}
2142
2143static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2144{
2145 struct gsm48_hdr *gh = msgb_l3(msg);
2146 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2147 struct tlv_parsed tp;
2148 struct gsm_mncc disc;
2149
2150 gsm48_stop_cc_timer(trans);
2151
2152 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2153
2154 memset(&disc, 0, sizeof(struct gsm_mncc));
2155 disc.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002156 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002157 /* cause */
2158 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2159 disc.fields |= MNCC_F_CAUSE;
Harald Welte55c8f352010-03-07 23:40:35 +01002160 gsm48_decode_cause(&disc.cause,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002161 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2162 }
2163 /* facility */
2164 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2165 disc.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01002166 gsm48_decode_facility(&disc.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002167 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2168 }
2169 /* user-user */
2170 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2171 disc.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01002172 gsm48_decode_useruser(&disc.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002173 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2174 }
2175 /* ss-version */
2176 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2177 disc.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01002178 gsm48_decode_ssversion(&disc.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002179 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2180 }
2181
Harald Welte596fed42009-07-23 19:06:52 +02002182 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002183
2184}
2185
Harald Weltec66b71c2009-06-11 14:23:20 +08002186static struct gsm_mncc_cause default_cause = {
2187 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2188 .coding = 0,
2189 .rec = 0,
2190 .rec_val = 0,
2191 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2192 .diag_len = 0,
2193 .diag = { 0 },
2194};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002195
2196static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2197{
2198 struct gsm_mncc *disc = arg;
2199 struct msgb *msg = gsm48_msgb_alloc();
2200 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2201
Harald Welte4bfdfe72009-06-10 23:11:52 +08002202 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2203
2204 gsm48_stop_cc_timer(trans);
2205 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2206
2207 /* cause */
2208 if (disc->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002209 gsm48_encode_cause(msg, 1, &disc->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002210 else
Harald Welte55c8f352010-03-07 23:40:35 +01002211 gsm48_encode_cause(msg, 1, &default_cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002212
2213 /* facility */
2214 if (disc->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01002215 gsm48_encode_facility(msg, 0, &disc->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002216 /* progress */
2217 if (disc->fields & MNCC_F_PROGRESS)
Harald Welte55c8f352010-03-07 23:40:35 +01002218 gsm48_encode_progress(msg, 0, &disc->progress);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002219 /* user-user */
2220 if (disc->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002221 gsm48_encode_useruser(msg, 0, &disc->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002222
2223 /* store disconnect cause for T306 expiry */
Harald Weltedcaf5652009-07-23 18:56:43 +02002224 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002225
2226 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2227
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002228 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002229}
2230
2231static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2232{
2233 struct gsm48_hdr *gh = msgb_l3(msg);
2234 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2235 struct tlv_parsed tp;
2236 struct gsm_mncc rel;
2237 int rc;
2238
2239 gsm48_stop_cc_timer(trans);
2240
2241 memset(&rel, 0, sizeof(struct gsm_mncc));
2242 rel.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002243 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002244 /* cause */
2245 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2246 rel.fields |= MNCC_F_CAUSE;
Harald Welte55c8f352010-03-07 23:40:35 +01002247 gsm48_decode_cause(&rel.cause,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002248 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2249 }
2250 /* facility */
2251 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2252 rel.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01002253 gsm48_decode_facility(&rel.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002254 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2255 }
2256 /* user-user */
2257 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2258 rel.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01002259 gsm48_decode_useruser(&rel.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002260 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2261 }
2262 /* ss-version */
2263 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2264 rel.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01002265 gsm48_decode_ssversion(&rel.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002266 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2267 }
2268
Harald Weltedcaf5652009-07-23 18:56:43 +02002269 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002270 /* release collision 5.4.5 */
Harald Welte596fed42009-07-23 19:06:52 +02002271 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002272 } else {
Holger Hans Peter Freythere9ed3402010-06-16 12:30:50 +08002273 rc = gsm48_tx_simple(trans->conn,
Harald Welte6f5aee02009-07-23 21:21:14 +02002274 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte596fed42009-07-23 19:06:52 +02002275 GSM48_MT_CC_RELEASE_COMPL);
2276 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002277 }
2278
2279 new_cc_state(trans, GSM_CSTATE_NULL);
2280
2281 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002282 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002283
2284 return rc;
2285}
2286
2287static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2288{
2289 struct gsm_mncc *rel = arg;
2290 struct msgb *msg = gsm48_msgb_alloc();
2291 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2292
Harald Welte4bfdfe72009-06-10 23:11:52 +08002293 gh->msg_type = GSM48_MT_CC_RELEASE;
2294
Harald Welte4bfdfe72009-06-10 23:11:52 +08002295 gsm48_stop_cc_timer(trans);
2296 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2297
2298 /* cause */
2299 if (rel->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002300 gsm48_encode_cause(msg, 0, &rel->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002301 /* facility */
2302 if (rel->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01002303 gsm48_encode_facility(msg, 0, &rel->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002304 /* user-user */
2305 if (rel->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002306 gsm48_encode_useruser(msg, 0, &rel->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002307
Harald Weltedcaf5652009-07-23 18:56:43 +02002308 trans->cc.T308_second = 0;
2309 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002310
Harald Weltedcaf5652009-07-23 18:56:43 +02002311 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002312 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2313
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002314 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002315}
2316
2317static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2318{
2319 struct gsm48_hdr *gh = msgb_l3(msg);
2320 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2321 struct tlv_parsed tp;
2322 struct gsm_mncc rel;
2323 int rc = 0;
2324
2325 gsm48_stop_cc_timer(trans);
2326
2327 memset(&rel, 0, sizeof(struct gsm_mncc));
2328 rel.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002329 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002330 /* cause */
2331 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2332 rel.fields |= MNCC_F_CAUSE;
Harald Welte55c8f352010-03-07 23:40:35 +01002333 gsm48_decode_cause(&rel.cause,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002334 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2335 }
2336 /* facility */
2337 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2338 rel.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01002339 gsm48_decode_facility(&rel.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002340 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2341 }
2342 /* user-user */
2343 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2344 rel.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01002345 gsm48_decode_useruser(&rel.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002346 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2347 }
2348 /* ss-version */
2349 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2350 rel.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01002351 gsm48_decode_ssversion(&rel.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002352 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2353 }
2354
2355 if (trans->callref) {
Harald Weltedcaf5652009-07-23 18:56:43 +02002356 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002357 case GSM_CSTATE_CALL_PRESENT:
Harald Welte596fed42009-07-23 19:06:52 +02002358 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002359 MNCC_REJ_IND, &rel);
2360 break;
2361 case GSM_CSTATE_RELEASE_REQ:
Harald Welte596fed42009-07-23 19:06:52 +02002362 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002363 MNCC_REL_CNF, &rel);
2364 break;
2365 default:
Harald Welte596fed42009-07-23 19:06:52 +02002366 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002367 MNCC_REL_IND, &rel);
2368 }
2369 }
2370
2371 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002372 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002373
2374 return rc;
2375}
2376
2377static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
2378{
2379 struct gsm_mncc *rel = arg;
2380 struct msgb *msg = gsm48_msgb_alloc();
2381 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Weltec7782de2010-12-21 19:31:41 +01002382 int ret;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002383
Harald Welte4bfdfe72009-06-10 23:11:52 +08002384 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
2385
2386 trans->callref = 0;
2387
2388 gsm48_stop_cc_timer(trans);
2389
2390 /* cause */
2391 if (rel->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002392 gsm48_encode_cause(msg, 0, &rel->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002393 /* facility */
2394 if (rel->fields & MNCC_F_FACILITY)
Harald Welte55c8f352010-03-07 23:40:35 +01002395 gsm48_encode_facility(msg, 0, &rel->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002396 /* user-user */
2397 if (rel->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002398 gsm48_encode_useruser(msg, 0, &rel->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002399
Harald Weltec7782de2010-12-21 19:31:41 +01002400 ret = gsm48_conn_sendmsg(msg, trans->conn, trans);
2401
Harald Weltedcaf5652009-07-23 18:56:43 +02002402 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002403
Harald Weltec7782de2010-12-21 19:31:41 +01002404 return ret;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002405}
2406
2407static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
2408{
2409 struct gsm48_hdr *gh = msgb_l3(msg);
2410 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2411 struct tlv_parsed tp;
2412 struct gsm_mncc fac;
2413
2414 memset(&fac, 0, sizeof(struct gsm_mncc));
2415 fac.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002416 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002417 /* facility */
2418 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2419 fac.fields |= MNCC_F_FACILITY;
Harald Welte55c8f352010-03-07 23:40:35 +01002420 gsm48_decode_facility(&fac.facility,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002421 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2422 }
2423 /* ss-version */
2424 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2425 fac.fields |= MNCC_F_SSVERSION;
Harald Welte55c8f352010-03-07 23:40:35 +01002426 gsm48_decode_ssversion(&fac.ssversion,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002427 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2428 }
2429
Harald Welte596fed42009-07-23 19:06:52 +02002430 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002431}
2432
2433static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
2434{
2435 struct gsm_mncc *fac = arg;
2436 struct msgb *msg = gsm48_msgb_alloc();
2437 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2438
Harald Welte4bfdfe72009-06-10 23:11:52 +08002439 gh->msg_type = GSM48_MT_CC_FACILITY;
2440
2441 /* facility */
Harald Welte55c8f352010-03-07 23:40:35 +01002442 gsm48_encode_facility(msg, 1, &fac->facility);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002443
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002444 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002445}
2446
2447static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
2448{
2449 struct gsm_mncc hold;
2450
2451 memset(&hold, 0, sizeof(struct gsm_mncc));
2452 hold.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002453 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002454}
2455
2456static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
2457{
2458 struct msgb *msg = gsm48_msgb_alloc();
2459 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2460
Harald Welte4bfdfe72009-06-10 23:11:52 +08002461 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
2462
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002463 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002464}
2465
2466static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
2467{
2468 struct gsm_mncc *hold_rej = arg;
2469 struct msgb *msg = gsm48_msgb_alloc();
2470 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2471
Harald Welte4bfdfe72009-06-10 23:11:52 +08002472 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
2473
2474 /* cause */
2475 if (hold_rej->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002476 gsm48_encode_cause(msg, 1, &hold_rej->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002477 else
Harald Welte55c8f352010-03-07 23:40:35 +01002478 gsm48_encode_cause(msg, 1, &default_cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002479
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002480 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002481}
2482
2483static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
2484{
2485 struct gsm_mncc retrieve;
2486
2487 memset(&retrieve, 0, sizeof(struct gsm_mncc));
2488 retrieve.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002489 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
2490 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002491}
2492
2493static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
2494{
2495 struct msgb *msg = gsm48_msgb_alloc();
2496 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2497
Harald Welte4bfdfe72009-06-10 23:11:52 +08002498 gh->msg_type = GSM48_MT_CC_RETR_ACK;
2499
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002500 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002501}
2502
2503static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
2504{
2505 struct gsm_mncc *retrieve_rej = arg;
2506 struct msgb *msg = gsm48_msgb_alloc();
2507 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2508
Harald Welte4bfdfe72009-06-10 23:11:52 +08002509 gh->msg_type = GSM48_MT_CC_RETR_REJ;
2510
2511 /* cause */
2512 if (retrieve_rej->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002513 gsm48_encode_cause(msg, 1, &retrieve_rej->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002514 else
Harald Welte55c8f352010-03-07 23:40:35 +01002515 gsm48_encode_cause(msg, 1, &default_cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002516
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002517 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002518}
2519
2520static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
2521{
2522 struct gsm48_hdr *gh = msgb_l3(msg);
2523 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2524 struct tlv_parsed tp;
2525 struct gsm_mncc dtmf;
2526
2527 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2528 dtmf.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002529 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002530 /* keypad facility */
2531 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
2532 dtmf.fields |= MNCC_F_KEYPAD;
Harald Welte55c8f352010-03-07 23:40:35 +01002533 gsm48_decode_keypad(&dtmf.keypad,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002534 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
2535 }
2536
Harald Welte596fed42009-07-23 19:06:52 +02002537 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002538}
2539
2540static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
2541{
2542 struct gsm_mncc *dtmf = arg;
2543 struct msgb *msg = gsm48_msgb_alloc();
2544 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2545
Harald Welte4bfdfe72009-06-10 23:11:52 +08002546 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
2547
2548 /* keypad */
2549 if (dtmf->fields & MNCC_F_KEYPAD)
Harald Welte55c8f352010-03-07 23:40:35 +01002550 gsm48_encode_keypad(msg, dtmf->keypad);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002551
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002552 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002553}
2554
2555static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
2556{
2557 struct gsm_mncc *dtmf = arg;
2558 struct msgb *msg = gsm48_msgb_alloc();
2559 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2560
Harald Welte4bfdfe72009-06-10 23:11:52 +08002561 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
2562
2563 /* cause */
2564 if (dtmf->fields & MNCC_F_CAUSE)
Harald Welte55c8f352010-03-07 23:40:35 +01002565 gsm48_encode_cause(msg, 1, &dtmf->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002566 else
Harald Welte55c8f352010-03-07 23:40:35 +01002567 gsm48_encode_cause(msg, 1, &default_cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002568
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002569 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002570}
2571
2572static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
2573{
2574 struct msgb *msg = gsm48_msgb_alloc();
2575 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2576
Harald Welte4bfdfe72009-06-10 23:11:52 +08002577 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
2578
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002579 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002580}
2581
2582static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
2583{
2584 struct gsm_mncc dtmf;
2585
2586 memset(&dtmf, 0, sizeof(struct gsm_mncc));
2587 dtmf.callref = trans->callref;
2588
Harald Welte596fed42009-07-23 19:06:52 +02002589 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002590}
2591
2592static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
2593{
2594 struct gsm48_hdr *gh = msgb_l3(msg);
2595 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2596 struct tlv_parsed tp;
2597 struct gsm_mncc modify;
2598
2599 memset(&modify, 0, sizeof(struct gsm_mncc));
2600 modify.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002601 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002602 /* bearer capability */
2603 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2604 modify.fields |= MNCC_F_BEARER_CAP;
Harald Welte55c8f352010-03-07 23:40:35 +01002605 gsm48_decode_bearer_cap(&modify.bearer_cap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002606 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2607 }
2608
2609 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
2610
Harald Welte596fed42009-07-23 19:06:52 +02002611 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002612}
2613
2614static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
2615{
2616 struct gsm_mncc *modify = arg;
2617 struct msgb *msg = gsm48_msgb_alloc();
2618 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2619
Harald Welte4bfdfe72009-06-10 23:11:52 +08002620 gh->msg_type = GSM48_MT_CC_MODIFY;
2621
2622 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
2623
2624 /* bearer capability */
Harald Welte55c8f352010-03-07 23:40:35 +01002625 gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002626
2627 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
2628
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002629 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002630}
2631
2632static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
2633{
2634 struct gsm48_hdr *gh = msgb_l3(msg);
2635 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2636 struct tlv_parsed tp;
2637 struct gsm_mncc modify;
2638
2639 gsm48_stop_cc_timer(trans);
2640
2641 memset(&modify, 0, sizeof(struct gsm_mncc));
2642 modify.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002643 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002644 /* bearer capability */
2645 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2646 modify.fields |= MNCC_F_BEARER_CAP;
Harald Welte55c8f352010-03-07 23:40:35 +01002647 gsm48_decode_bearer_cap(&modify.bearer_cap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002648 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2649 }
2650
2651 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2652
Harald Welte596fed42009-07-23 19:06:52 +02002653 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002654}
2655
2656static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
2657{
2658 struct gsm_mncc *modify = arg;
2659 struct msgb *msg = gsm48_msgb_alloc();
2660 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2661
Harald Welte4bfdfe72009-06-10 23:11:52 +08002662 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
2663
2664 /* bearer capability */
Harald Welte55c8f352010-03-07 23:40:35 +01002665 gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002666
2667 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2668
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002669 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002670}
2671
2672static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
2673{
2674 struct gsm48_hdr *gh = msgb_l3(msg);
2675 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2676 struct tlv_parsed tp;
2677 struct gsm_mncc modify;
2678
2679 gsm48_stop_cc_timer(trans);
2680
2681 memset(&modify, 0, sizeof(struct gsm_mncc));
2682 modify.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002683 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002684 /* bearer capability */
2685 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2686 modify.fields |= GSM48_IE_BEARER_CAP;
Harald Welte55c8f352010-03-07 23:40:35 +01002687 gsm48_decode_bearer_cap(&modify.bearer_cap,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002688 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2689 }
2690 /* cause */
2691 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2692 modify.fields |= MNCC_F_CAUSE;
Harald Welte55c8f352010-03-07 23:40:35 +01002693 gsm48_decode_cause(&modify.cause,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002694 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2695 }
2696
2697 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2698
Harald Welte596fed42009-07-23 19:06:52 +02002699 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002700}
2701
2702static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
2703{
2704 struct gsm_mncc *modify = arg;
2705 struct msgb *msg = gsm48_msgb_alloc();
2706 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2707
Harald Welte4bfdfe72009-06-10 23:11:52 +08002708 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
2709
2710 /* bearer capability */
Harald Welte55c8f352010-03-07 23:40:35 +01002711 gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002712 /* cause */
Harald Welte55c8f352010-03-07 23:40:35 +01002713 gsm48_encode_cause(msg, 1, &modify->cause);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002714
2715 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2716
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002717 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002718}
2719
2720static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
2721{
2722 struct gsm_mncc *notify = arg;
2723 struct msgb *msg = gsm48_msgb_alloc();
2724 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2725
Harald Welte4bfdfe72009-06-10 23:11:52 +08002726 gh->msg_type = GSM48_MT_CC_NOTIFY;
2727
2728 /* notify */
Harald Welte55c8f352010-03-07 23:40:35 +01002729 gsm48_encode_notify(msg, notify->notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002730
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002731 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002732}
2733
2734static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
2735{
2736 struct gsm48_hdr *gh = msgb_l3(msg);
2737 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2738// struct tlv_parsed tp;
2739 struct gsm_mncc notify;
2740
2741 memset(&notify, 0, sizeof(struct gsm_mncc));
2742 notify.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002743// tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002744 if (payload_len >= 1)
Harald Welte55c8f352010-03-07 23:40:35 +01002745 gsm48_decode_notify(&notify.notify, gh->data);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002746
Harald Welte596fed42009-07-23 19:06:52 +02002747 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002748}
2749
2750static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
2751{
2752 struct gsm_mncc *user = arg;
2753 struct msgb *msg = gsm48_msgb_alloc();
2754 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2755
Harald Welte4bfdfe72009-06-10 23:11:52 +08002756 gh->msg_type = GSM48_MT_CC_USER_INFO;
2757
2758 /* user-user */
2759 if (user->fields & MNCC_F_USERUSER)
Harald Welte55c8f352010-03-07 23:40:35 +01002760 gsm48_encode_useruser(msg, 1, &user->useruser);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002761 /* more data */
2762 if (user->more)
Harald Welte55c8f352010-03-07 23:40:35 +01002763 gsm48_encode_more(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002764
Holger Hans Peter Freyther9c137a72010-06-15 13:57:40 +08002765 return gsm48_conn_sendmsg(msg, trans->conn, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002766}
2767
2768static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
2769{
2770 struct gsm48_hdr *gh = msgb_l3(msg);
2771 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2772 struct tlv_parsed tp;
2773 struct gsm_mncc user;
2774
2775 memset(&user, 0, sizeof(struct gsm_mncc));
2776 user.callref = trans->callref;
Harald Welte474d19f2010-03-02 23:18:30 +01002777 tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002778 /* user-user */
2779 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2780 user.fields |= MNCC_F_USERUSER;
Harald Welte55c8f352010-03-07 23:40:35 +01002781 gsm48_decode_useruser(&user.useruser,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002782 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2783 }
2784 /* more data */
2785 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
2786 user.more = 1;
2787
Harald Welte596fed42009-07-23 19:06:52 +02002788 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002789}
2790
Holger Hans Peter Freytherff3f2602009-10-22 15:13:00 +02002791static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002792{
2793 struct gsm_mncc *mode = arg;
2794
Holger Hans Peter Freytherb549ddf2011-01-16 18:17:04 +01002795 return gsm0808_assign_req(trans->conn, mode->lchan_mode, 1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002796}
2797
2798static struct downstate {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02002799 uint32_t states;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002800 int type;
2801 int (*rout) (struct gsm_trans *trans, void *arg);
2802} downstatelist[] = {
2803 /* mobile originating call establishment */
2804 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
2805 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
2806 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
2807 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
2808 {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 */
2809 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
2810 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
2811 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
2812 /* mobile terminating call establishment */
2813 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
2814 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
2815 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
2816 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
2817 /* signalling during call */
2818 {SBIT(GSM_CSTATE_ACTIVE),
2819 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
2820 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
2821 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
2822 {ALL_STATES,
2823 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
2824 {ALL_STATES,
2825 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
2826 {ALL_STATES,
2827 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
2828 {SBIT(GSM_CSTATE_ACTIVE),
2829 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
2830 {SBIT(GSM_CSTATE_ACTIVE),
2831 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
2832 {SBIT(GSM_CSTATE_ACTIVE),
2833 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
2834 {SBIT(GSM_CSTATE_ACTIVE),
2835 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
2836 {SBIT(GSM_CSTATE_ACTIVE),
2837 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
2838 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
2839 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
2840 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
2841 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
2842 {SBIT(GSM_CSTATE_ACTIVE),
2843 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
2844 /* clearing */
2845 {SBIT(GSM_CSTATE_INITIATED),
2846 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
2847 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
2848 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
2849 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
2850 MNCC_REL_REQ, gsm48_cc_tx_release},
2851 /* special */
2852 {ALL_STATES,
Holger Hans Peter Freytherff3f2602009-10-22 15:13:00 +02002853 MNCC_LCHAN_MODIFY, _gsm48_lchan_modify},
Harald Welte4bfdfe72009-06-10 23:11:52 +08002854};
2855
2856#define DOWNSLLEN \
2857 (sizeof(downstatelist) / sizeof(struct downstate))
2858
2859
Harald Welte76556372010-12-22 23:57:45 +01002860int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002861{
Harald Welte1a6f7982009-08-09 18:52:33 +02002862 int i, rc = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002863 struct gsm_trans *trans = NULL, *transt;
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08002864 struct gsm_subscriber_connection *conn = NULL;
Holger Hans Peter Freytherb56a6bb2010-12-27 16:02:25 +01002865 struct gsm_bts *bts = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002866 struct gsm_mncc *data = arg, rel;
2867
Harald Welte04dc88f2010-12-22 21:45:05 +01002868 DEBUGP(DMNCC, "receive message %s\n", get_mncc_name(msg_type));
2869
Harald Welte4bfdfe72009-06-10 23:11:52 +08002870 /* handle special messages */
2871 switch(msg_type) {
2872 case MNCC_BRIDGE:
2873 return tch_bridge(net, arg);
2874 case MNCC_FRAME_DROP:
Harald Welteda7ab742009-12-19 22:23:05 +01002875 return tch_recv_mncc(net, data->callref, 0);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002876 case MNCC_FRAME_RECV:
Harald Welteda7ab742009-12-19 22:23:05 +01002877 return tch_recv_mncc(net, data->callref, 1);
2878 case GSM_TCHF_FRAME:
Andreas Eversbergd074f8f2013-12-06 16:59:10 +01002879 case GSM_TCHF_FRAME_EFR:
Harald Welteda7ab742009-12-19 22:23:05 +01002880 /* Find callref */
2881 trans = trans_find_by_callref(net, data->callref);
Harald Welte04dc88f2010-12-22 21:45:05 +01002882 if (!trans) {
2883 LOGP(DMNCC, LOGL_ERROR, "TCH frame for non-existing trans\n");
Harald Welteda7ab742009-12-19 22:23:05 +01002884 return -EIO;
Harald Welte04dc88f2010-12-22 21:45:05 +01002885 }
2886 if (!trans->conn) {
2887 LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without conn\n");
Harald Welteda7ab742009-12-19 22:23:05 +01002888 return 0;
Harald Welte04dc88f2010-12-22 21:45:05 +01002889 }
2890 if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) {
2891 /* This should be LOGL_ERROR or NOTICE, but
2892 * unfortuantely it happens for a couple of frames at
2893 * the beginning of every RTP connection */
2894 LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != TCH_F\n");
Harald Welteda7ab742009-12-19 22:23:05 +01002895 return 0;
Harald Welte04dc88f2010-12-22 21:45:05 +01002896 }
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01002897 bts = trans->conn->lchan->ts->trx->bts;
Harald Welteda7ab742009-12-19 22:23:05 +01002898 switch (bts->type) {
2899 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +02002900 case GSM_BTS_TYPE_OSMO_SYSMO:
Harald Welte04dc88f2010-12-22 21:45:05 +01002901 if (!trans->conn->lchan->abis_ip.rtp_socket) {
Harald Welte91c59c82010-12-24 12:40:21 +01002902 DEBUGP(DMNCC, "TCH frame to lchan without RTP connection\n");
Harald Welteda7ab742009-12-19 22:23:05 +01002903 return 0;
Harald Welte04dc88f2010-12-22 21:45:05 +01002904 }
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01002905 return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
Harald Welteda7ab742009-12-19 22:23:05 +01002906 case GSM_BTS_TYPE_BS11:
Harald Weltec76fb5d2011-03-20 06:27:31 -03002907 case GSM_BTS_TYPE_RBS2000:
Harald Welte10456972011-08-05 20:11:18 +02002908 case GSM_BTS_TYPE_NOKIA_SITE:
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01002909 return trau_send_frame(trans->conn->lchan, arg);
Harald Welteda7ab742009-12-19 22:23:05 +01002910 default:
Harald Weltee5215b52011-08-09 21:53:20 +02002911 LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
Harald Welteda7ab742009-12-19 22:23:05 +01002912 }
2913 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002914 }
2915
2916 memset(&rel, 0, sizeof(struct gsm_mncc));
2917 rel.callref = data->callref;
2918
2919 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002920 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002921
2922 /* Callref unknown */
2923 if (!trans) {
Holger Hans Peter Freytherccf53c62009-10-27 14:21:14 +01002924 struct gsm_subscriber *subscr;
2925
Harald Welte4a3464c2009-07-04 10:11:24 +02002926 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002927 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
2928 "Received '%s' from MNCC with "
2929 "unknown callref %d\n", data->called.number,
2930 get_mncc_name(msg_type), data->callref);
2931 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002932 return mncc_release_ind(net, NULL, data->callref,
2933 GSM48_CAUSE_LOC_PRN_S_LU,
2934 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002935 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02002936 if (!data->called.number[0] && !data->imsi[0]) {
2937 DEBUGP(DCC, "(bts - trx - ts - ti) "
2938 "Received '%s' from MNCC with "
2939 "no number or IMSI\n", get_mncc_name(msg_type));
2940 /* Invalid number */
2941 return mncc_release_ind(net, NULL, data->callref,
2942 GSM48_CAUSE_LOC_PRN_S_LU,
2943 GSM48_CC_CAUSE_INV_NR_FORMAT);
2944 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08002945 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02002946 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02002947 subscr = subscr_get_by_extension(net,
2948 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002949 else
Harald Welte9176bd42009-07-23 18:46:00 +02002950 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002951 /* If subscriber is not found */
2952 if (!subscr) {
2953 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
2954 "Received '%s' from MNCC with "
2955 "unknown subscriber %s\n", data->called.number,
2956 get_mncc_name(msg_type), data->called.number);
2957 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002958 return mncc_release_ind(net, NULL, data->callref,
2959 GSM48_CAUSE_LOC_PRN_S_LU,
2960 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002961 }
2962 /* If subscriber is not "attached" */
2963 if (!subscr->lac) {
2964 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
2965 "Received '%s' from MNCC with "
2966 "detached subscriber %s\n", data->called.number,
2967 get_mncc_name(msg_type), data->called.number);
2968 subscr_put(subscr);
2969 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002970 return mncc_release_ind(net, NULL, data->callref,
2971 GSM48_CAUSE_LOC_PRN_S_LU,
2972 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002973 }
2974 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02002975 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
2976 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002977 DEBUGP(DCC, "No memory for trans.\n");
2978 subscr_put(subscr);
2979 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002980 mncc_release_ind(net, NULL, data->callref,
2981 GSM48_CAUSE_LOC_PRN_S_LU,
2982 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002983 return -ENOMEM;
2984 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08002985 /* Find lchan */
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08002986 conn = connection_for_subscr(subscr);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +01002987
Harald Welte4bfdfe72009-06-10 23:11:52 +08002988 /* If subscriber has no lchan */
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08002989 if (!conn) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002990 /* find transaction with this subscriber already paging */
2991 llist_for_each_entry(transt, &net->trans_list, entry) {
2992 /* Transaction of our lchan? */
2993 if (transt == trans ||
2994 transt->subscr != subscr)
2995 continue;
Holger Hans Peter Freyther8e3eb582010-12-27 16:08:34 +01002996 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08002997 "Received '%s' from MNCC with "
2998 "unallocated channel, paging already "
Holger Hans Peter Freyther8e3eb582010-12-27 16:08:34 +01002999 "started for lac %d.\n",
Harald Welte4bfdfe72009-06-10 23:11:52 +08003000 data->called.number,
Holger Hans Peter Freyther8e3eb582010-12-27 16:08:34 +01003001 get_mncc_name(msg_type), subscr->lac);
Holger Hans Peter Freytherccf53c62009-10-27 14:21:14 +01003002 subscr_put(subscr);
3003 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003004 return 0;
3005 }
3006 /* store setup informations until paging was successfull */
Harald Weltedcaf5652009-07-23 18:56:43 +02003007 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Sylvain Munaut567c8dc2010-12-01 22:17:36 +01003008
3009 /* Get a channel */
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +01003010 trans->paging_request = talloc_zero(subscr->net, struct gsm_network*);
3011 if (!trans->paging_request) {
3012 LOGP(DCC, LOGL_ERROR, "Failed to allocate paging token.\n");
3013 subscr_put(subscr);
3014 trans_free(trans);
3015 return 0;
3016 }
3017
3018 *trans->paging_request = subscr->net;
3019 subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, trans->paging_request);
Sylvain Munaut567c8dc2010-12-01 22:17:36 +01003020
Holger Hans Peter Freytherccf53c62009-10-27 14:21:14 +01003021 subscr_put(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003022 return 0;
3023 }
3024 /* Assign lchan */
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08003025 trans->conn = conn;
Holger Hans Peter Freytherccf53c62009-10-27 14:21:14 +01003026 subscr_put(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003027 }
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01003028
3029 if (trans->conn)
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08003030 conn = trans->conn;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003031
3032 /* if paging did not respond yet */
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08003033 if (!conn) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003034 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02003035 "Received '%s' from MNCC in paging state\n",
Harald Welte4bfdfe72009-06-10 23:11:52 +08003036 (trans->subscr)?(trans->subscr->extension):"-",
3037 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003038 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3039 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003040 if (msg_type == MNCC_REL_REQ)
3041 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3042 else
3043 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3044 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003045 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003046 return rc;
3047 }
3048
3049 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3050 "Received '%s' from MNCC in state %d (%s)\n",
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +08003051 conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003052 trans->transaction_id,
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01003053 (trans->conn->subscr)?(trans->conn->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003054 get_mncc_name(msg_type), trans->cc.state,
Harald Weltee95daf192010-03-25 12:13:02 +08003055 gsm48_cc_state_name(trans->cc.state));
Harald Welte4bfdfe72009-06-10 23:11:52 +08003056
3057 /* Find function for current state and message */
3058 for (i = 0; i < DOWNSLLEN; i++)
3059 if ((msg_type == downstatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003060 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003061 break;
3062 if (i == DOWNSLLEN) {
3063 DEBUGP(DCC, "Message unhandled at this state.\n");
3064 return 0;
3065 }
3066
3067 rc = downstatelist[i].rout(trans, arg);
3068
3069 return rc;
3070}
3071
3072
3073static struct datastate {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02003074 uint32_t states;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003075 int type;
3076 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3077} datastatelist[] = {
3078 /* mobile originating call establishment */
3079 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3080 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3081 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3082 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3083 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3084 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3085 /* mobile terminating call establishment */
3086 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3087 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3088 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3089 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02003090 {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 */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003091 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3092 /* signalling during call */
3093 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3094 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3095 {SBIT(GSM_CSTATE_ACTIVE),
3096 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3097 {ALL_STATES,
3098 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3099 {ALL_STATES,
3100 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3101 {ALL_STATES,
3102 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3103 {SBIT(GSM_CSTATE_ACTIVE),
3104 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3105 {SBIT(GSM_CSTATE_ACTIVE),
3106 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3107 {SBIT(GSM_CSTATE_ACTIVE),
3108 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3109 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3110 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3111 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3112 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3113 {SBIT(GSM_CSTATE_ACTIVE),
3114 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3115 /* clearing */
3116 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3117 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3118 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3119 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3120 {ALL_STATES, /* 5.4.3.4 */
3121 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3122};
3123
3124#define DATASLLEN \
3125 (sizeof(datastatelist) / sizeof(struct datastate))
3126
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003127static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte4bc90a12008-12-27 16:32:52 +00003128{
3129 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02003130 uint8_t msg_type = gh->msg_type & 0xbf;
3131 uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Weltedcaf5652009-07-23 18:56:43 +02003132 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003133 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003134
Harald Welte4bfdfe72009-06-10 23:11:52 +08003135 if (msg_type & 0x80) {
3136 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3137 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003138 }
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +01003139
Harald Welte4bfdfe72009-06-10 23:11:52 +08003140 /* Find transaction */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +01003141 trans = trans_find_by_id(conn->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltedcaf5652009-07-23 18:56:43 +02003142
Harald Welte6f5aee02009-07-23 21:21:14 +02003143 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003144 "Received '%s' from MS in state %d (%s)\n",
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003145 conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +01003146 transaction_id, (conn->subscr)?(conn->subscr->extension):"-",
Harald Weltee95daf192010-03-25 12:13:02 +08003147 gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,
3148 gsm48_cc_state_name(trans?(trans->cc.state):0));
Harald Welte4bfdfe72009-06-10 23:11:52 +08003149
3150 /* Create transaction */
3151 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003152 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003153 "creating new trans.\n", transaction_id);
3154 /* Create transaction */
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +01003155 trans = trans_alloc(conn->subscr, GSM48_PDISC_CC,
Harald Weltedcaf5652009-07-23 18:56:43 +02003156 transaction_id, new_callref++);
3157 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003158 DEBUGP(DCC, "No memory for trans.\n");
Holger Hans Peter Freytherb549ddf2011-01-16 18:17:04 +01003159 rc = gsm48_tx_simple(conn,
Harald Welte6f5aee02009-07-23 21:21:14 +02003160 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003161 GSM48_MT_CC_RELEASE_COMPL);
3162 return -ENOMEM;
3163 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003164 /* Assign transaction */
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003165 trans->conn = conn;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003166 }
3167
3168 /* find function for current state and message */
3169 for (i = 0; i < DATASLLEN; i++)
3170 if ((msg_type == datastatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003171 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003172 break;
3173 if (i == DATASLLEN) {
3174 DEBUGP(DCC, "Message unhandled at this state.\n");
3175 return 0;
3176 }
3177
Holger Hans Peter Freyther1e61b252013-07-06 11:45:38 +02003178 assert(trans->subscr);
3179
Harald Welte4bfdfe72009-06-10 23:11:52 +08003180 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003181
3182 return rc;
3183}
3184
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003185/* Create a dummy to wait five seconds */
3186static void release_anchor(struct gsm_subscriber_connection *conn)
3187{
3188 if (!conn->anch_operation)
3189 return;
3190
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02003191 osmo_timer_del(&conn->anch_operation->timeout);
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003192 talloc_free(conn->anch_operation);
3193 conn->anch_operation = NULL;
3194}
3195
3196static void anchor_timeout(void *_data)
3197{
3198 struct gsm_subscriber_connection *con = _data;
3199
3200 release_anchor(con);
3201 msc_release_connection(con);
3202}
3203
3204int gsm0408_new_conn(struct gsm_subscriber_connection *conn)
3205{
3206 conn->anch_operation = talloc_zero(conn, struct gsm_anchor_operation);
3207 if (!conn->anch_operation)
3208 return -1;
3209
3210 conn->anch_operation->timeout.data = conn;
3211 conn->anch_operation->timeout.cb = anchor_timeout;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02003212 osmo_timer_schedule(&conn->anch_operation->timeout, 5, 0);
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003213 return 0;
3214}
3215
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +08003216/* here we get data from the BSC level... */
3217int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00003218{
3219 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02003220 uint8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003221 int rc = 0;
Harald Welte51008772009-12-29 11:49:12 +01003222
Holger Hans Peter Freyther758f4df2010-06-21 10:34:03 +08003223 if (silent_call_reroute(conn, msg))
3224 return silent_call_rx(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00003225
3226 switch (pdisc) {
3227 case GSM48_PDISC_CC:
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003228 release_anchor(conn);
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003229 rc = gsm0408_rcv_cc(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00003230 break;
3231 case GSM48_PDISC_MM:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003232 rc = gsm0408_rcv_mm(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00003233 break;
3234 case GSM48_PDISC_RR:
Holger Hans Peter Freyther3f122be2010-06-17 17:14:35 +08003235 rc = gsm0408_rcv_rr(conn, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00003236 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003237 case GSM48_PDISC_SMS:
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003238 release_anchor(conn);
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +08003239 rc = gsm0411_rcv_sms(conn, msg);
Harald Weltebcae43f2008-12-27 21:45:37 +00003240 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003241 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003242 case GSM48_PDISC_SM_GPRS:
Harald Welte5d24ba12009-12-24 12:13:17 +01003243 LOGP(DRLL, LOGL_NOTICE, "Unimplemented "
3244 "GSM 04.08 discriminator 0x%02x\n", pdisc);
Harald Welte52b1f982008-12-23 20:25:15 +00003245 break;
Harald Welte6eafe912009-10-16 08:32:58 +02003246 case GSM48_PDISC_NC_SS:
Holger Hans Peter Freyther02d39b22010-07-05 15:34:16 +08003247 release_anchor(conn);
Holger Hans Peter Freytherd42c3f22010-06-17 17:35:57 +08003248 rc = handle_rcv_ussd(conn, msg);
Harald Welte6eafe912009-10-16 08:32:58 +02003249 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003250 default:
Harald Welte5d24ba12009-12-24 12:13:17 +01003251 LOGP(DRLL, LOGL_NOTICE, "Unknown "
3252 "GSM 04.08 discriminator 0x%02x\n", pdisc);
Harald Welte52b1f982008-12-23 20:25:15 +00003253 break;
3254 }
3255
3256 return rc;
3257}
Harald Welte8470bf22008-12-25 23:28:35 +00003258
Harald Welte805f6442009-07-28 18:25:29 +02003259/*
3260 * This will be ran by the linker when loading the DSO. We use it to
3261 * do system initialization, e.g. registration of signal handlers.
3262 */
3263static __attribute__((constructor)) void on_dso_load_0408(void)
3264{
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02003265 osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, NULL);
Harald Welte805f6442009-07-28 18:25:29 +02003266}