blob: ab0112b187e33230a21bc7613b0398f3907dd25b [file] [log] [blame]
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +01001/* Interaction with the SCCP subsystem */
2/*
3 * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * (C) 2009-2010 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 General Public License as published by
9 * the Free Software Foundation; either version 2 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 General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <openbsc/gsm_data.h>
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +010024#include <openbsc/osmo_bsc.h>
25#include <openbsc/osmo_bsc_grace.h>
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +010026#include <openbsc/osmo_msc_data.h>
27#include <openbsc/debug.h>
Holger Hans Peter Freyther00f4cc22010-11-06 23:50:06 +010028#include <openbsc/signal.h>
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +010029
30#include <osmocore/gsm0808.h>
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +010031#include <osmocore/talloc.h>
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +010032#include <osmocore/protocol/gsm_08_08.h>
33
34#include <osmocom/sccp/sccp.h>
35
Holger Hans Peter Freytherc97d9b42010-11-06 20:23:58 +010036/* SCCP helper */
37#define SCCP_IT_TIMER 60
38
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +010039static LLIST_HEAD(active_connections);
40
41static void msc_outgoing_sccp_data(struct sccp_connection *conn,
42 struct msgb *msg, unsigned int len)
43{
44}
45
46static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
47{
48}
49
Holger Hans Peter Freyther00f4cc22010-11-06 23:50:06 +010050static void bsc_sccp_force_free(struct osmo_bsc_sccp_con *data)
51{
52 if (data->conn) {
53 gsm0808_clear(data->conn);
54 subscr_con_free(data->conn);
55 data->conn = NULL;
56 }
57
58 sccp_connection_force_free(data->sccp);
59 data->sccp = NULL;
60 bsc_delete_connection(data);
61}
62
Holger Hans Peter Freytherc97d9b42010-11-06 20:23:58 +010063static void sccp_it_timeout(void *_data)
64{
65 struct osmo_bsc_sccp_con *data =
66 (struct osmo_bsc_sccp_con *) _data;
67
68 sccp_connection_send_it(data->sccp);
69 bsc_schedule_timer(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
70}
71
72static void sccp_cc_timeout(void *_data)
73{
74 struct osmo_bsc_sccp_con *data =
75 (struct osmo_bsc_sccp_con *) _data;
76
77 if (data->sccp->connection_state >= SCCP_CONNECTION_STATE_ESTABLISHED)
78 return;
79
80 LOGP(DMSC, LOGL_ERROR, "The connection was never established.\n");
Holger Hans Peter Freyther00f4cc22010-11-06 23:50:06 +010081 bsc_sccp_force_free(data);
Holger Hans Peter Freytherc97d9b42010-11-06 20:23:58 +010082}
83
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +010084static void msc_sccp_write_ipa(struct sccp_connection *conn, struct msgb *msg, void *data)
85{
86 LOGP(DMSC, LOGL_ERROR, "Writing is not implemented.\n");
87 msgb_free(msg);
88}
89
90static int msc_sccp_accept(struct sccp_connection *connection, void *data)
91{
92 LOGP(DMSC, LOGL_DEBUG, "Rejecting incoming SCCP connection.\n");
93 return -1;
94}
95
96static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
97{
98 struct bssmap_header *bs;
99
100 LOGP(DMSC, LOGL_DEBUG, "Incoming SCCP message ftom MSC: %s\n",
101 hexdump(msgb->l3h, length));
102
103 if (length < sizeof(*bs)) {
104 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
105 return -1;
106 }
107
108 bs = (struct bssmap_header *) msgb->l3h;
109 if (bs->length < length - sizeof(*bs))
110 return -1;
111
112 switch (bs->type) {
113 case BSSAP_MSG_BSS_MANAGEMENT:
Holger Hans Peter Freyther1999cf12010-11-03 18:46:52 +0100114 LOGP(DMSC, LOGL_ERROR, "BSS management not implemented.\n");
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +0100115 break;
116 default:
117 LOGP(DMSC, LOGL_ERROR, "Unimplemented msg type: %d\n", bs->type);
118 }
119
120 return 0;
121}
122
Holger Hans Peter Freyther45825862010-11-04 11:48:49 +0100123int bsc_queue_for_msc(struct gsm_subscriber_connection *conn, struct msgb *msg)
124{
Holger Hans Peter Freytherca5c0222010-11-06 23:35:02 +0100125 struct sccp_connection *sccp = conn->sccp_con->sccp;
126
127 if (sccp->connection_state != SCCP_CONNECTION_STATE_ESTABLISHED) {
128 LOGP(DMSC, LOGL_ERROR, "The connection is not established.\n");
129 msgb_free(msg);
130 return -1;
131 }
132
133 sccp_connection_write(sccp, msg);
Holger Hans Peter Freyther45825862010-11-04 11:48:49 +0100134 msgb_free(msg);
135 return 0;
136}
137
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +0100138int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
Holger Hans Peter Freythercc48fb82010-11-05 11:10:46 +0100139{
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +0100140 struct gsm_network *net;
141 struct osmo_bsc_sccp_con *bsc_con;
142 struct sccp_connection *sccp;
143
144 net = conn->bts->network;
145 if (!net->msc_data->msc_con->is_authenticated) {
146 LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
147 return -1;
148 }
149
150 if (!bsc_grace_allow_new_connection(net)) {
151 LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
152 return -1;
153 }
154
155 sccp = sccp_connection_socket();
156 if (!sccp) {
157 LOGP(DMSC, LOGL_ERROR, "Failed to allocate memory.\n");
158 return -ENOMEM;
159 }
160
161 bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
162 if (!bsc_con) {
163 LOGP(DMSC, LOGL_ERROR, "Failed to allocate.\n");
164 sccp_connection_free(sccp);
165 return -1;
166 }
167
168 /* callbacks */
169 sccp->state_cb = msc_outgoing_sccp_state;
170 sccp->data_cb = msc_outgoing_sccp_data;
171 sccp->data_ctx = bsc_con;
172
Holger Hans Peter Freytherc97d9b42010-11-06 20:23:58 +0100173 /* prepare the timers */
174 bsc_con->sccp_it_timeout.cb = sccp_it_timeout;
175 bsc_con->sccp_it_timeout.data = bsc_con;
176 bsc_con->sccp_cc_timeout.cb = sccp_cc_timeout;
177 bsc_con->sccp_cc_timeout.data = bsc_con;
178
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +0100179 bsc_con->sccp = sccp;
180 bsc_con->msc_con = net->msc_data->msc_con;
Holger Hans Peter Freyther7e901082010-11-06 20:15:17 +0100181 bsc_con->conn = conn;
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +0100182 llist_add(&bsc_con->entry, &active_connections);
183 conn->sccp_con = bsc_con;
184 return 0;
Holger Hans Peter Freythercc48fb82010-11-05 11:10:46 +0100185}
186
Holger Hans Peter Freyther7e901082010-11-06 20:15:17 +0100187int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +0100188{
189 LOGP(DMSC, LOGL_ERROR, "Not implemented yet.\n");
190 return -1;
191}
192
Holger Hans Peter Freyther7e901082010-11-06 20:15:17 +0100193int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +0100194{
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +0100195 if (!sccp)
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +0100196 return 0;
197
Holger Hans Peter Freyther7e901082010-11-06 20:15:17 +0100198 if (sccp->conn)
199 LOGP(DMSC, LOGL_ERROR, "Should have been cleared.\n");
200
Holger Hans Peter Freytherb8781d22010-11-06 18:08:43 +0100201 llist_del(&sccp->entry);
202 bsc_del_timer(&sccp->sccp_it_timeout);
203 bsc_del_timer(&sccp->sccp_cc_timeout);
204 talloc_free(sccp);
Holger Hans Peter Freyther9b17c762010-11-05 19:48:47 +0100205 return 0;
206}
207
Holger Hans Peter Freyther00f4cc22010-11-06 23:50:06 +0100208static void bsc_close_connections(struct bsc_msc_connection *msc_con)
209{
210 struct osmo_bsc_sccp_con *con, *tmp;
211
212 llist_for_each_entry_safe(con, tmp, &active_connections, entry)
213 bsc_sccp_force_free(con);
214}
215
216static int handle_msc_signal(unsigned int subsys, unsigned int signal,
217 void *handler_data, void *signal_data)
218{
219 struct osmo_msc_data *data;
220
221 if (subsys != SS_MSC)
222 return 0;
223
224 data = (struct osmo_msc_data *) signal_data;
225 if (signal == S_MSC_LOST)
226 bsc_close_connections(data->msc_con);
227
228 return 0;
229}
230
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +0100231int osmo_bsc_sccp_init(struct gsm_network *gsmnet)
232{
233 sccp_set_log_area(DSCCP);
234 sccp_system_init(msc_sccp_write_ipa, gsmnet);
235 sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
236 sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, NULL);
237
Holger Hans Peter Freyther00f4cc22010-11-06 23:50:06 +0100238 register_signal_handler(SS_MSC, handle_msc_signal, gsmnet);
239
Holger Hans Peter Freytherf3d1ae72010-11-03 16:40:03 +0100240 return 0;
241}