blob: e32218d0c3399e2adcfc92e87aead714bc58b9b1 [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
Daniel Willmann806d6542011-10-28 14:23:48 +020061CTRL_CMD_DEFINE(msc_connection_status, "msc_connection_status");
62static 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
73static int set_msc_connection_status(struct ctrl_cmd *cmd, void *data)
74{
75 return CTRL_CMD_ERROR;
76}
77
78static int verify_msc_connection_status(struct ctrl_cmd *cmd, const char *value, void *data)
79{
80 cmd->reply = "Read-only property";
81 return 1;
82}
83
84static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
85{
86 struct ctrl_cmd *cmd;
87 struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
88
89 if (signal == S_MSC_LOST && msc_connection_status == 1) {
90 LOGP(DCTRL, LOGL_DEBUG, "MSC connection lost, sending TRAP.\n");
91 msc_connection_status = 0;
92 } else if (signal == S_MSC_CONNECTED && msc_connection_status == 0) {
93 LOGP(DCTRL, LOGL_DEBUG, "MSC connection (re)established, sending TRAP.\n");
94 msc_connection_status = 1;
95 } else {
96 return 0;
97 }
98
99 cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
100 if (!cmd) {
101 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
102 return 0;
103 }
104
105 cmd->id = "0";
106 cmd->variable = "msc_connection_status";
107
108 get_msc_connection_status(cmd, NULL);
109
110 ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
111
112 talloc_free(cmd);
113
114 return 0;
115}
116
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100117CTRL_CMD_DEFINE(bts_connection_status, "bts_connection_status");
118static int bts_connection_status = 0;
119
120static int get_bts_connection_status(struct ctrl_cmd *cmd, void *data)
121{
122 if (bts_connection_status)
123 cmd->reply = "connected";
124 else
125 cmd->reply = "disconnected";
126 return CTRL_CMD_REPLY;
127}
128
129static int set_bts_connection_status(struct ctrl_cmd *cmd, void *data)
130{
131 return CTRL_CMD_ERROR;
132}
133
134static int verify_bts_connection_status(struct ctrl_cmd *cmd, const char *value, void *data)
135{
136 cmd->reply = "Read-only property";
137 return 1;
138}
139
140static int bts_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
141{
142 struct ctrl_cmd *cmd;
143 struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
144 struct gsm_bts *bts;
145 int bts_current_status;
146
147 if (signal != S_L_INP_TEI_DN && signal != S_L_INP_TEI_UP) {
148 return 0;
149 }
150
151 bts_current_status = 0;
152 /* Check if OML on at least one BTS is up */
153 llist_for_each_entry(bts, &gsmnet->bts_list, list) {
154 if (bts->oml_link) {
155 bts_current_status = 1;
156 break;
157 }
158 }
159 if (bts_connection_status == 0 && bts_current_status == 1) {
160 LOGP(DCTRL, LOGL_DEBUG, "BTS connection (re)established, sending TRAP.\n");
161 } else if (bts_connection_status == 1 && bts_current_status == 0) {
162 LOGP(DCTRL, LOGL_DEBUG, "No more BTS connected, sending TRAP.\n");
163 } else {
164 return 0;
165 }
166
167 cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
168 if (!cmd) {
169 LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
170 return 0;
171 }
172
173 bts_connection_status = bts_current_status;
174
175 cmd->id = "0";
176 cmd->variable = "bts_connection_status";
177
178 get_bts_connection_status(cmd, NULL);
179
180 ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
181
182 talloc_free(cmd);
183
184 return 0;
185}
Daniel Willmann806d6542011-10-28 14:23:48 +0200186
Daniel Willmann11620112011-08-19 19:32:09 +0200187static int get_bts_loc(struct ctrl_cmd *cmd, void *data);
188
189static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_connection *msc_con)
190{
191 struct ctrl_cmd *cmd;
Daniel Willmann65924a52011-08-19 19:38:31 +0200192 const char *oper, *admin, *policy;
Daniel Willmann11620112011-08-19 19:32:09 +0200193
194 cmd = ctrl_cmd_create(msc_con, CTRL_TYPE_TRAP);
195 if (!cmd) {
196 LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n");
197 return;
198 }
199
200 cmd->id = "0";
Daniel Willmann6088f142011-08-25 16:37:45 +0200201 cmd->variable = talloc_asprintf(cmd, "bts.%i.location-state", bts->nr);
Daniel Willmann11620112011-08-19 19:32:09 +0200202
203 /* Prepare the location reply */
204 cmd->node = bts;
205 get_bts_loc(cmd, NULL);
206
Daniel Willmann65924a52011-08-19 19:38:31 +0200207 oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
208 admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
209 policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
210
Holger Hans Peter Freytherecdf9122014-02-04 17:09:55 +0100211 cmd->reply = talloc_asprintf_append(cmd->reply,
212 ",%s,%s,%s,%d,%d",
213 oper, admin, policy,
214 bts->network->country_code,
215 bts->network->network_code);
Daniel Willmann65924a52011-08-19 19:38:31 +0200216
Daniel Willmann11620112011-08-19 19:32:09 +0200217 osmo_bsc_send_trap(cmd, msc_con);
218 talloc_free(cmd);
219}
220
Holger Hans Peter Freyther98258db2014-02-22 10:30:32 +0100221void bsc_gen_location_state_trap(struct gsm_bts *bts)
222{
223 struct osmo_msc_data *msc;
224
225 llist_for_each_entry(msc, &bts->network->bsc_data->mscs, entry)
226 generate_location_state_trap(bts, msc->msc_con);
227}
228
Daniel Willmanna5352a02011-08-05 14:08:58 +0200229static int location_equal(struct bts_location *a, struct bts_location *b)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200230{
231 return ((a->tstamp == b->tstamp) && (a->valid == b->valid) && (a->lat == b->lat) &&
232 (a->lon == b->lon) && (a->height == b->height));
233}
234
Daniel Willmanna5352a02011-08-05 14:08:58 +0200235static void cleanup_locations(struct llist_head *locations)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200236{
Daniel Willmanna5352a02011-08-05 14:08:58 +0200237 struct bts_location *myloc, *tmp;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200238 int invalpos = 0, i = 0;
239
240 LOGP(DCTRL, LOGL_DEBUG, "Checking position list.\n");
Daniel Willmanna5352a02011-08-05 14:08:58 +0200241 llist_for_each_entry_safe(myloc, tmp, locations, list) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200242 i++;
243 if (i > 3) {
244 LOGP(DCTRL, LOGL_DEBUG, "Deleting old position.\n");
245 llist_del(&myloc->list);
246 talloc_free(myloc);
Daniel Willmanna5352a02011-08-05 14:08:58 +0200247 } else if (myloc->valid == BTS_LOC_FIX_INVALID) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200248 /* Only capture the newest of subsequent invalid positions */
249 invalpos++;
250 if (invalpos > 1) {
251 LOGP(DCTRL, LOGL_DEBUG, "Deleting subsequent invalid position.\n");
252 invalpos--;
253 i--;
254 llist_del(&myloc->list);
255 talloc_free(myloc);
256 }
257 } else {
258 invalpos = 0;
259 }
260 }
261 LOGP(DCTRL, LOGL_DEBUG, "Found %i positions.\n", i);
262}
263
Daniel Willmanna5352a02011-08-05 14:08:58 +0200264CTRL_CMD_DEFINE(bts_loc, "location");
265static int get_bts_loc(struct ctrl_cmd *cmd, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200266{
Daniel Willmanna5352a02011-08-05 14:08:58 +0200267 struct bts_location *curloc;
268 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
269 if (!bts) {
270 cmd->reply = "bts not found.";
271 return CTRL_CMD_ERROR;
272 }
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200273
Daniel Willmanna5352a02011-08-05 14:08:58 +0200274 if (llist_empty(&bts->loc_list)) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200275 cmd->reply = talloc_asprintf(cmd, "0,invalid,0,0,0");
276 return CTRL_CMD_REPLY;
277 } else {
Daniel Willmanna5352a02011-08-05 14:08:58 +0200278 curloc = llist_entry(bts->loc_list.next, struct bts_location, list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200279 }
280
Daniel Willmanna5352a02011-08-05 14:08:58 +0200281 cmd->reply = talloc_asprintf(cmd, "%lu,%s,%f,%f,%f", curloc->tstamp,
Daniel Willmann7d109832012-05-14 18:43:23 +0200282 get_value_string(bts_loc_fix_names, curloc->valid), curloc->lat, curloc->lon, curloc->height);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200283 if (!cmd->reply) {
284 cmd->reply = "OOM";
285 return CTRL_CMD_ERROR;
286 }
287
288 return CTRL_CMD_REPLY;
289}
290
Daniel Willmanna5352a02011-08-05 14:08:58 +0200291static int set_bts_loc(struct ctrl_cmd *cmd, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200292{
293 char *saveptr, *lat, *lon, *height, *tstamp, *valid, *tmp;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200294 struct bts_location *curloc, *lastloc;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200295 int ret;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200296 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
297 if (!bts) {
298 cmd->reply = "bts not found.";
299 return CTRL_CMD_ERROR;
300 }
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200301
302 tmp = talloc_strdup(cmd, cmd->value);
303 if (!tmp)
304 goto oom;
305
Daniel Willmanna5352a02011-08-05 14:08:58 +0200306 curloc = talloc_zero(tall_bsc_ctx, struct bts_location);
307 if (!curloc) {
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200308 talloc_free(tmp);
309 goto oom;
310 }
Daniel Willmanna5352a02011-08-05 14:08:58 +0200311 INIT_LLIST_HEAD(&curloc->list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200312
313
314 tstamp = strtok_r(tmp, ",", &saveptr);
315 valid = strtok_r(NULL, ",", &saveptr);
316 lat = strtok_r(NULL, ",", &saveptr);
317 lon = strtok_r(NULL, ",", &saveptr);
318 height = strtok_r(NULL, "\0", &saveptr);
319
Daniel Willmanna5352a02011-08-05 14:08:58 +0200320 curloc->tstamp = atol(tstamp);
Daniel Willmann7d109832012-05-14 18:43:23 +0200321 curloc->valid = get_string_value(bts_loc_fix_names, valid);
Daniel Willmanna5352a02011-08-05 14:08:58 +0200322 curloc->lat = atof(lat);
323 curloc->lon = atof(lon);
324 curloc->height = atof(height);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200325 talloc_free(tmp);
326
Daniel Willmanna5352a02011-08-05 14:08:58 +0200327 lastloc = llist_entry(bts->loc_list.next, struct bts_location, list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200328
329 /* Add location to the end of the list */
Daniel Willmanna5352a02011-08-05 14:08:58 +0200330 llist_add(&curloc->list, &bts->loc_list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200331
Daniel Willmanna5352a02011-08-05 14:08:58 +0200332 ret = get_bts_loc(cmd, data);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200333
Daniel Willmanna5352a02011-08-05 14:08:58 +0200334 if (!location_equal(curloc, lastloc))
Holger Hans Peter Freyther98258db2014-02-22 10:30:32 +0100335 bsc_gen_location_state_trap(bts);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200336
Daniel Willmanna5352a02011-08-05 14:08:58 +0200337 cleanup_locations(&bts->loc_list);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200338
339 return ret;
340
341oom:
342 cmd->reply = "OOM";
343 return CTRL_CMD_ERROR;
344}
345
Daniel Willmanna5352a02011-08-05 14:08:58 +0200346static int verify_bts_loc(struct ctrl_cmd *cmd, const char *value, void *data)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200347{
348 char *saveptr, *latstr, *lonstr, *heightstr, *tstampstr, *validstr, *tmp;
349 time_t tstamp;
350 int valid;
Holger Hans Peter Freyther5ecbc932013-07-27 18:39:30 +0200351 double lat, lon, height __attribute__((unused));
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200352
353 tmp = talloc_strdup(cmd, value);
354 if (!tmp)
355 return 1;
356
357 tstampstr = strtok_r(tmp, ",", &saveptr);
358 validstr = strtok_r(NULL, ",", &saveptr);
359 latstr = strtok_r(NULL, ",", &saveptr);
360 lonstr = strtok_r(NULL, ",", &saveptr);
361 heightstr = strtok_r(NULL, "\0", &saveptr);
362
363 if ((tstampstr == NULL) || (validstr == NULL) || (latstr == NULL) ||
364 (lonstr == NULL) || (heightstr == NULL))
365 goto err;
366
367 tstamp = atol(tstampstr);
Daniel Willmann7d109832012-05-14 18:43:23 +0200368 valid = get_string_value(bts_loc_fix_names, validstr);
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200369 lat = atof(latstr);
370 lon = atof(lonstr);
371 height = atof(heightstr);
372 talloc_free(tmp);
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100373 tmp = NULL;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200374
Daniel Willmanna5352a02011-08-05 14:08:58 +0200375 if (((tstamp == 0) && (valid != BTS_LOC_FIX_INVALID)) || (lat < -90) || (lat > 90) ||
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200376 (lon < -180) || (lon > 180) || (valid < 0)) {
377 goto err;
378 }
379
380 return 0;
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100381
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200382err:
Holger Hans Peter Freyther8ae35c12013-03-28 16:48:41 +0100383 talloc_free(tmp);
384 cmd->reply = talloc_strdup(cmd, "The format is <unixtime>,(invalid|fix2d|fix3d),<lat>,<lon>,<height>");
385 return 1;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200386}
387
Jacob Erlbeckcc391b82013-10-01 13:26:42 +0200388CTRL_CMD_DEFINE(bts_timezone, "timezone");
389static int get_bts_timezone(struct ctrl_cmd *cmd, void *data)
390{
391 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
392 if (!bts) {
393 cmd->reply = "bts not found.";
394 return CTRL_CMD_ERROR;
395 }
396
397 if (bts->tz.override)
398 cmd->reply = talloc_asprintf(cmd, "%d,%d,%d",
399 bts->tz.hr, bts->tz.mn, bts->tz.dst);
400 else
401 cmd->reply = talloc_asprintf(cmd, "off");
402
403 if (!cmd->reply) {
404 cmd->reply = "OOM";
405 return CTRL_CMD_ERROR;
406 }
407
408 return CTRL_CMD_REPLY;
409}
410
411static int set_bts_timezone(struct ctrl_cmd *cmd, void *data)
412{
413 char *saveptr, *hourstr, *minstr, *dststr, *tmp = 0;
414 int override;
415 struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
416
417 if (!bts) {
418 cmd->reply = "bts not found.";
419 return CTRL_CMD_ERROR;
420 }
421
422 tmp = talloc_strdup(cmd, cmd->value);
423 if (!tmp)
424 goto oom;
425
426 hourstr = strtok_r(tmp, ",", &saveptr);
427 minstr = strtok_r(NULL, ",", &saveptr);
428 dststr = strtok_r(NULL, ",", &saveptr);
429
430 override = 0;
431
432 if (hourstr != NULL)
433 override = strcasecmp(hourstr, "off") != 0;
434
435 bts->tz.override = override;
436
437 if (override) {
438 bts->tz.hr = hourstr ? atol(hourstr) : 0;
439 bts->tz.mn = minstr ? atol(minstr) : 0;
440 bts->tz.dst = dststr ? atol(dststr) : 0;
441 }
442
443 talloc_free(tmp);
444 tmp = NULL;
445
446 return get_bts_timezone(cmd, data);
447
448oom:
449 cmd->reply = "OOM";
450 return CTRL_CMD_ERROR;
451}
452
453static int verify_bts_timezone(struct ctrl_cmd *cmd, const char *value, void *data)
454{
455 char *saveptr, *hourstr, *minstr, *dststr, *tmp;
456 int override, tz_hours, tz_mins, tz_dst;
457
458 tmp = talloc_strdup(cmd, value);
459 if (!tmp)
460 return 1;
461
462 hourstr = strtok_r(tmp, ",", &saveptr);
463 minstr = strtok_r(NULL, ",", &saveptr);
464 dststr = strtok_r(NULL, ",", &saveptr);
465
466 if (hourstr == NULL)
467 goto err;
468
469 override = strcasecmp(hourstr, "off") != 0;
470
471 if (!override) {
472 talloc_free(tmp);
473 return 0;
474 }
475
476 if (minstr == NULL || dststr == NULL)
477 goto err;
478
479 tz_hours = atol(hourstr);
480 tz_mins = atol(minstr);
481 tz_dst = atol(dststr);
482
483 talloc_free(tmp);
484 tmp = NULL;
485
486 if ((tz_hours < -19) || (tz_hours > 19) ||
487 (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) ||
488 (tz_dst < 0) || (tz_dst > 2))
489 goto err;
490
491 return 0;
492
493err:
494 talloc_free(tmp);
495 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");
496 return 1;
497}
498
Daniel Willmann69665f82012-05-23 17:41:40 +0200499CTRL_CMD_DEFINE(bts_rf_state, "rf_state");
500static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data)
501{
502 const char *oper, *admin, *policy;
503 struct gsm_bts *bts = cmd->node;
504
505 if (!bts) {
506 cmd->reply = "bts not found.";
507 return CTRL_CMD_ERROR;
508 }
509
510 oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
511 admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
512 policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
513
514 cmd->reply = talloc_asprintf(cmd, "%s,%s,%s", oper, admin, policy);
515 if (!cmd->reply) {
516 cmd->reply = "OOM.";
517 return CTRL_CMD_ERROR;
518 }
519
520 return CTRL_CMD_REPLY;
521}
522
523static int set_bts_rf_state(struct ctrl_cmd *cmd, void *data)
524{
525 cmd->reply = "set is unimplemented";
526 return CTRL_CMD_ERROR;
527}
528
529static int verify_bts_rf_state(struct ctrl_cmd *cmd, const char *value, void *data)
530{
531 return 0;
532}
533
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200534CTRL_CMD_DEFINE(net_rf_lock, "rf_locked");
535static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data)
536{
537 cmd->reply = "get only works for the individual trx properties.";
538 return CTRL_CMD_ERROR;
539}
540
541static int set_net_rf_lock(struct ctrl_cmd *cmd, void *data)
542{
543 int locked = atoi(cmd->value);
544 struct gsm_network *net = cmd->node;
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200545 time_t now = time(NULL);
546 char now_buf[64];
547 struct osmo_bsc_rf *rf;
548
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200549 if (!net) {
550 cmd->reply = "net not found.";
551 return CTRL_CMD_ERROR;
552 }
553
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200554 rf = net->bsc_data->rf_ctrl;
555
556 if (!rf) {
Holger Hans Peter Freyther431cead2011-11-19 22:56:12 +0100557 cmd->reply = "RF Ctrl is not enabled in the BSC Configuration";
Holger Hans Peter Freyther7b6ea562011-08-16 14:29:53 +0200558 return CTRL_CMD_ERROR;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200559 }
560
Jacob Erlbeck779a7282013-09-11 10:46:57 +0200561 talloc_free(rf->last_rf_lock_ctrl_command);
562 strftime(now_buf, sizeof(now_buf), TIME_FORMAT_RFC2822, gmtime(&now));
563 rf->last_rf_lock_ctrl_command =
564 talloc_asprintf(rf, "rf_locked %u (%s)", locked, now_buf);
565
566 osmo_bsc_rf_schedule_lock(rf, locked == 1 ? '0' : '1');
Holger Hans Peter Freyther7b6ea562011-08-16 14:29:53 +0200567
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200568 cmd->reply = talloc_asprintf(cmd, "%u", locked);
569 if (!cmd->reply) {
570 cmd->reply = "OOM.";
571 return CTRL_CMD_ERROR;
572 }
573
574 return CTRL_CMD_REPLY;
575}
576
577static int verify_net_rf_lock(struct ctrl_cmd *cmd, const char *value, void *data)
578{
579 int locked = atoi(cmd->value);
580
581 if ((locked != 0) && (locked != 1))
582 return 1;
583
584 return 0;
585}
586
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200587static int msc_signal_handler(unsigned int subsys, unsigned int signal,
588 void *handler_data, void *signal_data)
589{
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200590 struct msc_signal_data *msc;
591 struct gsm_network *net;
592 struct gsm_bts *bts;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200593
594 if (subsys != SS_MSC)
595 return 0;
596 if (signal != S_MSC_AUTHENTICATED)
597 return 0;
598
599 msc = signal_data;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200600
601 net = msc->data->network;
Holger Hans Peter Freyther25eca0b2011-08-22 23:29:00 +0200602 llist_for_each_entry(bts, &net->bts_list, list)
603 generate_location_state_trap(bts, msc->data->msc_con);
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200604
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200605 return 0;
606}
607
Daniel Willmann806d6542011-10-28 14:23:48 +0200608int bsc_ctrl_cmds_install(struct gsm_network *net)
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200609{
Daniel Willmann5e95f452011-08-05 12:22:35 +0200610 int rc;
611
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100612 rc = bsc_base_ctrl_cmds_install();
613 if (rc)
614 goto end;
Daniel Willmann69665f82012-05-23 17:41:40 +0200615 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state);
616 if (rc)
617 goto end;
Daniel Willmanna5352a02011-08-05 14:08:58 +0200618 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_loc);
Daniel Willmann5e95f452011-08-05 12:22:35 +0200619 if (rc)
620 goto end;
Jacob Erlbeckcc391b82013-10-01 13:26:42 +0200621 rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_timezone);
622 if (rc)
623 goto end;
Daniel Willmann6088f142011-08-25 16:37:45 +0200624 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock);
Daniel Willmann806d6542011-10-28 14:23:48 +0200625 if (rc)
626 goto end;
627 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_msc_connection_status);
628 if (rc)
629 goto end;
630 rc = osmo_signal_register_handler(SS_MSC, &msc_connection_status_trap_cb, net);
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100631 if (rc)
632 goto end;
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200633 rc = osmo_signal_register_handler(SS_MSC, msc_signal_handler, NULL);
634 if (rc)
635 goto end;
Daniel Willmann7a7c2f82011-11-03 16:23:08 +0100636 rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_bts_connection_status);
637 if (rc)
638 goto end;
639 rc = osmo_signal_register_handler(SS_L_INPUT, &bts_connection_status_trap_cb, net);
Holger Hans Peter Freyther23446842011-08-16 20:10:40 +0200640
Daniel Willmann5e95f452011-08-05 12:22:35 +0200641end:
642 return rc;
Daniel Willmann5ff06af2011-08-05 12:20:58 +0200643}