blob: fd52a6e0af1ac236bb16adff320fa5389adcca25 [file] [log] [blame]
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +01001/* The routines to handle the state */
2/*
3 * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * (C) 2010-2011 by On-Waves
5 * All Rights Reserved
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <mtp_data.h>
Holger Hans Peter Freyther84ec8712011-02-15 20:01:47 +010023#include <msc_connection.h>
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010024#include <mtp_level3.h>
25#include <bss_patch.h>
26#include <bssap_sccp.h>
27#include <bsc_data.h>
28#include <cellmgr_debug.h>
29#include <bsc_sccp.h>
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +010030#include <bsc_ussd.h>
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010031#include <ss7_application.h>
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010032
33#include <osmocore/talloc.h>
34
35#include <osmocom/vty/vty.h>
36#include <osmocom/vty/telnet_interface.h>
37
38#include <sys/stat.h>
39#include <sys/types.h>
40
41#include <fcntl.h>
42#include <signal.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <assert.h>
47#include <unistd.h>
48
49static void send_reset_ack(struct mtp_link_set *link, int sls);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010050static void handle_local_sccp(struct mtp_link_set *link, struct msgb *inp, struct sccp_parse_result *res, int sls);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010051static void send_local_rlsd(struct mtp_link_set *link, struct sccp_parse_result *res);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010052static void update_con_state(struct ss7_application *ss7, int rc, struct sccp_parse_result *result, struct msgb *msg, int from_msc, int sls);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010053
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010054/*
55 * methods called from the MTP Level3 part
56 */
57void mtp_link_set_forward_sccp(struct mtp_link_set *link, struct msgb *_msg, int sls)
58{
59 int rc;
60 struct sccp_parse_result result;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010061 struct msc_connection *fw;
62
Holger Hans Peter Freyther2cdb73c2011-02-15 21:27:20 +010063 struct msgb *msg;
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010064
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010065 if (!link->app) {
66 LOGP(DINP, LOGL_ERROR, "The linkset %d/%s has no application.\n",
67 link->no, link->name);
Holger Hans Peter Freytherdd32ae52011-02-10 20:07:30 +010068 return;
69 }
70
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010071 fw = link->app->route_dst.msc;
72 if (!fw) {
73 LOGP(DINP, LOGL_ERROR, "The application %d/%s has no MSC.\n",
74 link->app->nr, link->app->name);
75 return;
76 }
77
78 if (link->app->forward_only) {
79 msc_send_direct(fw, _msg);
80 return;
81 }
Holger Hans Peter Freytherdd32ae52011-02-10 20:07:30 +010082
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010083 rc = bss_patch_filter_msg(_msg, &result);
84 if (rc == BSS_FILTER_RESET) {
85 LOGP(DMSC, LOGL_NOTICE, "Filtering BSS Reset from the BSC\n");
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +010086 msc_mgcp_reset(fw);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010087 send_reset_ack(link, sls);
88 return;
89 }
90
91 /* special responder */
92 if (fw->msc_link_down) {
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010093 if (rc == BSS_FILTER_RESET_ACK && link->app->reset_count > 0) {
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010094 LOGP(DMSC, LOGL_ERROR, "Received reset ack for closing.\n");
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010095 app_clear_connections(link->app);
96 app_resources_released(link->app);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +010097 return;
98 }
99
100 if (rc != 0 && rc != BSS_FILTER_RLSD && rc != BSS_FILTER_RLC) {
101 LOGP(DMSC, LOGL_ERROR, "Ignoring unparsable msg during closedown.\n");
102 return;
103 }
104
105 return handle_local_sccp(link, _msg, &result, sls);
106 }
107
108 /* update the connection state */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100109 update_con_state(link->app, rc, &result, _msg, 0, sls);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100110
111 if (rc == BSS_FILTER_CLEAR_COMPL) {
112 send_local_rlsd(link, &result);
113 } else if (rc == BSS_FILTER_RLC || rc == BSS_FILTER_RLSD) {
114 LOGP(DMSC, LOGL_DEBUG, "Not forwarding RLC/RLSD to the MSC.\n");
115 return;
116 }
117
Holger Hans Peter Freyther2cdb73c2011-02-15 21:27:20 +0100118 /* now send it out */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100119 bsc_ussd_handle_out_msg(fw, &result, _msg);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100120
Holger Hans Peter Freyther2cdb73c2011-02-15 21:27:20 +0100121 msg = msgb_alloc_headroom(4096, 128, "SCCP to MSC");
122 if (!msg) {
123 LOGP(DMSC, LOGL_ERROR, "Failed to alloc MSC msg.\n");
124 return;
125 }
126
127 bss_rewrite_header_for_msc(rc, msg, _msg, &result);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100128 msc_send_direct(fw, msg);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100129}
130
131void mtp_link_set_forward_isup(struct mtp_link_set *set, struct msgb *msg, int sls)
132{
133 LOGP(DINP, LOGL_ERROR, "ISUP is not handled.\n");
134}
135
136/*
137 * handle local message in close down mode
138 */
139static void handle_local_sccp(struct mtp_link_set *link, struct msgb *inpt, struct sccp_parse_result *result, int sls)
140{
141 /* Handle msg with a reject */
142 if (inpt->l2h[0] == SCCP_MSG_TYPE_CR) {
143 struct sccp_connection_request *cr;
144 struct msgb *msg;
145
146 LOGP(DINP, LOGL_NOTICE, "Handling CR localy.\n");
147 cr = (struct sccp_connection_request *) inpt->l2h;
148 msg = create_sccp_refuse(&cr->source_local_reference);
149 if (msg) {
150 mtp_link_set_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg));
151 msgb_free(msg);
152 }
153 return;
154 } else if (inpt->l2h[0] == SCCP_MSG_TYPE_DT1 && result->data_len >= 3) {
155 struct active_sccp_con *con;
156 struct sccp_data_form1 *form1;
157 struct msgb *msg;
158
159 if (inpt->l3h[0] == 0 && inpt->l3h[2] == BSS_MAP_MSG_CLEAR_COMPLETE) {
160 LOGP(DINP, LOGL_DEBUG, "Received Clear Complete. Sending Release.\n");
161
162 form1 = (struct sccp_data_form1 *) inpt->l2h;
163
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100164 llist_for_each_entry(con, &link->app->sccp_connections, entry) {
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100165 if (memcmp(&form1->destination_local_reference,
166 &con->dst_ref, sizeof(con->dst_ref)) == 0) {
167 LOGP(DINP, LOGL_DEBUG, "Sending a release request now.\n");
168 msg = create_sccp_rlsd(&con->dst_ref, &con->src_ref);
169 if (msg) {
170 mtp_link_set_submit_sccp_data(link, con->sls, msg->l2h, msgb_l2len(msg));
171 msgb_free(msg);
172 }
173 return;
174 }
175 }
176
177 LOGP(DINP, LOGL_ERROR, "Could not find connection for the Clear Command.\n");
178 }
179 } else if (inpt->l2h[0] == SCCP_MSG_TYPE_UDT && result->data_len >= 3) {
180 if (inpt->l3h[0] == 0 && inpt->l3h[2] == BSS_MAP_MSG_RESET_ACKNOWLEDGE) {
181 LOGP(DINP, LOGL_NOTICE, "Reset ACK. Connecting to the MSC again.\n");
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100182 app_resources_released(link->app);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100183 return;
184 }
185 }
186
187
188 /* Update the state, maybe the connection was released? */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100189 update_con_state(link->app, 0, result, inpt, 0, sls);
190 if (llist_empty(&link->app->sccp_connections))
191 app_resources_released(link->app);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100192 return;
193}
194
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +0100195void app_clear_connections(struct ss7_application *app)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100196{
197 struct active_sccp_con *tmp, *con;
198
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100199 llist_for_each_entry_safe(con, tmp, &app->sccp_connections, entry) {
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100200 free_con(con);
201 }
202
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100203 link_clear_all(app->route_src.set);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100204}
205
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100206void app_resources_released(struct ss7_application *app)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100207{
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100208 bsc_del_timer(&app->reset_timeout);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100209}
210
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100211static void bsc_reset_timeout(void *_app)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100212{
213 struct msgb *msg;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100214 struct ss7_application *app = _app;
215 struct mtp_link_set *set = app->route_src.set;
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100216
217 /* no reset */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100218 if (app->reset_count > 0) {
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100219 LOGP(DINP, LOGL_ERROR, "The BSC did not answer the GSM08.08 reset. Restart MTP\n");
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100220 mtp_link_set_stop(app->route_src.set);
221 app_clear_connections(app);
222 link_reset_all(app->route_src.set);
223 app_resources_released(app);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100224 return;
225 }
226
227 msg = create_reset();
228 if (!msg) {
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100229 bsc_schedule_timer(&app->reset_timeout, 10, 0);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100230 return;
231 }
232
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100233 ++app->reset_count;
234 mtp_link_set_submit_sccp_data(set, -1, msg->l2h, msgb_l2len(msg));
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100235 msgb_free(msg);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100236 bsc_schedule_timer(&app->reset_timeout, 20, 0);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100237}
238
239/*
240 * We have lost the connection to the MSC. This is tough. We
241 * can not just bring down the MTP link as this will disable
242 * the BTS radio. We will have to do the following:
243 *
244 * 1.) Bring down all open SCCP connections. As this will close
245 * all radio resources
246 * 2.) Bring down all MGCP endpoints
247 * 3.) Clear the connection data.
248 *
249 * To make things worse we need to buffer the BSC messages... atfer
250 * everything has been sent we will try to connect to the MSC again.
251 *
252 * We will have to veriy that all connections are closed properly..
253 * this means we need to parse response message. In the case the
254 * MTP link is going down while we are sending. We will simply
255 * reconnect to the MSC.
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100256 *
257 * This could be called for the relay type and the cellmgr type, in case
258 * of the relay type the list of connections should be empty so we can
259 * avoid branching out.
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100260 */
Holger Hans Peter Freyther84ec8712011-02-15 20:01:47 +0100261void release_bsc_resources(struct msc_connection *fw)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100262{
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100263 struct ss7_application *app;
264 struct mtp_link_set *set;
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100265 struct active_sccp_con *tmp;
266 struct active_sccp_con *con;
267
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100268 if (!fw->app) {
269 LOGP(DINP, LOGL_ERROR, "No app assigned to the MSC connection %d/%s\n",
270 fw->nr, fw->name);
271 return;
272 }
273
274 app = fw->app;
275 set = app->route_src.set;
276 bsc_del_timer(&app->reset_timeout);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100277
278 /* 2. clear the MGCP endpoints */
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +0100279 msc_mgcp_reset(fw);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100280
281 /* 1. send BSSMAP Cleanup.. if we have any connection */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100282 llist_for_each_entry_safe(con, tmp, &app->sccp_connections, entry) {
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100283 if (!con->has_dst_ref) {
284 free_con(con);
285 continue;
286 }
287
288 struct msgb *msg = create_clear_command(&con->src_ref);
289 if (!msg)
290 continue;
291
292 /* wait for the clear commands */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100293 mtp_link_set_submit_sccp_data(set, con->sls, msg->l2h, msgb_l2len(msg));
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100294 msgb_free(msg);
295 }
296
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100297 if (llist_empty(&app->sccp_connections)) {
298 app_resources_released(app);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100299 } else {
300 /* Send a reset in 20 seconds if we fail to bring everything down */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100301 app->reset_timeout.cb = bsc_reset_timeout;
302 app->reset_timeout.data = app;
303 app->reset_count = 0;
304 bsc_schedule_timer(&app->reset_timeout, 10, 0);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100305 }
306}
307
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100308/**
309 * update the connection state and helpers below
310 */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100311static void send_rlc_to_bsc(struct mtp_link_set *set,
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100312 unsigned int sls, struct sccp_source_reference *src,
313 struct sccp_source_reference *dst)
314{
315 struct msgb *msg;
316
317 msg = create_sccp_rlc(src, dst);
318 if (!msg)
319 return;
320
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100321 mtp_link_set_submit_sccp_data(set, sls, msg->l2h, msgb_l2len(msg));
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100322 msgb_free(msg);
323}
324
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100325static void handle_rlsd(struct ss7_application *app, struct sccp_connection_released *rlsd, int from_msc)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100326{
327 struct active_sccp_con *con;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100328 struct msc_connection *msc = app->route_dst.msc;
329 struct mtp_link_set *set = app->route_src.set;
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100330
331 if (from_msc) {
332 /* search for a connection, reverse src/dest for MSC */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100333 con = find_con_by_src_dest_ref(app, &rlsd->destination_local_reference,
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100334 &rlsd->source_local_reference);
335 if (con) {
336 LOGP(DINP, LOGL_DEBUG, "RLSD conn still alive: local: 0x%x remote: 0x%x\n",
337 sccp_src_ref_to_int(&con->src_ref),
338 sccp_src_ref_to_int(&con->dst_ref));
339 con->released_from_msc = 1;
340 } else {
341 /* send RLC */
342 LOGP(DINP, LOGL_DEBUG, "Sending RLC for MSC: src: 0x%x dst: 0x%x\n",
343 sccp_src_ref_to_int(&rlsd->destination_local_reference),
344 sccp_src_ref_to_int(&rlsd->source_local_reference));
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100345 msc_send_rlc(msc, &rlsd->destination_local_reference,
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100346 &rlsd->source_local_reference);
347 }
348 } else {
349 unsigned int sls = -1;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100350 con = find_con_by_src_dest_ref(app, &rlsd->source_local_reference,
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100351 &rlsd->destination_local_reference);
352 if (con) {
353 LOGP(DINP, LOGL_DEBUG, "Timeout on BSC. Sending RLC. src: 0x%x\n",
354 sccp_src_ref_to_int(&rlsd->source_local_reference));
355
356 if (con->released_from_msc)
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100357 msc_send_rlc(msc, &con->src_ref, &con->dst_ref);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100358 sls = con->sls;
359 free_con(con);
360 } else {
361 LOGP(DINP, LOGL_ERROR, "Timeout on BSC for unknown connection. src: 0x%x\n",
362 sccp_src_ref_to_int(&rlsd->source_local_reference));
363 }
364
365 /* now send a rlc back to the BSC */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100366 send_rlc_to_bsc(set, sls, &rlsd->destination_local_reference, &rlsd->source_local_reference);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100367 }
368}
369
370/**
371 * Update connection state and also send message.....
372 *
373 * RLSD from MSC:
374 * 1.) We don't find the entry in this case we will send a
375 * forged RLC to the MSC and we are done.
376 * 2.) We find an entry in this we will need to register that
377 * we need to send a RLC and we are done for now.
378 * RLSD from BSC:
379 * 1.) This is an error we are ignoring for now.
380 * RLC from BSC:
381 * 1.) We are destroying the connection, we might send a RLC to
382 * the MSC if we are waiting for one.
383 */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100384void update_con_state(struct ss7_application *app, int rc, struct sccp_parse_result *res, struct msgb *msg, int from_msc, int sls)
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100385{
386 struct active_sccp_con *con;
387 struct sccp_connection_request *cr;
388 struct sccp_connection_confirm *cc;
389 struct sccp_connection_release_complete *rlc;
390 struct sccp_connection_refused *cref;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100391 struct msc_connection *msc;
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100392
393 /* was the header okay? */
394 if (rc < 0)
395 return;
396
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100397 msc = app->route_dst.msc;
398
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100399 /* the header was size checked */
400 switch (msg->l2h[0]) {
401 case SCCP_MSG_TYPE_CR:
402 if (from_msc) {
403 LOGP(DMSC, LOGL_ERROR, "CR from MSC is not handled.\n");
404 return;
405 }
406
407 cr = (struct sccp_connection_request *) msg->l2h;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100408 con = find_con_by_src_ref(app, &cr->source_local_reference);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100409 if (con) {
410 LOGP(DINP, LOGL_ERROR, "Duplicate SRC reference for: 0x%x. Reusing\n",
411 sccp_src_ref_to_int(&con->src_ref));
412 free_con(con);
413 }
414
415 con = talloc_zero(NULL, struct active_sccp_con);
416 if (!con) {
417 LOGP(DINP, LOGL_ERROR, "Failed to allocate\n");
418 return;
419 }
420
421 con->src_ref = cr->source_local_reference;
422 con->sls = sls;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100423 con->app = app;
424 llist_add_tail(&con->entry, &app->sccp_connections);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100425 LOGP(DINP, LOGL_DEBUG, "Adding CR: local ref: 0x%x\n", sccp_src_ref_to_int(&con->src_ref));
426 break;
427 case SCCP_MSG_TYPE_CC:
428 if (!from_msc) {
429 LOGP(DINP, LOGL_ERROR, "CC from BSC is not handled.\n");
430 return;
431 }
432
433 cc = (struct sccp_connection_confirm *) msg->l2h;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100434 con = find_con_by_src_ref(app, &cc->destination_local_reference);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100435 if (con) {
436 con->dst_ref = cc->source_local_reference;
437 con->has_dst_ref = 1;
438 LOGP(DINP, LOGL_DEBUG, "Updating CC: local: 0x%x remote: 0x%x\n",
439 sccp_src_ref_to_int(&con->src_ref), sccp_src_ref_to_int(&con->dst_ref));
440 return;
441 }
442
443 LOGP(DINP, LOGL_ERROR, "CCed connection can not be found: 0x%x\n",
444 sccp_src_ref_to_int(&cc->destination_local_reference));
445 break;
446 case SCCP_MSG_TYPE_CREF:
447 if (!from_msc) {
448 LOGP(DINP, LOGL_ERROR, "CREF from BSC is not handled.\n");
449 return;
450 }
451
452 cref = (struct sccp_connection_refused *) msg->l2h;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100453 con = find_con_by_src_ref(app, &cref->destination_local_reference);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100454 if (con) {
455 LOGP(DINP, LOGL_DEBUG, "Releasing local: 0x%x\n", sccp_src_ref_to_int(&con->src_ref));
456 free_con(con);
457 return;
458 }
459
460 LOGP(DINP, LOGL_ERROR, "CREF from BSC is not handled.\n");
461 break;
462 case SCCP_MSG_TYPE_RLSD:
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100463 handle_rlsd(app, (struct sccp_connection_released *) msg->l2h, from_msc);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100464 break;
465 case SCCP_MSG_TYPE_RLC:
466 if (from_msc) {
467 LOGP(DINP, LOGL_ERROR, "RLC from MSC is wrong.\n");
468 return;
469 }
470
471 rlc = (struct sccp_connection_release_complete *) msg->l2h;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100472 con = find_con_by_src_dest_ref(app, &rlc->source_local_reference,
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100473 &rlc->destination_local_reference);
474 if (con) {
475 LOGP(DINP, LOGL_DEBUG, "Releasing local: 0x%x\n", sccp_src_ref_to_int(&con->src_ref));
476 if (con->released_from_msc)
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100477 msc_send_rlc(msc, &con->src_ref, &con->dst_ref);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100478 free_con(con);
479 return;
480 }
481
482 LOGP(DINP, LOGL_ERROR, "RLC can not be found. 0x%x 0x%x\n",
483 sccp_src_ref_to_int(&rlc->source_local_reference),
484 sccp_src_ref_to_int(&rlc->destination_local_reference));
485 break;
486 }
487}
488
489static void send_local_rlsd_for_con(void *data)
490{
491 struct msgb *rlsd;
492 struct active_sccp_con *con = (struct active_sccp_con *) data;
493
494 /* try again in three seconds */
495 con->rlc_timeout.data = con;
496 con->rlc_timeout.cb = send_local_rlsd_for_con;
497 bsc_schedule_timer(&con->rlc_timeout, 3, 0);
498
499 /* we send this to the BSC so we need to switch src and dest */
500 rlsd = create_sccp_rlsd(&con->dst_ref, &con->src_ref);
501 if (!rlsd)
502 return;
503
504 ++con->rls_tries;
505 LOGP(DINP, LOGL_DEBUG, "Sending RLSD for 0x%x the %d time.\n",
506 sccp_src_ref_to_int(&con->src_ref), con->rls_tries);
507 mtp_link_set_submit_sccp_data(con->link, con->sls, rlsd->l2h, msgb_l2len(rlsd));
508 msgb_free(rlsd);
509}
510
511static void send_local_rlsd(struct mtp_link_set *link, struct sccp_parse_result *res)
512{
513 struct active_sccp_con *con;
514
515 LOGP(DINP, LOGL_DEBUG, "Received GSM Clear Complete. Sending RLSD locally.\n");
516
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100517 con = find_con_by_dest_ref(link->app, res->destination_local_reference);
Holger Hans Peter Freyther43b015a2011-02-10 17:35:35 +0100518 if (!con)
519 return;
520 con->rls_tries = 0;
521 send_local_rlsd_for_con(con);
522}
523
524static void send_reset_ack(struct mtp_link_set *link, int sls)
525{
526 static const uint8_t reset_ack[] = {
527 0x09, 0x00, 0x03, 0x05, 0x7, 0x02, 0x42, 0xfe,
528 0x02, 0x42, 0xfe, 0x03,
529 0x00, 0x01, 0x31
530 };
531
532 mtp_link_set_submit_sccp_data(link, sls, reset_ack, sizeof(reset_ack));
533}
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100534
535void msc_dispatch_sccp(struct msc_connection *msc, struct msgb *msg)
536{
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100537 struct mtp_link_set *set;
538
539 if (!msc->app) {
540 LOGP(DINP, LOGL_ERROR, "The MSC Connection %d/%s has no app assigned.\n",
541 msc->nr, msc->name);
542 return;
543 }
544
545
546 set = msc->app->route_src.set;
547
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100548 /* we can not forward it right now */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100549 if (msc->app->forward_only) {
550 if (!set->sccp_up)
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100551 return;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100552 mtp_link_set_submit_sccp_data(set, -1,
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100553 msg->l2h, msgb_l2len(msg));
554 } else {
555 struct sccp_parse_result result;
556 int rc;
557
558 rc = bss_patch_filter_msg(msg, &result);
559
560 if (rc == BSS_FILTER_RESET_ACK) {
561 LOGP(DMSC, LOGL_NOTICE, "Filtering reset ack from the MSC\n");
562 } else if (rc == BSS_FILTER_RLSD) {
563 LOGP(DMSC, LOGL_DEBUG, "Filtering RLSD from the MSC\n");
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100564 update_con_state(msc->app, rc, &result, msg, 1, 0);
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100565 } else if (rc == BSS_FILTER_RLC) {
566 /* if we receive this we have forwarded a RLSD to the network */
567 LOGP(DMSC, LOGL_ERROR, "RLC from the network. BAD!\n");
568 } else if (rc == BSS_FILTER_CLEAR_COMPL) {
569 LOGP(DMSC, LOGL_ERROR, "Clear Complete from the network.\n");
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100570 } else if (set->sccp_up) {
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100571 unsigned int sls;
572
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100573 update_con_state(msc->app, rc, &result, msg, 1, 0);
574 sls = sls_for_src_ref(msc->app, result.destination_local_reference);
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100575
576 /* Check for Location Update Accept */
577 bsc_ussd_handle_in_msg(msc, &result, msg);
578
579 /* patch a possible PC */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100580 bss_rewrite_header_to_bsc(msg, set->opc, set->dpc);
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100581
582 /* we can not forward it right now */
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100583 mtp_link_set_submit_sccp_data(set, sls,
Holger Hans Peter Freyther3d4d8c72011-02-15 21:14:09 +0100584 msg->l2h, msgb_l2len(msg));
585 }
586 }
587}