Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 1 | /*! \file control_cmd.h */ |
| 2 | |
Harald Welte | 5ddd435 | 2014-08-21 15:42:44 +0200 | [diff] [blame] | 3 | #pragma once |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 4 | |
| 5 | #include <osmocom/core/msgb.h> |
Holger Hans Peter Freyther | 43a11db | 2013-01-09 16:54:49 +0100 | [diff] [blame] | 6 | #include <osmocom/core/talloc.h> |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 7 | #include <osmocom/core/write_queue.h> |
Harald Welte | 1238cc6 | 2014-08-20 19:50:04 +0200 | [diff] [blame] | 8 | #include <osmocom/core/logging.h> |
Max | 70c7d41 | 2017-02-24 13:59:14 +0100 | [diff] [blame] | 9 | #include <osmocom/core/utils.h> |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 10 | #include <osmocom/vty/vector.h> |
| 11 | |
| 12 | #define CTRL_CMD_ERROR -1 |
| 13 | #define CTRL_CMD_HANDLED 0 |
| 14 | #define CTRL_CMD_REPLY 1 |
Max | 30b2e34 | 2018-11-26 10:38:55 +0100 | [diff] [blame] | 15 | #define CTRL_CMD_TRAP_ID "0" |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 16 | |
Daniel Willmann | 35a1b3b | 2011-05-06 16:38:11 +0200 | [diff] [blame] | 17 | struct ctrl_handle; |
| 18 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 19 | /*! The class of node at which a ctrl command is registered to */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 20 | enum ctrl_node_type { |
| 21 | CTRL_NODE_ROOT, /* Root elements */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 22 | 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 Welte | 31c0fef | 2017-04-16 17:26:30 +0200 | [diff] [blame] | 25 | CTRL_NODE_FSM, /* Finite State Machine (description) */ |
| 26 | CTRL_NODE_FSM_INST, /* Finite State Machine (instance) */ |
Matan Perelman | 0df28e0 | 2024-01-30 17:04:57 +0200 | [diff] [blame] | 27 | CTRL_NODE_LCHAN, /* LCHAN specific (net.btsN.trxM.tsI.lchanL) */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 28 | _LAST_CTRL_NODE |
| 29 | }; |
| 30 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 31 | /*! Ctrl command types (GET, SET, ...) */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 32 | enum ctrl_type { |
Neels Hofmeyr | 7c1ec8c | 2017-03-02 14:32:52 +0100 | [diff] [blame] | 33 | CTRL_TYPE_UNKNOWN, |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 34 | CTRL_TYPE_GET, |
| 35 | CTRL_TYPE_SET, |
| 36 | CTRL_TYPE_GET_REPLY, |
| 37 | CTRL_TYPE_SET_REPLY, |
| 38 | CTRL_TYPE_TRAP, |
| 39 | CTRL_TYPE_ERROR |
| 40 | }; |
| 41 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 42 | /*! human-readable string names for \ref ctrl_type */ |
Max | 70c7d41 | 2017-02-24 13:59:14 +0100 | [diff] [blame] | 43 | extern const struct value_string ctrl_type_vals[]; |
| 44 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 45 | /*! Represents a single ctrl connection */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 46 | struct ctrl_connection { |
| 47 | struct llist_head list_entry; |
| 48 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 49 | /*! The queue for sending data back */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 50 | struct osmo_wqueue write_queue; |
| 51 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 52 | /*! Buffer for partial input data */ |
Jacob Erlbeck | 141de62 | 2014-03-31 13:42:11 +0200 | [diff] [blame] | 53 | struct msgb *pending_msg; |
| 54 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 55 | /*! Callback if the connection was closed */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 56 | void (*closed_cb)(struct ctrl_connection *conn); |
| 57 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 58 | /*! Pending commands for this connection */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 59 | struct llist_head cmds; |
Harald Welte | 39c9e7b | 2014-08-22 00:28:51 +0200 | [diff] [blame] | 60 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 61 | /*! Pending deferred command responses for this connection */ |
Harald Welte | 39c9e7b | 2014-08-22 00:28:51 +0200 | [diff] [blame] | 62 | struct llist_head def_cmds; |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 63 | }; |
| 64 | |
Neels Hofmeyr | cdbc9af | 2018-04-03 16:51:49 +0200 | [diff] [blame] | 65 | struct ctrl_cmd_def; |
| 66 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 67 | /*! Represents a single ctrl command after parsing */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 68 | struct ctrl_cmd { |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 69 | /*! connection through which the command was received */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 70 | struct ctrl_connection *ccon; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 71 | /*! command type */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 72 | enum ctrl_type type; |
Neels Hofmeyr | 694f72d | 2016-10-20 13:46:23 +0200 | [diff] [blame] | 73 | char *id; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 74 | /*! node of the specified variable */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 75 | void *node; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 76 | /*! name of the variable */ |
Neels Hofmeyr | 694f72d | 2016-10-20 13:46:23 +0200 | [diff] [blame] | 77 | char *variable; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 78 | /*! value of the specified CTRL variable */ |
Neels Hofmeyr | 694f72d | 2016-10-20 13:46:23 +0200 | [diff] [blame] | 79 | char *value; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 80 | /*! respnse message string */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 81 | char *reply; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 82 | /*! state representing deferred (async) response, if any */ |
Neels Hofmeyr | cdbc9af | 2018-04-03 16:51:49 +0200 | [diff] [blame] | 83 | struct ctrl_cmd_def *defer; |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 84 | }; |
| 85 | |
Neels Hofmeyr | abdd7a2 | 2017-10-19 02:40:01 +0200 | [diff] [blame] | 86 | #define ctrl_cmd_reply_printf(cmd, fmt, args ...) \ |
| 87 | osmo_talloc_asprintf(cmd, cmd->reply, fmt, ## args) |
| 88 | |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 89 | struct ctrl_cmd_struct { |
| 90 | int nr_commands; |
| 91 | char **command; |
| 92 | }; |
| 93 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 94 | /*! Implementation of a given CTRL command. This is what a program registers |
| 95 | * using \r ctrl_cmd_install in order to implement a given control variable. */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 96 | struct ctrl_cmd_element { |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 97 | /*! textual name/id of the CTRL command */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 98 | const char *name; |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 99 | struct ctrl_cmd_struct strcmd; |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 100 | /*! call-back function implementing the SET operation */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 101 | int (*set)(struct ctrl_cmd *cmd, void *data); |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 102 | /*! call-back function implementing the GET operation */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 103 | int (*get)(struct ctrl_cmd *cmd, void *data); |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 104 | /*! call-back function to validate a value; called before SET */ |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 105 | int (*verify)(struct ctrl_cmd *cmd, const char *value, void *data); |
| 106 | }; |
| 107 | |
| 108 | struct ctrl_cmd_map { |
| 109 | char *cmd; |
| 110 | enum ctrl_type type; |
| 111 | }; |
| 112 | |
Harald Welte | 39c9e7b | 2014-08-22 00:28:51 +0200 | [diff] [blame] | 113 | /* deferred control command, i.e. responded asynchronously */ |
| 114 | struct ctrl_cmd_def { |
| 115 | struct llist_head list; /* ctrl_connection.def_cmds */ |
| 116 | struct ctrl_cmd *cmd; |
| 117 | void *data; /* opaque user data */ |
| 118 | }; |
| 119 | |
| 120 | struct ctrl_cmd_def * |
| 121 | ctrl_cmd_def_make(const void *ctx, struct ctrl_cmd *cmd, void *data, unsigned int secs); |
| 122 | int ctrl_cmd_def_is_zombie(struct ctrl_cmd_def *cd); |
| 123 | int ctrl_cmd_def_send(struct ctrl_cmd_def *cd); |
| 124 | |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 125 | int ctrl_cmd_exec(vector vline, struct ctrl_cmd *command, vector node, void *data); |
| 126 | int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd); |
Daniel Willmann | 35a1b3b | 2011-05-06 16:38:11 +0200 | [diff] [blame] | 127 | int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd); |
Pau Espin Pedrol | 239ed3b | 2018-07-12 17:51:16 +0200 | [diff] [blame] | 128 | struct ctrl_cmd *ctrl_cmd_parse3(void *ctx, struct msgb *msg, bool *parse_failed); |
Neels Hofmeyr | f2e83ad | 2017-12-16 01:05:25 +0100 | [diff] [blame] | 129 | struct ctrl_cmd *ctrl_cmd_parse2(void *ctx, struct msgb *msg); |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 130 | struct ctrl_cmd *ctrl_cmd_parse(void *ctx, struct msgb *msg); |
| 131 | struct msgb *ctrl_cmd_make(struct ctrl_cmd *cmd); |
Daniel Willmann | 8b7a962 | 2011-03-17 15:37:54 +0100 | [diff] [blame] | 132 | struct ctrl_cmd *ctrl_cmd_cpy(void *ctx, struct ctrl_cmd *cmd); |
Holger Hans Peter Freyther | a6b3401 | 2011-08-22 23:44:32 +0200 | [diff] [blame] | 133 | struct ctrl_cmd *ctrl_cmd_create(void *ctx, enum ctrl_type); |
Daniel Willmann | f2e75d4 | 2011-07-22 18:08:31 +0200 | [diff] [blame] | 134 | struct ctrl_cmd *ctrl_cmd_trap(struct ctrl_cmd *cmd); |
Daniel Willmann | 1264cb4 | 2010-10-21 15:00:36 +0200 | [diff] [blame] | 135 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 136 | /*! 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 Freyther | 6217930 | 2014-05-15 15:33:46 +0200 | [diff] [blame] | 140 | #define CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_name) \ |
| 141 | static 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 147 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 148 | /*! 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 152 | #define CTRL_HELPER_GET_INT(cmdname, dtype, element) \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 153 | static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 154 | { \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 155 | dtype *node = cmd->node; \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 156 | 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 162 | } |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 163 | |
| 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 168 | #define CTRL_HELPER_SET_INT(cmdname, dtype, element) \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 169 | static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 170 | { \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 171 | dtype *node = cmd->node; \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 172 | int tmp = atoi(cmd->value); \ |
| 173 | node->element = tmp; \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 174 | return get_##cmdname(cmd, _data); \ |
Holger Hans Peter Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 175 | } |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 176 | |
| 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 181 | #define CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 182 | static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *_data) \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 183 | { \ |
| 184 | int tmp = atoi(value); \ |
| 185 | if ((tmp >= min)&&(tmp <= max)) { \ |
| 186 | return 0; \ |
| 187 | } \ |
Holger Hans Peter Freyther | e9f7be1 | 2013-02-22 10:53:29 +0100 | [diff] [blame] | 188 | cmd->reply = "Input not within the range"; \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 189 | return -1; \ |
Holger Hans Peter Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 190 | } |
| 191 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 192 | /*! 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 Freyther | 05f655e | 2013-02-22 10:09:45 +0100 | [diff] [blame] | 199 | #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 Freyther | 0e7b67c | 2014-05-15 17:27:12 +0200 | [diff] [blame] | 203 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname) |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 204 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 205 | /*! 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 Freyther | 416e316 | 2013-02-22 11:04:35 +0100 | [diff] [blame] | 209 | #define CTRL_HELPER_GET_STRING(cmdname, dtype, element) \ |
Holger Hans Peter Freyther | 43a11db | 2013-01-09 16:54:49 +0100 | [diff] [blame] | 210 | static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 211 | { \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 212 | dtype *data = cmd->node; \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 213 | 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 Freyther | 416e316 | 2013-02-22 11:04:35 +0100 | [diff] [blame] | 219 | } |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 220 | |
| 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 Freyther | 416e316 | 2013-02-22 11:04:35 +0100 | [diff] [blame] | 225 | #define CTRL_HELPER_SET_STRING(cmdname, dtype, element) \ |
Holger Hans Peter Freyther | 43a11db | 2013-01-09 16:54:49 +0100 | [diff] [blame] | 226 | static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \ |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 227 | { \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 228 | dtype *data = cmd->node; \ |
Harald Welte | f3c7e85 | 2014-08-20 22:50:47 +0200 | [diff] [blame] | 229 | osmo_talloc_replace_string(cmd->node, &data->element, cmd->value); \ |
Holger Hans Peter Freyther | 17e7e5a | 2013-01-09 17:11:50 +0100 | [diff] [blame] | 230 | return get_##cmdname(cmd, _data); \ |
Holger Hans Peter Freyther | 416e316 | 2013-02-22 11:04:35 +0100 | [diff] [blame] | 231 | } |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 232 | |
| 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 Yanitskiy | 2a0b121 | 2023-02-28 03:29:35 +0700 | [diff] [blame] | 237 | * \param[in] element name of field within \a dtype */ |
Holger Hans Peter Freyther | 416e316 | 2013-02-22 11:04:35 +0100 | [diff] [blame] | 238 | #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 Freyther | 6217930 | 2014-05-15 15:33:46 +0200 | [diff] [blame] | 241 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, NULL) |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 242 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 243 | /*! 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 Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 246 | #define CTRL_CMD_DEFINE(cmdname, cmdstr) \ |
Daniel Willmann | f7c74e5 | 2011-08-05 11:48:18 +0200 | [diff] [blame] | 247 | static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \ |
| 248 | static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \ |
| 249 | static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data); \ |
Holger Hans Peter Freyther | 6217930 | 2014-05-15 15:33:46 +0200 | [diff] [blame] | 250 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname) |
Daniel Willmann | fcf010f | 2011-05-05 17:01:09 +0200 | [diff] [blame] | 251 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 252 | /*! 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 Freyther | c08c551 | 2014-05-14 09:50:27 +0200 | [diff] [blame] | 255 | #define CTRL_CMD_DEFINE_RO(cmdname, cmdstr) \ |
| 256 | static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \ |
| 257 | static int set_##cmdname(struct ctrl_cmd *cmd, void *data) \ |
| 258 | { \ |
| 259 | cmd->reply = "Read Only attribute"; \ |
| 260 | return CTRL_CMD_ERROR; \ |
| 261 | } \ |
| 262 | static 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 Freyther | 6217930 | 2014-05-15 15:33:46 +0200 | [diff] [blame] | 267 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname) |
Holger Hans Peter Freyther | c08c551 | 2014-05-14 09:50:27 +0200 | [diff] [blame] | 268 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 269 | /*! 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 */ |
Max | 8928747 | 2017-01-11 17:47:04 +0100 | [diff] [blame] | 272 | #define CTRL_CMD_DEFINE_WO(cmdname, cmdstr) \ |
| 273 | static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \ |
| 274 | static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \ |
| 275 | { \ |
| 276 | cmd->reply = "Write Only attribute"; \ |
| 277 | return CTRL_CMD_ERROR; \ |
| 278 | } \ |
| 279 | static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data); \ |
| 280 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname) |
| 281 | |
Harald Welte | b418682 | 2018-05-26 17:25:11 +0200 | [diff] [blame] | 282 | /*! 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 */ |
Max | 8928747 | 2017-01-11 17:47:04 +0100 | [diff] [blame] | 285 | #define CTRL_CMD_DEFINE_WO_NOVRF(cmdname, cmdstr) \ |
| 286 | static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \ |
| 287 | static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \ |
| 288 | { \ |
| 289 | cmd->reply = "Write Only attribute"; \ |
| 290 | return CTRL_CMD_ERROR; \ |
| 291 | } \ |
| 292 | static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void *data) \ |
| 293 | { \ |
| 294 | return 0; \ |
| 295 | } \ |
| 296 | CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname) |
| 297 | |
Harald Welte | 18b70b5 | 2011-07-13 14:14:03 +0200 | [diff] [blame] | 298 | struct gsm_network; |