blob: 93055c7ce434442f0b343b4c3fad2a18da668869 [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
15
Daniel Willmann35a1b3b2011-05-06 16:38:11 +020016struct ctrl_handle;
17
Harald Welteb4186822018-05-26 17:25:11 +020018/*! The class of node at which a ctrl command is registered to */
Daniel Willmann1264cb42010-10-21 15:00:36 +020019enum ctrl_node_type {
20 CTRL_NODE_ROOT, /* Root elements */
Daniel Willmann1264cb42010-10-21 15:00:36 +020021 CTRL_NODE_BTS, /* BTS specific (net.btsN.) */
22 CTRL_NODE_TRX, /* TRX specific (net.btsN.trxM.) */
23 CTRL_NODE_TS, /* TS specific (net.btsN.trxM.tsI.) */
Harald Welte31c0fef2017-04-16 17:26:30 +020024 CTRL_NODE_FSM, /* Finite State Machine (description) */
25 CTRL_NODE_FSM_INST, /* Finite State Machine (instance) */
Daniel Willmann1264cb42010-10-21 15:00:36 +020026 _LAST_CTRL_NODE
27};
28
Harald Welteb4186822018-05-26 17:25:11 +020029/*! Ctrl command types (GET, SET, ...) */
Daniel Willmann1264cb42010-10-21 15:00:36 +020030enum ctrl_type {
Neels Hofmeyr7c1ec8c2017-03-02 14:32:52 +010031 CTRL_TYPE_UNKNOWN,
Daniel Willmann1264cb42010-10-21 15:00:36 +020032 CTRL_TYPE_GET,
33 CTRL_TYPE_SET,
34 CTRL_TYPE_GET_REPLY,
35 CTRL_TYPE_SET_REPLY,
36 CTRL_TYPE_TRAP,
37 CTRL_TYPE_ERROR
38};
39
Harald Welteb4186822018-05-26 17:25:11 +020040/*! human-readable string names for \ref ctrl_type */
Max70c7d412017-02-24 13:59:14 +010041extern const struct value_string ctrl_type_vals[];
42
Harald Welteb4186822018-05-26 17:25:11 +020043/*! Represents a single ctrl connection */
Daniel Willmann1264cb42010-10-21 15:00:36 +020044struct ctrl_connection {
45 struct llist_head list_entry;
46
Harald Welteb4186822018-05-26 17:25:11 +020047 /*! The queue for sending data back */
Daniel Willmann1264cb42010-10-21 15:00:36 +020048 struct osmo_wqueue write_queue;
49
Harald Welteb4186822018-05-26 17:25:11 +020050 /*! Buffer for partial input data */
Jacob Erlbeck141de622014-03-31 13:42:11 +020051 struct msgb *pending_msg;
52
Harald Welteb4186822018-05-26 17:25:11 +020053 /*! Callback if the connection was closed */
Daniel Willmann1264cb42010-10-21 15:00:36 +020054 void (*closed_cb)(struct ctrl_connection *conn);
55
Harald Welteb4186822018-05-26 17:25:11 +020056 /*! Pending commands for this connection */
Daniel Willmann1264cb42010-10-21 15:00:36 +020057 struct llist_head cmds;
Harald Welte39c9e7b2014-08-22 00:28:51 +020058
Harald Welteb4186822018-05-26 17:25:11 +020059 /*! Pending deferred command responses for this connection */
Harald Welte39c9e7b2014-08-22 00:28:51 +020060 struct llist_head def_cmds;
Daniel Willmann1264cb42010-10-21 15:00:36 +020061};
62
Neels Hofmeyrcdbc9af2018-04-03 16:51:49 +020063struct ctrl_cmd_def;
64
Harald Welteb4186822018-05-26 17:25:11 +020065/*! Represents a single ctrl command after parsing */
Daniel Willmann1264cb42010-10-21 15:00:36 +020066struct ctrl_cmd {
Harald Welteb4186822018-05-26 17:25:11 +020067 /*! connection through which the command was received */
Daniel Willmann1264cb42010-10-21 15:00:36 +020068 struct ctrl_connection *ccon;
Harald Welteb4186822018-05-26 17:25:11 +020069 /*! command type */
Daniel Willmann1264cb42010-10-21 15:00:36 +020070 enum ctrl_type type;
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020071 char *id;
Harald Welteb4186822018-05-26 17:25:11 +020072 /*! node of the specified variable */
Daniel Willmann1264cb42010-10-21 15:00:36 +020073 void *node;
Harald Welteb4186822018-05-26 17:25:11 +020074 /*! name of the variable */
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020075 char *variable;
Harald Welteb4186822018-05-26 17:25:11 +020076 /*! value of the specified CTRL variable */
Neels Hofmeyr694f72d2016-10-20 13:46:23 +020077 char *value;
Harald Welteb4186822018-05-26 17:25:11 +020078 /*! respnse message string */
Daniel Willmann1264cb42010-10-21 15:00:36 +020079 char *reply;
Harald Welteb4186822018-05-26 17:25:11 +020080 /*! state representing deferred (async) response, if any */
Neels Hofmeyrcdbc9af2018-04-03 16:51:49 +020081 struct ctrl_cmd_def *defer;
Daniel Willmann1264cb42010-10-21 15:00:36 +020082};
83
Neels Hofmeyrabdd7a22017-10-19 02:40:01 +020084#define ctrl_cmd_reply_printf(cmd, fmt, args ...) \
85 osmo_talloc_asprintf(cmd, cmd->reply, fmt, ## args)
86
Daniel Willmann1264cb42010-10-21 15:00:36 +020087struct ctrl_cmd_struct {
88 int nr_commands;
89 char **command;
90};
91
Harald Welteb4186822018-05-26 17:25:11 +020092/*! Implementation of a given CTRL command. This is what a program registers
93 * using \r ctrl_cmd_install in order to implement a given control variable. */
Daniel Willmann1264cb42010-10-21 15:00:36 +020094struct ctrl_cmd_element {
Harald Welteb4186822018-05-26 17:25:11 +020095 /*! textual name/id of the CTRL command */
Daniel Willmann1264cb42010-10-21 15:00:36 +020096 const char *name;
Daniel Willmann1264cb42010-10-21 15:00:36 +020097 struct ctrl_cmd_struct strcmd;
Harald Welteb4186822018-05-26 17:25:11 +020098 /*! call-back function implementing the SET operation */
Daniel Willmann1264cb42010-10-21 15:00:36 +020099 int (*set)(struct ctrl_cmd *cmd, void *data);
Harald Welteb4186822018-05-26 17:25:11 +0200100 /*! call-back function implementing the GET operation */
Daniel Willmann1264cb42010-10-21 15:00:36 +0200101 int (*get)(struct ctrl_cmd *cmd, void *data);
Harald Welteb4186822018-05-26 17:25:11 +0200102 /*! call-back function to validate a value; called before SET */
Daniel Willmann1264cb42010-10-21 15:00:36 +0200103 int (*verify)(struct ctrl_cmd *cmd, const char *value, void *data);
104};
105
106struct ctrl_cmd_map {
107 char *cmd;
108 enum ctrl_type type;
109};
110
Harald Welte39c9e7b2014-08-22 00:28:51 +0200111/* deferred control command, i.e. responded asynchronously */
112struct ctrl_cmd_def {
113 struct llist_head list; /* ctrl_connection.def_cmds */
114 struct ctrl_cmd *cmd;
115 void *data; /* opaque user data */
116};
117
118struct ctrl_cmd_def *
119ctrl_cmd_def_make(const void *ctx, struct ctrl_cmd *cmd, void *data, unsigned int secs);
120int ctrl_cmd_def_is_zombie(struct ctrl_cmd_def *cd);
121int ctrl_cmd_def_send(struct ctrl_cmd_def *cd);
122
Daniel Willmann1264cb42010-10-21 15:00:36 +0200123int ctrl_cmd_exec(vector vline, struct ctrl_cmd *command, vector node, void *data);
124int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200125int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd);
Daniel Willmann35a1b3b2011-05-06 16:38:11 +0200126int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd);
Pau Espin Pedrol239ed3b2018-07-12 17:51:16 +0200127struct ctrl_cmd *ctrl_cmd_parse3(void *ctx, struct msgb *msg, bool *parse_failed);
Neels Hofmeyrf2e83ad2017-12-16 01:05:25 +0100128struct ctrl_cmd *ctrl_cmd_parse2(void *ctx, struct msgb *msg);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200129struct ctrl_cmd *ctrl_cmd_parse(void *ctx, struct msgb *msg);
130struct msgb *ctrl_cmd_make(struct ctrl_cmd *cmd);
Daniel Willmann8b7a9622011-03-17 15:37:54 +0100131struct ctrl_cmd *ctrl_cmd_cpy(void *ctx, struct ctrl_cmd *cmd);
Holger Hans Peter Freythera6b34012011-08-22 23:44:32 +0200132struct ctrl_cmd *ctrl_cmd_create(void *ctx, enum ctrl_type);
Daniel Willmannf2e75d42011-07-22 18:08:31 +0200133struct ctrl_cmd *ctrl_cmd_trap(struct ctrl_cmd *cmd);
Daniel Willmann1264cb42010-10-21 15:00:36 +0200134
Harald Welteb4186822018-05-26 17:25:11 +0200135/*! Helper to generate static struct ctrl_cmd_element
136 * \param[in] cmdname symbol name of the command related functions/structures
137 * \param[in] cmdstr string name exposed on CTRL
138 * \param[in] verify_name full symbol name of verification function */
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200139#define CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_name) \
140static struct ctrl_cmd_element cmd_##cmdname = { \
141 .name = cmdstr, \
142 .get = &get_##cmdname, \
143 .set = &set_##cmdname, \
144 .verify = verify_name, \
145}
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100146
Harald Welteb4186822018-05-26 17:25:11 +0200147/*! Helper to generate static GET function for integer
148 * \param[in] cmdname symbol name of the command related function
149 * \param[in] dtype name of outer struct of user data
150 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100151#define CTRL_HELPER_GET_INT(cmdname, dtype, element) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100152static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200153{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100154 dtype *node = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200155 cmd->reply = talloc_asprintf(cmd, "%i", node->element); \
156 if (!cmd->reply) { \
157 cmd->reply = "OOM"; \
158 return CTRL_CMD_ERROR; \
159 } \
160 return CTRL_CMD_REPLY; \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100161}
Harald Welteb4186822018-05-26 17:25:11 +0200162
163/*! Helper to generate static SET function for integer
164 * \param[in] cmdname symbol name of the command related function
165 * \param[in] dtype name of outer struct of user data
166 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100167#define CTRL_HELPER_SET_INT(cmdname, dtype, element) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100168static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200169{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100170 dtype *node = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200171 int tmp = atoi(cmd->value); \
172 node->element = tmp; \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100173 return get_##cmdname(cmd, _data); \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100174}
Harald Welteb4186822018-05-26 17:25:11 +0200175
176/*! Helper to generate static VERIFY unction validating a numeric range
177 * \param[in] cmdname symbol name of the command related function
178 * \param[in] min minimum permitted integer value
179 * \param[in] max maximum permitted integer value */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100180#define CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100181static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200182{ \
183 int tmp = atoi(value); \
184 if ((tmp >= min)&&(tmp <= max)) { \
185 return 0; \
186 } \
Holger Hans Peter Freythere9f7be12013-02-22 10:53:29 +0100187 cmd->reply = "Input not within the range"; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200188 return -1; \
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100189}
190
Harald Welteb4186822018-05-26 17:25:11 +0200191/*! Helper to generate GET, SET, VERIFY + ctrl_cmd_element for integer
192 * \param[in] cmdname symbol name of the command related function
193 * \param[in] cmdstr string name exposed on CTRL
194 * \param[in] dtype name of outer struct of user data
195 * \param[in] element name of field within \a dtype
196 * \param[in] min minimum permitted integer value
197 * \param[in] max maximum permitted integer value */
Holger Hans Peter Freyther05f655e2013-02-22 10:09:45 +0100198#define CTRL_CMD_DEFINE_RANGE(cmdname, cmdstr, dtype, element, min, max) \
199 CTRL_HELPER_GET_INT(cmdname, dtype, element) \
200 CTRL_HELPER_SET_INT(cmdname, dtype, element) \
201 CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \
Holger Hans Peter Freyther0e7b67c2014-05-15 17:27:12 +0200202CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200203
Harald Welteb4186822018-05-26 17:25:11 +0200204/*! Helper to generate static GET function for string
205 * \param[in] cmdname symbol name of the command related function
206 * \param[in] dtype name of outer struct of user data
207 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100208#define CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther43a11db2013-01-09 16:54:49 +0100209static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200210{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100211 dtype *data = cmd->node; \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200212 cmd->reply = talloc_asprintf(cmd, "%s", data->element); \
213 if (!cmd->reply) { \
214 cmd->reply = "OOM"; \
215 return CTRL_CMD_ERROR; \
216 } \
217 return CTRL_CMD_REPLY; \
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100218}
Harald Welteb4186822018-05-26 17:25:11 +0200219
220/*! Helper to generate static SET function for string
221 * \param[in] cmdname symbol name of the command related function
222 * \param[in] dtype name of outer struct of user data
223 * \param[in] element name of field within \a dtype */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100224#define CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther43a11db2013-01-09 16:54:49 +0100225static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200226{ \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100227 dtype *data = cmd->node; \
Harald Weltef3c7e852014-08-20 22:50:47 +0200228 osmo_talloc_replace_string(cmd->node, &data->element, cmd->value); \
Holger Hans Peter Freyther17e7e5a2013-01-09 17:11:50 +0100229 return get_##cmdname(cmd, _data); \
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100230}
Harald Welteb4186822018-05-26 17:25:11 +0200231
232/*! Helper to generate GET, SET, VERIFY + ctrl_cmd_element for string
233 * \param[in] cmdname symbol name of the command related function
234 * \param[in] cmdstr string name exposed on CTRL
235 * \param[in] dtype name of outer struct of user data
236 * \param[in] element name of field within \a dtype
237 * \param[in] min minimum permitted integer value
238 * \param[in] max maximum permitted integer value */
Holger Hans Peter Freyther416e3162013-02-22 11:04:35 +0100239#define CTRL_CMD_DEFINE_STRING(cmdname, cmdstr, dtype, element) \
240 CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
241 CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200242CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, NULL)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200243
Harald Welteb4186822018-05-26 17:25:11 +0200244/*! Declare a read-write attribute. Declares get, set, verify.
245 * \param[in] cmdname symbol name of the command related functions/structures
246 * \param[in] cmdstr string name exposed on CTRL */
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200247#define CTRL_CMD_DEFINE(cmdname, cmdstr) \
Daniel Willmannf7c74e52011-08-05 11:48:18 +0200248static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \
249static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
250static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data); \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200251CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Daniel Willmannfcf010f2011-05-05 17:01:09 +0200252
Harald Welteb4186822018-05-26 17:25:11 +0200253/*! Define a read-only attribute. Declares get, implements set+verify
254 * \param[in] cmdname symbol name of the command related functions/structures
255 * \param[in] cmdstr string name exposed on CTRL */
Holger Hans Peter Freytherc08c5512014-05-14 09:50:27 +0200256#define CTRL_CMD_DEFINE_RO(cmdname, cmdstr) \
257static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \
258static int set_##cmdname(struct ctrl_cmd *cmd, void *data) \
259{ \
260 cmd->reply = "Read Only attribute"; \
261 return CTRL_CMD_ERROR; \
262} \
263static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data) \
264{ \
265 cmd->reply = "Read Only attribute"; \
266 return 1; \
267} \
Holger Hans Peter Freyther62179302014-05-15 15:33:46 +0200268CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
Holger Hans Peter Freytherc08c5512014-05-14 09:50:27 +0200269
Harald Welteb4186822018-05-26 17:25:11 +0200270/*! Define a write-only attribute. Declares set+verify, implements read call-back
271 * \param[in] cmdname symbol name of the command related functions/structures
272 * \param[in] cmdstr string name exposed on CTRL */
Max89287472017-01-11 17:47:04 +0100273#define CTRL_CMD_DEFINE_WO(cmdname, cmdstr) \
274static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
275static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
276{ \
277 cmd->reply = "Write Only attribute"; \
278 return CTRL_CMD_ERROR; \
279} \
280static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data); \
281CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
282
Harald Welteb4186822018-05-26 17:25:11 +0200283/*! Define a write-only attribute without verify. Declares set, implements read+verify
284 * \param[in] cmdname symbol name of the command related functions/structures
285 * \param[in] cmdstr string name exposed on CTRL */
Max89287472017-01-11 17:47:04 +0100286#define CTRL_CMD_DEFINE_WO_NOVRF(cmdname, cmdstr) \
287static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
288static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
289{ \
290 cmd->reply = "Write Only attribute"; \
291 return CTRL_CMD_ERROR; \
292} \
293static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data) \
294{ \
295 return 0; \
296} \
297CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
298
Harald Welte18b70b52011-07-13 14:14:03 +0200299struct gsm_network;