blob: 485aa2e2376737b29f79aa80bb71119fcddae657 [file] [log] [blame]
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +01001/*
2 * The SS7 Application part for forwarding or nat...
3 *
4 * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2010-2011 by On-Waves
6 * All Rights Reserved
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <ss7_application.h>
24#include <bsc_data.h>
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +010025#include <bsc_sccp.h>
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +010026#include <cellmgr_debug.h>
27#include <msc_connection.h>
28#include <sctp_m2ua.h>
29
30#include <osmocore/talloc.h>
31
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +010032
33/* the SS7 dispatch... maybe as function pointers in the future */
Holger Hans Peter Freyther64b7d562011-02-16 23:00:50 +010034void forward_sccp_stp(struct mtp_link_set *set, struct msgb *_msg, int sls)
35{
36 struct mtp_link_set *other;
37 other = set->app->route_src.set == set ?
38 set->app->route_dst.set : set->app->route_src.set;
39 mtp_link_set_submit_sccp_data(other, sls, _msg->l2h, msgb_l2len(_msg));
40}
41
42void forward_isup_stp(struct mtp_link_set *set, struct msgb *msg, int sls)
43{
44 struct mtp_link_set *other;
45 other = set->app->route_src.set == set ?
46 set->app->route_dst.set : set->app->route_src.set;
47 mtp_link_set_submit_isup_data(other, sls, msg->l3h, msgb_l3len(msg));
48}
49
50void mtp_link_set_forward_sccp(struct mtp_link_set *set, struct msgb *_msg, int sls)
51{
52 if (!set->app) {
53 LOGP(DINP, LOGL_ERROR, "Linkset %d/%s has no application.\n",
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +010054 set->nr, set->name);
Holger Hans Peter Freyther64b7d562011-02-16 23:00:50 +010055 return;
56 }
57
58 switch (set->app->type) {
59 case APP_STP:
60 forward_sccp_stp(set, _msg, sls);
61 break;
62 case APP_CELLMGR:
63 case APP_RELAY:
64 app_forward_sccp(set->app, _msg, sls);
65 break;
66 }
67}
68
69void mtp_link_set_forward_isup(struct mtp_link_set *set, struct msgb *msg, int sls)
70{
71 if (!set->app) {
72 LOGP(DINP, LOGL_ERROR, "Linkset %d/%s has no application.\n",
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +010073 set->nr, set->name);
Holger Hans Peter Freyther64b7d562011-02-16 23:00:50 +010074 return;
75 }
76
77
78 switch (set->app->type) {
79 case APP_STP:
80 forward_isup_stp(set, msg, sls);
81 break;
82 case APP_CELLMGR:
83 case APP_RELAY:
84 LOGP(DINP, LOGL_ERROR, "ISUP is not handled.\n");
85 break;
86 }
87}
88
Holger Hans Peter Freytherc5200fc2011-02-16 22:35:30 +010089void mtp_linkset_down(struct mtp_link_set *set)
90{
91 set->available = 0;
92 mtp_link_set_stop(set);
93
94 if (set->app && set->app->type != APP_STP) {
95 app_clear_connections(set->app);
96
97 /* If we have an A link send a reset to the MSC */
98 msc_mgcp_reset(set->app->route_dst.msc);
99 msc_send_reset(set->app->route_dst.msc);
100 }
101}
102
103void mtp_linkset_up(struct mtp_link_set *set)
104{
105 set->available = 1;
106
107 /* we have not gone through link down */
108 if (set->app && set->app->type != APP_STP &&
109 set->app->route_dst.msc->msc_link_down) {
110 app_clear_connections(set->app);
111 app_resources_released(set->app);
112 }
113
114 mtp_link_set_reset(set);
115}
116
117
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100118struct ss7_application *ss7_application_alloc(struct bsc_data *bsc)
119{
120 struct ss7_application *app;
121
122 app = talloc_zero(bsc, struct ss7_application);
123 if (!app) {
124 LOGP(DINP, LOGL_ERROR, "Failed to create SS7 Application.\n");
125 return NULL;
126 }
127
128 INIT_LLIST_HEAD(&app->sccp_connections);
Holger Hans Peter Freyther169a1a92011-02-22 15:45:52 +0100129 llist_add_tail(&app->entry, &bsc->apps);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100130 app->nr = bsc->num_apps++;
131 app->bsc = bsc;
132
133 return app;
134}
135
136struct ss7_application *ss7_application_num(struct bsc_data *bsc, int num)
137{
138 struct ss7_application *ss7;
139
140 llist_for_each_entry(ss7, &bsc->apps, entry)
141 if (ss7->nr == num)
142 return ss7;
143
144 return NULL;
145}
146
147static int ss7_app_setup_stp(struct ss7_application *app,
148 int src_type, int src_num,
149 int dst_type, int dst_num)
150{
151 struct mtp_link_set *src, *dst;
152
153 if (src_type != SS7_SET_LINKSET) {
154 LOGP(DINP, LOGL_ERROR,
155 "SS7 %d/%s source needs to be a linkset.\n",
156 app->nr, app->name);
157 return -1;
158 }
159
160 if (dst_type != SS7_SET_LINKSET) {
161 LOGP(DINP, LOGL_ERROR,
162 "SS7 %d/%s destination needs to be a linkset.\n",
163 app->nr, app->name);
164 return -1;
165 }
166
167 /* veryify the MTP Linkset */
168 src = mtp_link_set_num(app->bsc, src_num);
169 if (!src) {
170 LOGP(DINP, LOGL_ERROR,
171 "SS7 %d/%s source linkset not found with nr: %d.\n",
172 app->nr, app->name, src_num);
173 return -2;
174 }
175
176 if (src->app) {
177 LOGP(DINP, LOGL_ERROR,
178 "SS7 %d/%s is using linkset %d/%s\n",
179 src->app->nr, src->app->name,
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +0100180 src->nr, src->name);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100181 return -3;
182 }
183
184 /* veryify the MTP Linkset */
185 dst = mtp_link_set_num(app->bsc, dst_num);
186 if (!dst) {
187 LOGP(DINP, LOGL_ERROR,
188 "SS7 %d/%s destionation linkset not found with nr: %d.\n",
189 app->nr, app->name, dst_num);
190 return -2;
191 }
192
193 if (dst->app) {
194 LOGP(DINP, LOGL_ERROR,
195 "SS7 %d/%s is using linkset %d/%s\n",
196 dst->app->nr, dst->app->name,
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +0100197 dst->nr, dst->name);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100198 return -3;
199 }
200
201 /* now connect it */
202 src->app = app;
203 app->route_src.type = src_type;
204 app->route_src.nr = src_num;
205 app->route_src.set = src;
206 app->route_src.msc = NULL;
207
208 dst->app = app;
209 app->route_dst.type = dst_type;
210 app->route_dst.nr = dst_num;
211 app->route_dst.set = dst;
212 app->route_dst.msc = NULL;
213
214 app->type = APP_STP;
215 app->bsc->m2ua_trans->started = 1;
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100216 app->route_is_set = 1;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100217
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100218 return 0;
219}
220
221static int ss7_app_setup_relay(struct ss7_application *app, int type,
222 int src_type, int src_num, int dst_type, int dst_num)
223{
224 struct mtp_link_set *mtp;
225 struct msc_connection *msc;
226
227 /* verify the types */
228 if (src_type != SS7_SET_LINKSET) {
229 LOGP(DINP, LOGL_ERROR,
230 "SS7 %d/%s source needs to be a linkset.\n",
231 app->nr, app->name);
232 return -1;
233 }
234
235 if (dst_type != SS7_SET_MSC) {
236 LOGP(DINP, LOGL_ERROR,
237 "SS7 %d/%s dest needs to be a MSC.\n",
238 app->nr, app->name);
239 return -1;
240 }
241
242 /* veryify the MTP Linkset */
243 mtp = mtp_link_set_num(app->bsc, src_num);
244 if (!mtp) {
245 LOGP(DINP, LOGL_ERROR,
246 "SS7 %d/%s source linkset not found with nr: %d.\n",
247 app->nr, app->name, src_num);
248 return -2;
249 }
250
251 if (mtp->app) {
252 LOGP(DINP, LOGL_ERROR,
253 "SS7 %d/%s is using linkset %d/%s\n",
254 mtp->app->nr, mtp->app->name,
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +0100255 mtp->nr, mtp->name);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100256 return -3;
257 }
258
259 /* verify the MSC connection */
260 msc = msc_connection_num(app->bsc, dst_num);
261 if (!msc) {
262 LOGP(DINP, LOGL_ERROR,
263 "SS7 %d/%s dest MSC not found with nr: %d.\n",
264 app->nr, app->name, dst_num);
265 return -4;
266 }
267
268 if (msc->app) {
269 LOGP(DINP, LOGL_ERROR,
270 "SS7 %d/%s is using MSC connection %d/%s\n",
271 msc->app->nr, msc->app->name,
272 msc->nr, msc->name);
273 return -5;
274 }
275
276
277 /* now connect it and run the app */
278 mtp->app = app;
279 app->route_src.type = src_type;
280 app->route_src.nr = src_num;
281 app->route_src.set = mtp;
282 app->route_src.msc = NULL;
283
284 msc->app = app;
285 app->route_dst.type = dst_type;
286 app->route_dst.nr = dst_num;
287 app->route_dst.set = NULL;
288 app->route_dst.msc = msc;
289
290 app->type = type;
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100291 app->route_is_set = 1;
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100292
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100293 return 0;
294}
295
296int ss7_application_setup(struct ss7_application *ss7, int type,
297 int src_type, int src_num,
298 int dst_type, int dst_num)
299{
300 switch (type) {
301 case APP_CELLMGR:
302 case APP_RELAY:
303 return ss7_app_setup_relay(ss7, type, src_type, src_num,
304 dst_type, dst_num);
305 break;
306 case APP_STP:
307 return ss7_app_setup_stp(ss7, src_type, src_num,
308 dst_type, dst_num);
309 default:
310 LOGP(DINP, LOGL_ERROR,
311 "SS7 Application %d is not supported.\n", type);
312 return -1;
313 }
314}
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100315
316
317static void start_mtp(struct mtp_link_set *set)
318{
319 struct mtp_link *link;
320
321 llist_for_each_entry(link, &set->links, entry)
322 link->reset(link);
323}
324
325static void start_msc(struct msc_connection *msc)
326{
327 msc_connection_start(msc);
328}
329
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100330static void start_set(struct ss7_application *app, struct mtp_link_set *set)
331{
332 if (!set)
333 return;
334
335 set->isup_opc = set->isup_opc >= 0 ? set->isup_opc : set->opc;
336 set->sccp_opc = set->sccp_opc >= 0 ? set->sccp_opc : set->opc;
337 set->pass_all_isup = app->isup_pass;
338 start_mtp(set);
339}
340
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100341int ss7_application_start(struct ss7_application *app)
342{
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100343 if (!app->route_is_set) {
344 LOGP(DINP, LOGL_ERROR,
345 "The routes are not configured on app %d.\n", app->nr);
346 return -1;
347 }
348
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100349 start_set(app, app->route_src.set);
350 start_set(app, app->route_dst.set);
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100351
352 if (app->route_src.msc)
353 start_msc(app->route_src.msc);
354 if (app->route_dst.msc)
355 start_msc(app->route_dst.msc);
356
357 LOGP(DINP, LOGL_NOTICE, "SS7 Application %d/%s is now running.\n",
358 app->nr, app->name);
359 return 0;
360}
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100361
362void ss7_application_pass_isup(struct ss7_application *app, int pass)
363{
364 if (app->route_src.set)
365 app->route_src.set->pass_all_isup = pass;
366 if (app->route_dst.set)
367 app->route_dst.set->pass_all_isup = pass;
368}