blob: 1451ffb829dc8109ee8fc4c9802bf9ec82de7518 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file control_cmd.h */
2
Harald Welte5ddd4352014-08-21 15:42:44 +02003#pragma once
Daniel Willmann1264cb42010-10-21 15:00:36 +02004
5#include <osmocom/core/msgb.h>
Holger Hans Peter Freyther43a11db2013-01-09 16:54:49 +01006#include <osmocom/core/talloc.h>
Daniel Willmann1264cb42010-10-21 15:00:36 +02007#include <osmocom/core/write_queue.h>
Harald Welte1238cc62014-08-20 19:50:04 +02008#include <osmocom/core/logging.h>
Max70c7d412017-02-24 13:59:14 +01009#include <osmocom/core/utils.h>
Daniel Willmann1264cb42010-10-21 15:00:36 +020010#include <osmocom/vty/vector.h>
11
12#define CTRL_CMD_ERROR -1
13#define CTRL_CMD_HANDLED 0
14#define CTRL_CMD_REPLY 1
Max30b2e342018-11-26 10:38:55 +010015#define CTRL_CMD_TRAP_ID "0"
Daniel Willmann1264cb42010-10-21 15:00:36 +020016
Daniel Willmann35a1b3b2011-05-06 16:38:11 +020017struct ctrl_handle;
18
Harald Welteb4186822018-05-26 17:25:11 +020019/*! The class of node at which a ctrl command is registered to */
Daniel Willmann1264cb42010-10-21 15:00:36 +020020enum ctrl_node_type {
21 CTRL_NODE_ROOT, /* Root elements */
Daniel Willmann1264cb42010-10-21 15:00:36 +020022 CTRL_NODE_BTS, /* BTS specific (net.btsN.) */
23 CTRL_NODE_TRX, /* TRX specific (net.btsN.trxM.) */
24 CTRL_NODE_TS, /* TS specific (net.btsN.trxM.tsI.) */
Harald Welte31c0fef2017-04-16 17:26:30 +020025 CTRL_NODE_FSM, /* Finite State Machine (description) */
26 CTRL_NODE_FSM_INST, /* Finite State Machine (instance) */
Daniel Willmann1264cb42010-10-21 15:00:36 +020027 _LAST_CTRL_NODE
28};
29
Harald Welteb4186822018-05-26 17:25:11 +020030/*! Ctrl command types (GET, SET, ...) */
Daniel Willmann1264cb42010-10-21 15:00:36 +020031enum ctrl_type {
Neels Hofmeyr7c1ec8c2017-03-02 14:32:52 +010032 CTRL_TYPE_UNKNOWN,
Daniel Willmann1264cb42010-10-21 15:00:36 +020033 CTRL_TYPE_GET,
34 CTRL_TYPE_SET,
35 CTRL_TYPE_GET_REPLY,
36 CTRL_TYPE_SET_REPLY,
37 CTRL_TYPE_TRAP,
38 CTRL_TYPE_ERROR
39};
40
Harald Welteb4186822018-05-26 17:25:11 +020041/*! human-readable string names for \ref ctrl_type */
Max70c7d412017-02-24 13:59:14 +010042extern const struct value_string ctrl_type_vals[];
43
Harald Welteb4186822018-05-26 17:25:11 +020044/*! Represents a single ctrl connection */
Daniel Willmann1264cb42010-10-21 15:00:36 +020045struct ctrl_connection {
46 struct llist_head list_entry;
47
Harald Welteb4186822018-05-26 17:25:11 +020048 /*! The queue for sending data back */
Daniel Willmann1264cb42010-10-21 15:00:36 +020049 struct osmo_wqueue write_queue;
50
Harald Welteb4186822018-05-26 17:25:11 +020051 /*! Buffer for partial input data */
Jacob Erlbeck141de622014-03-31 13:42:11 +020052 struct msgb *pending_msg;
53
Harald Welteb4186822018-05-26 17:25:11 +020054 /*! Callback if the connection was closed */
Daniel Willmann1264cb42010-10-21 15:00:36 +020055 void (*closed_cb)(struct ctrl_connection *conn);
56
Harald Welteb4186822018-05-26 17:25:11 +020057 /*! Pending commands for this connection */
Daniel Willmann1264cb42010-10-21 15:00:36 +020058 struct llist_head cmds;
Harald Welte39c9e7b2014-08-22 00:28:51 +020059
Harald Welteb4186822018-05-26 17:25:11 +020060 /*! Pending deferred command responses for this connection */
Harald Welte39c9e7b2014-08-22 00:28:51 +020061 struct llist_head def_cmds;
Daniel Willmann1264cb42010-10-21 15:00:36 +020062};
63
Neels Hofmeyrcdbc9af2018-04-03 16:51:49 +020064struct ctrl_cmd_def;
65
Harald Welteb4186822018-05-26 17:25:11 +020066/*! Represents a single ctrl command after parsing */
Daniel Willmann1264cb42010-10-21 15:00:36 +020067struct ctrl_cmd {
Harald Welteb4186822018-05-26 17:25:11 +020068 /*! connection through which the command was received */
Daniel Willmann1264cb42010-10-21 15:00:36 +020069 struct ctrl_connection *ccon;
Harald Welteb4186822018-05-26 17:25:11 +020070 /*! command type */
Daniel Willmann1264cb42010-10-21 15:00:36 +020071 enum ctrl_type type;
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020072 char *id;
Harald Welteb4186822018-05-26 17:25:11 +020073 /*! node of the specified variable */
Daniel Willmann1264cb42010-10-21 15:00:36 +020074 void *node;
Harald Welteb4186822018-05-26 17:25:11 +020075 /*! name of the variable */
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020076 char *variable;
Harald Welteb4186822018-05-26 17:25:11 +020077 /*! value of the specified CTRL variable */
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020078 char *value;
Harald Welteb4186822018-05-26 17:25:11 +020079 /*! respnse message string */
Daniel Willmann1264cb42010-10-21 15:00:36 +020080 char *reply;
Harald Welteb4186822018-05-26 17:25:11 +020081 /*! state representing deferred (async) response, if any */
Neels Hofmeyrcdbc9af2018-04-03 16:51:49 +020082 struct ctrl_cmd_def *defer;
Daniel Willmann1264cb42010-10-21 15:00:36 +020083};
84
Neels Hofmeyrabdd7a22017-10-19 02:40:01 +020085#define ctrl_cmd_reply_printf(cmd, fmt, args ...) \
86 osmo_talloc_asprintf(cmd, cmd->reply, fmt, ## args)
87
Daniel Willmann1264cb42010-10-21 15:00:36 +020088struct ctrl_cmd_struct {
89 int nr_commands;
90 char **command;
91};
92
Harald Welteb4186822018-05-26 17:25:11 +020093/*! Implementation of a given CTRL command. This is what a program registers
94 * using \r ctrl_cmd_install in order to implement a given control variable. */
Daniel Willmann1264cb42010-10-21 15:00:36 +020095struct ctrl_cmd_element {
Harald Welteb4186822018-05-26 17:25:11 +020096 /*! textual name/id of the CTRL command */
Daniel Willmann1264cb42010-10-21 15:00:36 +020097 const char *name;
Daniel Willmann1264cb42010-10-21 15:00:36 +020098 struct ctrl_cmd_struct strcmd;
Harald Welteb4186822018-05-26 17:25:11 +020099 /*! call-back function implementing the SET operation */
Daniel Willmann1264cb42010-10-21 15:00:36 +0200100 int (*set)(struct ctrl_cmd *cmd, void *data);
Harald Welteb4186822018-05-26 17:25:11 +0200101 /*! call-back function implementing the GET operation */
Daniel Willmann1264cb42010-10-21 15:00:36 +0200102 int (*get)(struct ctrl_cmd *cmd, void *data);
Harald Welteb4186822018-05-26 17:25:11 +0200103 /*! call-back function to validate a value; called before SET */
Daniel Willmann1264cb42010-10-21 15:00:36 +0200104 int (*verify)(struct ctrl_cmd *cmd, const char *value, void *data);
105};
106
107struct ctrl_cmd_map {
108 char *cmd;
109 enum ctrl_type type;
110};
111
Harald Welte39c9e7b2014-08-22 00:28:51 +0200112/* deferred control command, i.e. responded asynchronously */
113struct ctrl_cmd_def {
114 struct llist_head list; /* ctrl_connection.def_cmds */
115 struct ctrl_cmd *cmd;
116 void *data; /* opaque user data */
117};
118
119struct ctrl_cmd_def *
120ctrl_cmd_def_make(const void *ctx, struct ctrl_cmd *cmd, void *data, unsigned int secs);
121int ctrl_cmd_def_is_zombie(struct ctrl_cmd_def *cd);
122int ctrl_cmd_def_send(struct ctrl_cmd_def *cd);
123
Daniel Willmann1264cb42010-10-21 15:00:36 +0200124int ctrl_cmd_exec(vector vline, struct ctrl_cmd *command, vector node, void *data);
125int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200126int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd);
Daniel Willmann35a1b3b2011-05-06 16:38:11 +0200127int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd);
Pau Espin Pedrol239ed3b2018-07-12 17:51:16 +0200128struct ctrl_cmd *ctrl_cmd_parse3(void *ctx, struct msgb *msg, bool *parse_failed);
Neels Hofmeyrf2e83ad2017-12-16 01:05:25 +0100129struct ctrl_cmd *ctrl_cmd_parse2(void *ctx, struct msgb *msg);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200130struct ctrl_cmd *ctrl_cmd_parse(void *ctx, struct msgb *msg);
131struct msgb *ctrl_cmd_make(struct ctrl_cmd *cmd);
Daniel Willmann8b7a9622011-03-17 15:37:54 +0100132struct ctrl_cmd *ctrl_cmd_cpy(void *ctx, struct ctrl_cmd *cmd);
Holger Hans Peter Freythera6b34012011-08-22 23:44:32 +0200133struct ctrl_cmd *ctrl_cmd_create(void *ctx, enum ctrl_type);
Daniel Willmannf2e75d42011-07-22 18:08:31 +0200134struct ctrl_cmd *ctrl_cmd_trap(struct ctrl_cmd *cmd);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200135
Harald Welteb4186822018-05-26 17:25:11 +0200136/*! Helper to generate static struct ctrl_cmd_element
137 * \param[in] cmdname symbol name of the command related functions/structures
138 * \param[in] cmdstr string name exposed on CTRL
139 * \param[in] verify_name full symbol name of verification function */
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200140#define CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_name) \
141static struct ctrl_cmd_element cmd_##cmdname = { \
142 .name = cmdstr, \
143 .get = &get_##cmdname, \
144 .set = &set_##cmdname, \
145 .verify = verify_name, \
146}
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100147
Harald Welteb4186822018-05-26 17:25:11 +0200148/*! Helper to generate static GET function for integer
149 * \param[in] cmdname symbol name of the command related function
150 * \param[in] dtype name of outer struct of user data
151 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100152#define CTRL_HELPER_GET_INT(cmdname, dtype, element) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100153static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200154{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100155 dtype *node = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200156 cmd->reply = talloc_asprintf(cmd, "%i", node->element); \
157 if (!cmd->reply) { \
158 cmd->reply = "OOM"; \
159 return CTRL_CMD_ERROR; \
160 } \
161 return CTRL_CMD_REPLY; \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100162}
Harald Welteb4186822018-05-26 17:25:11 +0200163
164/*! Helper to generate static SET function for integer
165 * \param[in] cmdname symbol name of the command related function
166 * \param[in] dtype name of outer struct of user data
167 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100168#define CTRL_HELPER_SET_INT(cmdname, dtype, element) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100169static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200170{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100171 dtype *node = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200172 int tmp = atoi(cmd->value); \
173 node->element = tmp; \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100174 return get_##cmdname(cmd, _data); \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100175}
Harald Welteb4186822018-05-26 17:25:11 +0200176
177/*! Helper to generate static VERIFY unction validating a numeric range
178 * \param[in] cmdname symbol name of the command related function
179 * \param[in] min minimum permitted integer value
180 * \param[in] max maximum permitted integer value */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100181#define CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100182static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200183{ \
184 int tmp = atoi(value); \
185 if ((tmp >= min)&&(tmp <= max)) { \
186 return 0; \
187 } \
Holger Hans Peter Freythere9f7be12013-02-22 10:53:29 +0100188 cmd->reply = "Input not within the range"; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200189 return -1; \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100190}
191
Harald Welteb4186822018-05-26 17:25:11 +0200192/*! Helper to generate GET, SET, VERIFY + ctrl_cmd_element for integer
193 * \param[in] cmdname symbol name of the command related function
194 * \param[in] cmdstr string name exposed on CTRL
195 * \param[in] dtype name of outer struct of user data
196 * \param[in] element name of field within \a dtype
197 * \param[in] min minimum permitted integer value
198 * \param[in] max maximum permitted integer value */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100199#define CTRL_CMD_DEFINE_RANGE(cmdname, cmdstr, dtype, element, min, max) \
200 CTRL_HELPER_GET_INT(cmdname, dtype, element) \
201 CTRL_HELPER_SET_INT(cmdname, dtype, element) \
202 CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \
Holger Hans Peter Freyther0e7b67c2014-05-15 17:27:12 +0200203CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200204
Harald Welteb4186822018-05-26 17:25:11 +0200205/*! Helper to generate static GET function for string
206 * \param[in] cmdname symbol name of the command related function
207 * \param[in] dtype name of outer struct of user data
208 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100209#define CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther43a11db2013-01-09 16:54:49 +0100210static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200211{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100212 dtype *data = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200213 cmd->reply = talloc_asprintf(cmd, "%s", data->element); \
214 if (!cmd->reply) { \
215 cmd->reply = "OOM"; \
216 return CTRL_CMD_ERROR; \
217 } \
218 return CTRL_CMD_REPLY; \
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100219}
Harald Welteb4186822018-05-26 17:25:11 +0200220
221/*! Helper to generate static SET function for string
222 * \param[in] cmdname symbol name of the command related function
223 * \param[in] dtype name of outer struct of user data
224 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100225#define CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther43a11db2013-01-09 16:54:49 +0100226static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200227{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100228 dtype *data = cmd->node; \
Harald Weltef3c7e852014-08-20 22:50:47 +0200229 osmo_talloc_replace_string(cmd->node, &data->element, cmd->value); \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100230 return get_##cmdname(cmd, _data); \
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100231}
Harald Welteb4186822018-05-26 17:25:11 +0200232
233/*! Helper to generate GET, SET, VERIFY + ctrl_cmd_element for string
234 * \param[in] cmdname symbol name of the command related function
235 * \param[in] cmdstr string name exposed on CTRL
236 * \param[in] dtype name of outer struct of user data
Vadim Yanitskiy2a0b1212023-02-28 03:29:35 +0700237 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100238#define CTRL_CMD_DEFINE_STRING(cmdname, cmdstr, dtype, element) \
239 CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
240 CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200241CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, NULL)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200242
Harald Welteb4186822018-05-26 17:25:11 +0200243/*! Declare a read-write attribute. Declares get, set, verify.
244 * \param[in] cmdname symbol name of the command related functions/structures
245 * \param[in] cmdstr string name exposed on CTRL */
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200246#define CTRL_CMD_DEFINE(cmdname, cmdstr) \
Daniel Willmannf7c74e52011-08-05 11:48:18 +0200247static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \
248static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
249static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data); \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200250CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200251
Harald Welteb4186822018-05-26 17:25:11 +0200252/*! Define a read-only attribute. Declares get, implements set+verify
253 * \param[in] cmdname symbol name of the command related functions/structures
254 * \param[in] cmdstr string name exposed on CTRL */
Holger Hans Peter Freytherc08c5512014-05-14 09:50:27 +0200255#define CTRL_CMD_DEFINE_RO(cmdname, cmdstr) \
256static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \
257static int set_##cmdname(struct ctrl_cmd *cmd, void *data) \
258{ \
259 cmd->reply = "Read Only attribute"; \
260 return CTRL_CMD_ERROR; \
261} \
262static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data) \
263{ \
264 cmd->reply = "Read Only attribute"; \
265 return 1; \
266} \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200267CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Holger Hans Peter Freytherc08c5512014-05-14 09:50:27 +0200268
Harald Welteb4186822018-05-26 17:25:11 +0200269/*! Define a write-only attribute. Declares set+verify, implements read call-back
270 * \param[in] cmdname symbol name of the command related functions/structures
271 * \param[in] cmdstr string name exposed on CTRL */
Max89287472017-01-11 17:47:04 +0100272#define CTRL_CMD_DEFINE_WO(cmdname, cmdstr) \
273static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
274static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
275{ \
276 cmd->reply = "Write Only attribute"; \
277 return CTRL_CMD_ERROR; \
278} \
279static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data); \
280CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
281
Harald Welteb4186822018-05-26 17:25:11 +0200282/*! Define a write-only attribute without verify. Declares set, implements read+verify
283 * \param[in] cmdname symbol name of the command related functions/structures
284 * \param[in] cmdstr string name exposed on CTRL */
Max89287472017-01-11 17:47:04 +0100285#define CTRL_CMD_DEFINE_WO_NOVRF(cmdname, cmdstr) \
286static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
287static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
288{ \
289 cmd->reply = "Write Only attribute"; \
290 return CTRL_CMD_ERROR; \
291} \
292static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data) \
293{ \
294 return 0; \
295} \
296CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
297
Harald Welte18b70b52011-07-13 14:14:03 +0200298struct gsm_network;