blob: 8832057816daa237c3c3ce5d0fd3545e84855d65 [file] [log] [blame]
Daniel Willmann5ff06af2011-08-05 12:20:58 +02001/* (C) 2011 by Daniel Willmann <daniel@totalueberwachung.de>
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +02002 * (C) 2011 by Holger Hans Peter Freyther
Daniel Willmann5ff06af2011-08-05 12:20:58 +02003 * (C) 2011 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <openbsc/control_cmd.h>
22#include <openbsc/debug.h>
23#include <openbsc/gsm_data.h>
24#include <openbsc/osmo_bsc.h>
25#include <openbsc/osmo_bsc_rf.h>
26#include <openbsc/osmo_msc_data.h>
Daniel Willmann806d6542011-10-28 14:23:48 +020027#include <openbsc/signal.h>
Daniel Willmann5ff06af2011-08-05 12:20:58 +020028
29#include <osmocom/core/linuxlist.h>
Daniel Willmann806d6542011-10-28 14:23:48 +020030#include <osmocom/core/signal.h>
Daniel Willmann5ff06af2011-08-05 12:20:58 +020031#include <osmocom/core/talloc.h>
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <time.h>
36#include <unistd.h>
37
Jacob Erlbeck779a7282013-09-11 10:46:57 +020038#define TIME_FORMAT_RFC2822 "%a, %d %b %Y %T %z"
39
Daniel Willmann5ff06af2011-08-05 12:20:58 +020040void osmo_bsc_send_trap(struct ctrl_cmd *cmd, struct bsc_msc_connection *msc_con)
41{
42 struct ctrl_cmd *trap;
43 struct ctrl_handle *ctrl;
44 struct osmo_msc_data *msc_data;
45
46 msc_data = (struct osmo_msc_data *) msc_con->write_queue.bfd.data;
47 ctrl = msc_data->network->ctrl;
48
49 trap = ctrl_cmd_trap(cmd);
50 if (!trap) {
51 LOGP(DCTRL, LOGL_ERROR, "Failed to create trap.\n");
52 return;
53 }
54
55 ctrl_cmd_send_to_all(ctrl, trap);
56 ctrl_cmd_send(&msc_con->write_queue, trap);
57
58 talloc_free(trap);
59}
60
Holger Hans Peter Freyther11590052014-05-14 09:50:27 +020061CTRL_CMD_DEFINE_RO(msc_connection_status, "msc_connection_status");
Daniel Willmann806d6542011-10-28 14:23:48 +020062static int msc_connection_status = 0;
63
64static int get_msc_connection_status(struct ctrl_cmd *cmd, void *data)
65{
66 if (msc_connection_status)
67 cmd->reply = "connected";
68 else
69 cmd->reply = "disconnected";
70 return CTRL_CMD_REPLY;
71}
72
Daniel Willmann806d6542011-10-28 14:23:48 +020073static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
74{
75 struct ctrl_cmd *cmd;
76 struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
77
78 if (signal == S_MSC_LOST && msc_connection_status == 1) {
79 LOGP(DCTRL, LOGL_DEBUG, "MSC connection lost, sending TRAP.\n");
80 msc_connection_status = 0;
81 } else if (signal == S_MSC_CONNECTED && msc_connection_status == 0) {
82 LOGP(DCTRL, LOGL_DEBUG, "MSC connection (re)established, sending TRAP.\n");
83 msc_connection_status = 1;
84 } else {
85 return 0;
86 }
87
88 cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
89 if (!cmd) {
90 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
91 return 0;
92 }
93
94 cmd->id = "0";
95 cmd->variable = "msc_connection_status";
96
97 get_msc_connection_status(cmd, NULL);
98
99 ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
100
101 talloc_free(cmd);
102
103 return 0;
104}
105
Holger Hans Peter Freyther11590052014-05-14 09:50:27 +0200106CTRL_CMD_DEFINE_RO(bts_connection_status, "bts_connection_status");
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100107static int bts_connection_status = 0;
108
109static int get_bts_connection_status(struct ctrl_cmd *cmd, void *data)
110{
111 if (bts_connection_status)
112 cmd->reply = "connected";
113 else
114 cmd->reply = "disconnected";
115 return CTRL_CMD_REPLY;
116}
117
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100118static int bts_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
119{
120 struct ctrl_cmd *cmd;
121 struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
122 struct gsm_bts *bts;
123 int bts_current_status;
124
125 if (signal != S_L_INP_TEI_DN && signal != S_L_INP_TEI_UP) {
126 return 0;
127 }
128
129 bts_current_status = 0;
130 /* Check if OML on at least one BTS is up */
131 llist_for_each_entry(bts, &gsmnet->bts_list, list) {
132 if (bts->oml_link) {
133 bts_current_status = 1;
134 break;
135 }
136 }
137 if (bts_connection_status == 0 && bts_current_status == 1) {
138 LOGP(DCTRL, LOGL_DEBUG, "BTS connection (re)established, sending TRAP.\n");
139 } else if (bts_connection_status == 1 && bts_current_status == 0) {
140 LOGP(DCTRL, LOGL_DEBUG, "No more BTS connected, sending TRAP.\n");
141 } else {
142 return 0;
143 }
144
145 cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
146 if (!cmd) {
147 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
148 return 0;
149 }
150
151 bts_connection_status = bts_current_status;
152
153 cmd->id = "0";
154 cmd->variable = "bts_connection_status";
155
156 get_bts_connection_status(cmd, NULL);
157
158 ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
159
160 talloc_free(cmd);
161
162 return 0;
163}
Daniel Willmann806d6542011-10-28 14:23:48 +0200164
Daniel Willmann11620112011-08-19 19:32:09 +0200165static int get_bts_loc(struct ctrl_cmd *cmd, void *data);
166
167static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_connection *msc_con)
168{
169 struct ctrl_cmd *cmd;
Daniel Willmann65924a52011-08-19 19:38:31 +0200170 const char *oper, *admin, *policy;
Daniel Willmann11620112011-08-19 19:32:09 +0200171
172 cmd = ctrl_cmd_create(msc_con, CTRL_TYPE_TRAP);
173 if (!cmd) {
174 LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n");
175 return;
176 }
177
178 cmd->id = "0";
Daniel Willmann6088f142011-08-25 16:37:45 +0200179 cmd->variable = talloc_asprintf(cmd, "bts.%i.location-state", bts->nr);
Daniel Willmann11620112011-08-19 19:32:09 +0200180
181 /* Prepare the location reply */
182 cmd->node = bts;
183 get_bts_loc(cmd, NULL);
184
Daniel Willmann65924a52011-08-19 19:38:31 +0200185 oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
186 admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
187 policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
188
Holger Hans Peter Freytherecdf9122014-02-04 17:09:55 +0100189 cmd->reply = talloc_asprintf_append(cmd->reply,
190 ",%s,%s,%s,%d,%d",
191 oper, admin, policy,
192 bts->network->country_code,
193 bts->network->network_code);
Daniel Willmann65924a52011-08-19 19:38:31 +0200194
Daniel Willmann11620112011-08-19 19:32:09 +0200195 osmo_bsc_send_trap(cmd, msc_con);
196 talloc_free(cmd);
197}
198
Holger Hans Peter Freyther98258db2014-02-22 10:30:32 +0100199void bsc_gen_location_state_trap(struct gsm_bts *bts)
200{
201 struct osmo_msc_data *msc;
202
203 llist_for_each_entry(msc, &bts->network->bsc_data->mscs, entry)
204 generate_location_state_trap(bts, msc->msc_con);
205}
206
Daniel Willmanna5352a02011-08-05 14:08:58 +0200207static int location_equal(struct bts_location *a, struct bts_location *b)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200208{
209 return ((a->tstamp == b->tstamp) && (a->valid == b->valid) && (a->lat == b->lat) &&
210 (a->lon == b->lon) && (a->height == b->height));
211}
212
Daniel Willmanna5352a02011-08-05 14:08:58 +0200213static void cleanup_locations(struct llist_head *locations)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200214{
Daniel Willmanna5352a02011-08-05 14:08:58 +0200215 struct bts_location *myloc, *tmp;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200216 int invalpos = 0, i = 0;
217
218 LOGP(DCTRL, LOGL_DEBUG, "Checking position list.\n");
Daniel Willmanna5352a02011-08-05 14:08:58 +0200219 llist_for_each_entry_safe(myloc, tmp, locations, list) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200220 i++;
221 if (i > 3) {
222 LOGP(DCTRL, LOGL_DEBUG, "Deleting old position.\n");
223 llist_del(&myloc->list);
224 talloc_free(myloc);
Daniel Willmanna5352a02011-08-05 14:08:58 +0200225 } else if (myloc->valid == BTS_LOC_FIX_INVALID) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200226 /* Only capture the newest of subsequent invalid positions */
227 invalpos++;
228 if (invalpos > 1) {
229 LOGP(DCTRL, LOGL_DEBUG, "Deleting subsequent invalid position.\n");
230 invalpos--;
231 i--;
232 llist_del(&myloc->list);
233 talloc_free(myloc);
234 }
235 } else {
236 invalpos = 0;
237 }
238 }
239 LOGP(DCTRL, LOGL_DEBUG, "Found %i positions.\n", i);
240}
241
Daniel Willmanna5352a02011-08-05 14:08:58 +0200242CTRL_CMD_DEFINE(bts_loc, "location");
243static int get_bts_loc(struct ctrl_cmd *cmd, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200244{
Daniel Willmanna5352a02011-08-05 14:08:58 +0200245 struct bts_location *curloc;
246 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
247 if (!bts) {
248 cmd->reply = "bts not found.";
249 return CTRL_CMD_ERROR;
250 }
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200251
Daniel Willmanna5352a02011-08-05 14:08:58 +0200252 if (llist_empty(&bts->loc_list)) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200253 cmd->reply = talloc_asprintf(cmd, "0,invalid,0,0,0");
254 return CTRL_CMD_REPLY;
255 } else {
Daniel Willmanna5352a02011-08-05 14:08:58 +0200256 curloc = llist_entry(bts->loc_list.next, struct bts_location, list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200257 }
258
Daniel Willmanna5352a02011-08-05 14:08:58 +0200259 cmd->reply = talloc_asprintf(cmd, "%lu,%s,%f,%f,%f", curloc->tstamp,
Daniel Willmann7d109832012-05-14 18:43:23 +0200260 get_value_string(bts_loc_fix_names, curloc->valid), curloc->lat, curloc->lon, curloc->height);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200261 if (!cmd->reply) {
262 cmd->reply = "OOM";
263 return CTRL_CMD_ERROR;
264 }
265
266 return CTRL_CMD_REPLY;
267}
268
Daniel Willmanna5352a02011-08-05 14:08:58 +0200269static int set_bts_loc(struct ctrl_cmd *cmd, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200270{
271 char *saveptr, *lat, *lon, *height, *tstamp, *valid, *tmp;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200272 struct bts_location *curloc, *lastloc;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200273 int ret;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200274 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
275 if (!bts) {
276 cmd->reply = "bts not found.";
277 return CTRL_CMD_ERROR;
278 }
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200279
280 tmp = talloc_strdup(cmd, cmd->value);
281 if (!tmp)
282 goto oom;
283
Daniel Willmanna5352a02011-08-05 14:08:58 +0200284 curloc = talloc_zero(tall_bsc_ctx, struct bts_location);
285 if (!curloc) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200286 talloc_free(tmp);
287 goto oom;
288 }
Daniel Willmanna5352a02011-08-05 14:08:58 +0200289 INIT_LLIST_HEAD(&curloc->list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200290
291
292 tstamp = strtok_r(tmp, ",", &saveptr);
293 valid = strtok_r(NULL, ",", &saveptr);
294 lat = strtok_r(NULL, ",", &saveptr);
295 lon = strtok_r(NULL, ",", &saveptr);
296 height = strtok_r(NULL, "\0", &saveptr);
297
Daniel Willmanna5352a02011-08-05 14:08:58 +0200298 curloc->tstamp = atol(tstamp);
Daniel Willmann7d109832012-05-14 18:43:23 +0200299 curloc->valid = get_string_value(bts_loc_fix_names, valid);
Daniel Willmanna5352a02011-08-05 14:08:58 +0200300 curloc->lat = atof(lat);
301 curloc->lon = atof(lon);
302 curloc->height = atof(height);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200303 talloc_free(tmp);
304
Daniel Willmanna5352a02011-08-05 14:08:58 +0200305 lastloc = llist_entry(bts->loc_list.next, struct bts_location, list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200306
307 /* Add location to the end of the list */
Daniel Willmanna5352a02011-08-05 14:08:58 +0200308 llist_add(&curloc->list, &bts->loc_list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200309
Daniel Willmanna5352a02011-08-05 14:08:58 +0200310 ret = get_bts_loc(cmd, data);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200311
Daniel Willmanna5352a02011-08-05 14:08:58 +0200312 if (!location_equal(curloc, lastloc))
Holger Hans Peter Freyther98258db2014-02-22 10:30:32 +0100313 bsc_gen_location_state_trap(bts);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200314
Daniel Willmanna5352a02011-08-05 14:08:58 +0200315 cleanup_locations(&bts->loc_list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200316
317 return ret;
318
319oom:
320 cmd->reply = "OOM";
321 return CTRL_CMD_ERROR;
322}
323
Daniel Willmanna5352a02011-08-05 14:08:58 +0200324static int verify_bts_loc(struct ctrl_cmd *cmd, const char *value, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200325{
326 char *saveptr, *latstr, *lonstr, *heightstr, *tstampstr, *validstr, *tmp;
327 time_t tstamp;
328 int valid;
Holger Hans Peter Freyther5ecbc932013-07-27 18:39:30 +0200329 double lat, lon, height __attribute__((unused));
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200330
331 tmp = talloc_strdup(cmd, value);
332 if (!tmp)
333 return 1;
334
335 tstampstr = strtok_r(tmp, ",", &saveptr);
336 validstr = strtok_r(NULL, ",", &saveptr);
337 latstr = strtok_r(NULL, ",", &saveptr);
338 lonstr = strtok_r(NULL, ",", &saveptr);
339 heightstr = strtok_r(NULL, "\0", &saveptr);
340
341 if ((tstampstr == NULL) || (validstr == NULL) || (latstr == NULL) ||
342 (lonstr == NULL) || (heightstr == NULL))
343 goto err;
344
345 tstamp = atol(tstampstr);
Daniel Willmann7d109832012-05-14 18:43:23 +0200346 valid = get_string_value(bts_loc_fix_names, validstr);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200347 lat = atof(latstr);
348 lon = atof(lonstr);
349 height = atof(heightstr);
350 talloc_free(tmp);
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100351 tmp = NULL;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200352
Daniel Willmanna5352a02011-08-05 14:08:58 +0200353 if (((tstamp == 0) && (valid != BTS_LOC_FIX_INVALID)) || (lat < -90) || (lat > 90) ||
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200354 (lon < -180) || (lon > 180) || (valid < 0)) {
355 goto err;
356 }
357
358 return 0;
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100359
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200360err:
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100361 talloc_free(tmp);
362 cmd->reply = talloc_strdup(cmd, "The format is <unixtime>,(invalid|fix2d|fix3d),<lat>,<lon>,<height>");
363 return 1;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200364}
365
Jacob Erlbeckcc391b82013-10-01 13:26:42 +0200366CTRL_CMD_DEFINE(bts_timezone, "timezone");
367static int get_bts_timezone(struct ctrl_cmd *cmd, void *data)
368{
369 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
370 if (!bts) {
371 cmd->reply = "bts not found.";
372 return CTRL_CMD_ERROR;
373 }
374
375 if (bts->tz.override)
376 cmd->reply = talloc_asprintf(cmd, "%d,%d,%d",
377 bts->tz.hr, bts->tz.mn, bts->tz.dst);
378 else
379 cmd->reply = talloc_asprintf(cmd, "off");
380
381 if (!cmd->reply) {
382 cmd->reply = "OOM";
383 return CTRL_CMD_ERROR;
384 }
385
386 return CTRL_CMD_REPLY;
387}
388
389static int set_bts_timezone(struct ctrl_cmd *cmd, void *data)
390{
391 char *saveptr, *hourstr, *minstr, *dststr, *tmp = 0;
392 int override;
393 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
394
395 if (!bts) {
396 cmd->reply = "bts not found.";
397 return CTRL_CMD_ERROR;
398 }
399
400 tmp = talloc_strdup(cmd, cmd->value);
401 if (!tmp)
402 goto oom;
403
404 hourstr = strtok_r(tmp, ",", &saveptr);
405 minstr = strtok_r(NULL, ",", &saveptr);
406 dststr = strtok_r(NULL, ",", &saveptr);
407
408 override = 0;
409
410 if (hourstr != NULL)
411 override = strcasecmp(hourstr, "off") != 0;
412
413 bts->tz.override = override;
414
415 if (override) {
416 bts->tz.hr = hourstr ? atol(hourstr) : 0;
417 bts->tz.mn = minstr ? atol(minstr) : 0;
418 bts->tz.dst = dststr ? atol(dststr) : 0;
419 }
420
421 talloc_free(tmp);
422 tmp = NULL;
423
424 return get_bts_timezone(cmd, data);
425
426oom:
427 cmd->reply = "OOM";
428 return CTRL_CMD_ERROR;
429}
430
431static int verify_bts_timezone(struct ctrl_cmd *cmd, const char *value, void *data)
432{
433 char *saveptr, *hourstr, *minstr, *dststr, *tmp;
434 int override, tz_hours, tz_mins, tz_dst;
435
436 tmp = talloc_strdup(cmd, value);
437 if (!tmp)
438 return 1;
439
440 hourstr = strtok_r(tmp, ",", &saveptr);
441 minstr = strtok_r(NULL, ",", &saveptr);
442 dststr = strtok_r(NULL, ",", &saveptr);
443
444 if (hourstr == NULL)
445 goto err;
446
447 override = strcasecmp(hourstr, "off") != 0;
448
449 if (!override) {
450 talloc_free(tmp);
451 return 0;
452 }
453
454 if (minstr == NULL || dststr == NULL)
455 goto err;
456
457 tz_hours = atol(hourstr);
458 tz_mins = atol(minstr);
459 tz_dst = atol(dststr);
460
461 talloc_free(tmp);
462 tmp = NULL;
463
464 if ((tz_hours < -19) || (tz_hours > 19) ||
465 (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) ||
466 (tz_dst < 0) || (tz_dst > 2))
467 goto err;
468
469 return 0;
470
471err:
472 talloc_free(tmp);
473 cmd->reply = talloc_strdup(cmd, "The format is <hours>,<mins>,<dst> or 'off' where -19 <= hours <= 19, mins in {0, 15, 30, 45}, and 0 <= dst <= 2");
474 return 1;
475}
476
Holger Hans Peter Freyther11590052014-05-14 09:50:27 +0200477CTRL_CMD_DEFINE_RO(bts_rf_state, "rf_state");
Daniel Willmann69665f82012-05-23 17:41:40 +0200478static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data)
479{
480 const char *oper, *admin, *policy;
481 struct gsm_bts *bts = cmd->node;
482
483 if (!bts) {
484 cmd->reply = "bts not found.";
485 return CTRL_CMD_ERROR;
486 }
487
488 oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
489 admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
490 policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
491
492 cmd->reply = talloc_asprintf(cmd, "%s,%s,%s", oper, admin, policy);
493 if (!cmd->reply) {
494 cmd->reply = "OOM.";
495 return CTRL_CMD_ERROR;
496 }
497
498 return CTRL_CMD_REPLY;
499}
500
Daniel Willmann69665f82012-05-23 17:41:40 +0200501
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200502CTRL_CMD_DEFINE(net_rf_lock, "rf_locked");
503static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data)
504{
505 cmd->reply = "get only works for the individual trx properties.";
506 return CTRL_CMD_ERROR;
507}
508
509static int set_net_rf_lock(struct ctrl_cmd *cmd, void *data)
510{
511 int locked = atoi(cmd->value);
512 struct gsm_network *net = cmd->node;
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200513 time_t now = time(NULL);
514 char now_buf[64];
515 struct osmo_bsc_rf *rf;
516
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200517 if (!net) {
518 cmd->reply = "net not found.";
519 return CTRL_CMD_ERROR;
520 }
521
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200522 rf = net->bsc_data->rf_ctrl;
523
524 if (!rf) {
Holger Hans Peter Freyther431cead2011-11-19 22:56:12 +0100525 cmd->reply = "RF Ctrl is not enabled in the BSC Configuration";
Holger Hans Peter Freyther7b6ea562011-08-16 14:29:53 +0200526 return CTRL_CMD_ERROR;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200527 }
528
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200529 talloc_free(rf->last_rf_lock_ctrl_command);
530 strftime(now_buf, sizeof(now_buf), TIME_FORMAT_RFC2822, gmtime(&now));
531 rf->last_rf_lock_ctrl_command =
532 talloc_asprintf(rf, "rf_locked %u (%s)", locked, now_buf);
533
534 osmo_bsc_rf_schedule_lock(rf, locked == 1 ? '0' : '1');
Holger Hans Peter Freyther7b6ea562011-08-16 14:29:53 +0200535
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200536 cmd->reply = talloc_asprintf(cmd, "%u", locked);
537 if (!cmd->reply) {
538 cmd->reply = "OOM.";
539 return CTRL_CMD_ERROR;
540 }
541
542 return CTRL_CMD_REPLY;
543}
544
545static int verify_net_rf_lock(struct ctrl_cmd *cmd, const char *value, void *data)
546{
547 int locked = atoi(cmd->value);
548
549 if ((locked != 0) && (locked != 1))
550 return 1;
551
552 return 0;
553}
554
Holger Hans Peter Freyther5308fff2014-05-31 08:42:29 +0200555CTRL_CMD_DEFINE(net_notification, "notification");
556static int get_net_notification(struct ctrl_cmd *cmd, void *data)
557{
558 cmd->reply = "There is nothing to read";
559 return CTRL_CMD_ERROR;
560}
561
562static int set_net_notification(struct ctrl_cmd *cmd, void *data)
563{
564 struct ctrl_cmd *trap;
565 struct gsm_network *net;
566
567 net = cmd->node;
568
569 trap = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
570 if (!trap) {
571 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed\n");
572 goto handled;
573 }
574
575 trap->id = "0";
576 trap->variable = "notification";
577 trap->reply = talloc_strdup(trap, cmd->value);
578
579 /*
580 * This should only be sent to local systems. In the future
581 * we might even ask for systems to register to receive
582 * the notifications.
583 */
584 ctrl_cmd_send_to_all(net->ctrl, trap);
585 talloc_free(trap);
586
587handled:
588 return CTRL_CMD_HANDLED;
589}
590
591static int verify_net_notification(struct ctrl_cmd *cmd, const char *value, void *data)
592{
593 return 0;
594}
595
Holger Hans Peter Freytherd29b8a42014-07-09 15:22:21 +0200596CTRL_CMD_DEFINE(net_inform_msc, "inform-msc-v1");
597static int get_net_inform_msc(struct ctrl_cmd *cmd, void *data)
598{
599 cmd->reply = "There is nothing to read";
600 return CTRL_CMD_ERROR;
601}
602
603static int set_net_inform_msc(struct ctrl_cmd *cmd, void *data)
604{
605 struct gsm_network *net;
606 struct osmo_msc_data *msc;
607
608 net = cmd->node;
609 llist_for_each_entry(msc, &net->bsc_data->mscs, entry) {
610 struct ctrl_cmd *trap;
611
612 trap = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
613 if (!trap) {
614 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed\n");
615 continue;
616 }
617
618 trap->id = "0";
619 trap->variable = "inform-msc-v1";
620 trap->reply = talloc_strdup(trap, cmd->value);
621 ctrl_cmd_send(&msc->msc_con->write_queue, trap);
622 talloc_free(trap);
623 }
624
625
626 return CTRL_CMD_HANDLED;
627}
628
629static int verify_net_inform_msc(struct ctrl_cmd *cmd, const char *value, void *data)
630{
631 return 0;
632}
633
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200634static int msc_signal_handler(unsigned int subsys, unsigned int signal,
635 void *handler_data, void *signal_data)
636{
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200637 struct msc_signal_data *msc;
638 struct gsm_network *net;
639 struct gsm_bts *bts;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200640
641 if (subsys != SS_MSC)
642 return 0;
643 if (signal != S_MSC_AUTHENTICATED)
644 return 0;
645
646 msc = signal_data;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200647
648 net = msc->data->network;
Holger Hans Peter Freyther25eca0b2011-08-22 23:29:00 +0200649 llist_for_each_entry(bts, &net->bts_list, list)
650 generate_location_state_trap(bts, msc->data->msc_con);
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200651
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200652 return 0;
653}
654
Daniel Willmann806d6542011-10-28 14:23:48 +0200655int bsc_ctrl_cmds_install(struct gsm_network *net)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200656{
Daniel Willmann5e95f452011-08-05 12:22:35 +0200657 int rc;
658
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100659 rc = bsc_base_ctrl_cmds_install();
660 if (rc)
661 goto end;
Daniel Willmann69665f82012-05-23 17:41:40 +0200662 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state);
663 if (rc)
664 goto end;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200665 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_loc);
Daniel Willmann5e95f452011-08-05 12:22:35 +0200666 if (rc)
667 goto end;
Jacob Erlbeckcc391b82013-10-01 13:26:42 +0200668 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_timezone);
669 if (rc)
670 goto end;
Daniel Willmann6088f142011-08-25 16:37:45 +0200671 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock);
Daniel Willmann806d6542011-10-28 14:23:48 +0200672 if (rc)
673 goto end;
674 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_msc_connection_status);
675 if (rc)
676 goto end;
677 rc = osmo_signal_register_handler(SS_MSC, &msc_connection_status_trap_cb, net);
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100678 if (rc)
679 goto end;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200680 rc = osmo_signal_register_handler(SS_MSC, msc_signal_handler, NULL);
681 if (rc)
682 goto end;
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100683 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_bts_connection_status);
684 if (rc)
685 goto end;
Holger Hans Peter Freyther5308fff2014-05-31 08:42:29 +0200686 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_notification);
687 if (rc)
688 goto end;
Holger Hans Peter Freytherd29b8a42014-07-09 15:22:21 +0200689 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_inform_msc);
690 if (rc)
691 goto end;
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100692 rc = osmo_signal_register_handler(SS_L_INPUT, &bts_connection_status_trap_cb, net);
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200693
Daniel Willmann5e95f452011-08-05 12:22:35 +0200694end:
695 return rc;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200696}