blob: b3c90365f29b6245bcfe10f739a2d9cce95639b3 [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;
216
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100217 return 0;
218}
219
220static int ss7_app_setup_relay(struct ss7_application *app, int type,
221 int src_type, int src_num, int dst_type, int dst_num)
222{
223 struct mtp_link_set *mtp;
224 struct msc_connection *msc;
225
226 /* verify the types */
227 if (src_type != SS7_SET_LINKSET) {
228 LOGP(DINP, LOGL_ERROR,
229 "SS7 %d/%s source needs to be a linkset.\n",
230 app->nr, app->name);
231 return -1;
232 }
233
234 if (dst_type != SS7_SET_MSC) {
235 LOGP(DINP, LOGL_ERROR,
236 "SS7 %d/%s dest needs to be a MSC.\n",
237 app->nr, app->name);
238 return -1;
239 }
240
241 /* veryify the MTP Linkset */
242 mtp = mtp_link_set_num(app->bsc, src_num);
243 if (!mtp) {
244 LOGP(DINP, LOGL_ERROR,
245 "SS7 %d/%s source linkset not found with nr: %d.\n",
246 app->nr, app->name, src_num);
247 return -2;
248 }
249
250 if (mtp->app) {
251 LOGP(DINP, LOGL_ERROR,
252 "SS7 %d/%s is using linkset %d/%s\n",
253 mtp->app->nr, mtp->app->name,
Holger Hans Peter Freythera33b23f2011-02-16 23:37:40 +0100254 mtp->nr, mtp->name);
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100255 return -3;
256 }
257
258 /* verify the MSC connection */
259 msc = msc_connection_num(app->bsc, dst_num);
260 if (!msc) {
261 LOGP(DINP, LOGL_ERROR,
262 "SS7 %d/%s dest MSC not found with nr: %d.\n",
263 app->nr, app->name, dst_num);
264 return -4;
265 }
266
267 if (msc->app) {
268 LOGP(DINP, LOGL_ERROR,
269 "SS7 %d/%s is using MSC connection %d/%s\n",
270 msc->app->nr, msc->app->name,
271 msc->nr, msc->name);
272 return -5;
273 }
274
275
276 /* now connect it and run the app */
277 mtp->app = app;
278 app->route_src.type = src_type;
279 app->route_src.nr = src_num;
280 app->route_src.set = mtp;
281 app->route_src.msc = NULL;
282
283 msc->app = app;
284 app->route_dst.type = dst_type;
285 app->route_dst.nr = dst_num;
286 app->route_dst.set = NULL;
287 app->route_dst.msc = msc;
288
289 app->type = type;
290
Holger Hans Peter Freythera7bc3aa2011-02-16 16:12:07 +0100291 return 0;
292}
293
294int ss7_application_setup(struct ss7_application *ss7, int type,
295 int src_type, int src_num,
296 int dst_type, int dst_num)
297{
298 switch (type) {
299 case APP_CELLMGR:
300 case APP_RELAY:
301 return ss7_app_setup_relay(ss7, type, src_type, src_num,
302 dst_type, dst_num);
303 break;
304 case APP_STP:
305 return ss7_app_setup_stp(ss7, src_type, src_num,
306 dst_type, dst_num);
307 default:
308 LOGP(DINP, LOGL_ERROR,
309 "SS7 Application %d is not supported.\n", type);
310 return -1;
311 }
312}
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100313
314
315static void start_mtp(struct mtp_link_set *set)
316{
317 struct mtp_link *link;
318
319 llist_for_each_entry(link, &set->links, entry)
320 link->reset(link);
321}
322
323static void start_msc(struct msc_connection *msc)
324{
325 msc_connection_start(msc);
326}
327
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100328static void start_set(struct ss7_application *app, struct mtp_link_set *set)
329{
330 if (!set)
331 return;
332
333 set->isup_opc = set->isup_opc >= 0 ? set->isup_opc : set->opc;
334 set->sccp_opc = set->sccp_opc >= 0 ? set->sccp_opc : set->opc;
335 set->pass_all_isup = app->isup_pass;
336 start_mtp(set);
337}
338
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100339int ss7_application_start(struct ss7_application *app)
340{
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100341 start_set(app, app->route_src.set);
342 start_set(app, app->route_dst.set);
Holger Hans Peter Freytherab7c6012011-02-16 22:23:52 +0100343
344 if (app->route_src.msc)
345 start_msc(app->route_src.msc);
346 if (app->route_dst.msc)
347 start_msc(app->route_dst.msc);
348
349 LOGP(DINP, LOGL_NOTICE, "SS7 Application %d/%s is now running.\n",
350 app->nr, app->name);
351 return 0;
352}
Holger Hans Peter Freythercfe9d712011-02-17 20:32:09 +0100353
354void ss7_application_pass_isup(struct ss7_application *app, int pass)
355{
356 if (app->route_src.set)
357 app->route_src.set->pass_all_isup = pass;
358 if (app->route_dst.set)
359 app->route_dst.set->pass_all_isup = pass;
360}