Loading...
Searching...
No Matches
control_if.c File Reference

SNMP-like status interface. More...

`#include "config.h"`
`#include <errno.h>`
`#include <inttypes.h>`
`#include <stdio.h>`
`#include <stdlib.h>`
`#include <string.h>`
`#include <time.h>`
`#include <unistd.h>`
`#include <limits.h>`
`#include <arpa/inet.h>`
`#include <netinet/in.h>`
`#include <netinet/tcp.h>`
`#include <fcntl.h>`
`#include <sys/ioctl.h>`
`#include <sys/socket.h>`
`#include <sys/types.h>`
`#include <osmocom/ctrl/control_cmd.h>`
`#include <osmocom/ctrl/control_if.h>`
`#include <osmocom/core/msgb.h>`
`#include <osmocom/core/rate_ctr.h>`
`#include <osmocom/core/stat_item.h>`
`#include <osmocom/core/select.h>`
`#include <osmocom/core/counter.h>`
`#include <osmocom/core/talloc.h>`
`#include <osmocom/core/socket.h>`
`#include <osmocom/gsm/protocol/ipaccess.h>`
`#include <osmocom/gsm/ipa.h>`
`#include <osmocom/vty/command.h>`
`#include <osmocom/vty/vector.h>`

## Data Structures

struct | lookup_helper

## Functions

int | osmo_fsm_ctrl_cmds_install (void)
static | LLIST_HEAD (ctrl_lookup_helpers)
int | ctrl_parse_get_num (vector vline, int i, long *num)
| Parse ascii-encoded decimal number at vline[i].
int | ctrl_cmd_send_to_all (struct ctrl_handle *ctrl, struct ctrl_cmd *cmd)
| Send a CTRL command to all connections.
int | ctrl_cmd_send (struct osmo_wqueue *queue, struct ctrl_cmd *cmd)
| Encode a CTRL command and append it to the given write queue.
int | ctrl_cmd_send_trap (struct ctrl_handle *ctrl, const char *name, char *value)
| Send TRAP over given Control Interface.
struct ctrl_cmd * | ctrl_cmd_trap (struct ctrl_cmd *cmd)
| Copy given cmd and convert copy to CTRL_TYPE_TRAP.
static void | control_close_conn (struct ctrl_connection *ccon)
int | ctrl_cmd_handle (struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void *data)
static int | handle_control_read (struct osmo_fd *bfd)
int | ctrl_handle_msg (struct ctrl_handle *ctrl, struct ctrl_connection *ccon, struct msgb *msg)
| Handle a received CTRL command contained in a Message buffers.
static int | control_write_cb (struct osmo_fd *bfd, struct msgb *msg)
struct ctrl_connection * | osmo_ctrl_conn_alloc (void *ctx, void *data)
| Allocate CTRL connection.
static int | listen_fd_cb (struct osmo_fd *listen_bfd, unsigned int what)
static uint64_t | get_rate_ctr_value (const struct rate_ctr *ctr, int intv, const char *grp)
static int | get_rate_ctr_group_idx (struct rate_ctr_group *ctrg, int intv, struct ctrl_cmd *cmd)
static int | ctrl_rate_ctr_group_handler (struct rate_ctr_group *ctrg, void *data)
| CTRL_CMD_DEFINE (rate_ctr, "rate_ctr *")
static int | get_rate_ctr (struct ctrl_cmd *cmd, void *data)
static int | set_rate_ctr (struct ctrl_cmd *cmd, void *data)
static int | verify_rate_ctr (struct ctrl_cmd *cmd, const char *value, void *data)
| CTRL_CMD_DEFINE_RO (stat_item, "stat_item *")
static int | get_stat_item (struct ctrl_cmd *cmd, void *data)
| CTRL_CMD_DEFINE (counter, "counter *")
static int | get_counter (struct ctrl_cmd *cmd, void *data)
static int | set_counter (struct ctrl_cmd *cmd, void *data)
static int | verify_counter (struct ctrl_cmd *cmd, const char *value, void *data)
struct ctrl_handle * | ctrl_interface_setup (void *data, uint16_t port, ctrl_cmd_lookup lookup)
static int | ctrl_init (unsigned int node_count)
struct ctrl_handle * | ctrl_handle_alloc2 (void *ctx, void *data, ctrl_cmd_lookup lookup, unsigned int node_count)
| Allocate a CTRL interface handle.
struct ctrl_handle * | ctrl_handle_alloc (void *ctx, void *data, ctrl_cmd_lookup lookup)
| Allocate a CTRL interface handle.
struct ctrl_handle * | ctrl_interface_setup_dynip2 (void *data, const char *bind_addr, uint16_t port, ctrl_cmd_lookup lookup, unsigned int node_count)
| Setup CTRL interface on a given address.
struct ctrl_handle * | ctrl_interface_setup_dynip (void *data, const char *bind_addr, uint16_t port, ctrl_cmd_lookup lookup)
| Setup CTRL interface on a given address.
int | ctrl_lookup_register (ctrl_cmd_lookup lookup)
| Install a lookup helper function for control nodes This function is used by e.g.
struct ctrl_cmd * | ctrl_cmd_exec_from_string (struct ctrl_handle *ch, const char *cmdstr)
| Helper for "local execution" of a CTRL command from a string The function will parse + execute the given control command string and return a corresponding ctrl_cmd.

## Variables

vector | ctrl_node_vec
static int | ctrl_initialized = 0

## Detailed Description

SNMP-like status interface.

## Function Documentation

## control_close_conn()

static void control_close_conn | ( | struct ctrl_connection * | ccon | ) |

static

References osmo_wqueue::bfd, ctrl_connection::closed_cb, ctrl_cmd_def::cmd, ctrl_connection::def_cmds, DLCTRL, osmo_fd::fd, ctrl_cmd_def::list, ctrl_connection::list_entry, llist_for_each_entry_safe, LOGL_INFO, LOGP, msgb_free(), name, osmo_fd_unregister(), osmo_sock_get_name(), osmo_wqueue_clear(), ctrl_connection::pending_msg, and ctrl_connection::write_queue.

Referenced by control_write_cb(), and handle_control_read().

## control_write_cb()

static int control_write_cb | ( | struct osmo_fd * | bfd,
|  | struct msgb * | msg
| ) |  |

static

References container_of, control_close_conn(), DLCTRL, osmo_fd::fd, len, LOGL_ERROR, LOGP, msg, and ctrl_connection::write_queue.

Referenced by osmo_ctrl_conn_alloc().

## CTRL_CMD_DEFINE() [1/2]

CTRL_CMD_DEFINE | ( | counter | ,
|  | "counter *" |
| ) |  |

## CTRL_CMD_DEFINE() [2/2]

CTRL_CMD_DEFINE | ( | rate_ctr | ,
|  | "rate_ctr *" |
| ) |  |

## CTRL_CMD_DEFINE_RO()

CTRL_CMD_DEFINE_RO | ( | stat_item | ,
|  | "stat_item *" |
| ) |  |

## ctrl_cmd_exec_from_string()

struct ctrl_cmd * ctrl_cmd_exec_from_string | ( | struct ctrl_handle * | ch,
|  | const char * | cmdstr
| ) |  |

Helper for "local execution" of a CTRL command from a string The function will parse + execute the given control command string and return a corresponding ctrl_cmd.

Caller is responsible to talloc_free() the return value.

Parameters

  [in] | Control | Interface Command String

Returns
  parsed command, including reply; NULL on error

References ctrl_cmd_handle(), CTRL_CMD_HANDLED, ctrl_cmd_parse2(), CTRL_TYPE_ERROR, msg, msgb_alloc(), msgb_free(), osmo_strlcpy(), and ctrl_cmd::type.

## ctrl_cmd_handle()

int ctrl_cmd_handle | ( | struct ctrl_handle * | ctrl,
|  | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

References ctrl_cmd_def::cmd, cmd_free_strvec(), cmd_make_strvec(), cmdvec, CTRL_CMD_ERROR, ctrl_cmd_exec(), CTRL_CMD_HANDLED, CTRL_CMD_REPLY, CTRL_NODE_ROOT, ctrl_node_vec, CTRL_TYPE_ERROR, CTRL_TYPE_GET_REPLY, CTRL_TYPE_SET_REPLY, ctrl_type_vals, data, ctrl_cmd_def::data, DLCTRL, get_value_string(), ctrl_cmd::id, lookup_helper::list, llist_for_each_entry, LOGL_DEBUG, LOGL_ERROR, LOGL_NOTICE, LOGP, ctrl_handle::lookup, lookup_helper::lookup, node, ctrl_cmd::node, ctrl_cmd::reply, ctrl_handle::reply_cb, ctrl_cmd::type, ctrl_cmd::variable, vector_active, vector_free(), vector_init(), vector_lookup(), vector_set(), and vector_slot.

Referenced by ctrl_cmd_exec_from_string(), and ctrl_handle_msg().

## ctrl_cmd_send()

int ctrl_cmd_send | ( | struct osmo_wqueue * | queue,
|  | struct ctrl_cmd * | cmd
| ) |  |

Encode a CTRL command and append it to the given write queue.

Parameters

  [in,out] | queue | write queue to which encoded cmd shall be appended
  [in] | cmd | decoded command representation

Returns
  0 in case of success; negative on error

References ctrl_cmd_make(), DLCTRL, ipa_prepend_header(), ipa_prepend_header_ext(), IPAC_PROTO_EXT_CTRL, IPAC_PROTO_OSMO, LOGL_ERROR, LOGP, msg, msgb_free(), and osmo_wqueue_enqueue().

Referenced by ctrl_cmd_def_send(), ctrl_cmd_send_to_all(), and ctrl_handle_msg().

## ctrl_cmd_send_to_all()

int ctrl_cmd_send_to_all | ( | struct ctrl_handle * | ctrl,
|  | struct ctrl_cmd * | cmd
| ) |  |

Send a CTRL command to all connections.

Parameters

  [in] | ctrl | global control handle
  [in] | cmd | command to send to all connections in \ctrl

Returns
  number of times the command has been sent

References ctrl_cmd::ccon, ctrl_handle::ccon_list, ctrl_cmd_send(), ctrl_connection::list_entry, llist_for_each_entry, and ctrl_connection::write_queue.

Referenced by ctrl_cmd_send_trap().

## ctrl_cmd_send_trap()

int ctrl_cmd_send_trap | ( | struct ctrl_handle * | ctrl,
|  | const char * | name,
|  | char * | value
| ) |  |

Send TRAP over given Control Interface.

Parameters

  [in] | ctrl | Control Interface over which TRAP will be sent
  [in] | name | Name of the TRAP variable
  [in] | value | Value of the TRAP variable

Returns
  Negative value on error, result of ctrl_cmd_send_to_all() otherwise

References ctrl_cmd_create(), ctrl_cmd_send_to_all(), CTRL_CMD_TRAP_ID, CTRL_TYPE_TRAP, ctrl_cmd::id, name, ctrl_cmd::reply, ctrl_cmd::value, and ctrl_cmd::variable.

## ctrl_cmd_trap()

struct ctrl_cmd * ctrl_cmd_trap | ( | struct ctrl_cmd * | cmd | ) |

Copy given cmd and convert copy to CTRL_TYPE_TRAP.

Parameters

  [in] | cmd | command to be copied

Returns
  pointer to newly-allocated copy of type TRAP. Allocated as sibling of cmd

References ctrl_cmd::ccon, ctrl_cmd_cpy(), CTRL_TYPE_TRAP, and ctrl_cmd::type.

## ctrl_handle_alloc()

struct ctrl_handle * ctrl_handle_alloc | ( | void * | ctx,
|  | void * | data,
|  | ctrl_cmd_lookup | lookup
| ) |  |

Allocate a CTRL interface handle.

Parameters

  [in] | ctx | Talloc allocation context to be used
  [in] | data | Pointer which will be made available to each set_..() get_..() verify_..() control command function
  [in] | lookup | Lookup function pointer, can be NULL

Returns
  ctrl_handle pointer or NULL in case of errors

References ctrl_handle_alloc2(), ctrl_handle::data, and ctrl_handle::lookup.

## ctrl_handle_alloc2()

struct ctrl_handle * ctrl_handle_alloc2 | ( | void * | ctx,
|  | void * | data,
|  | ctrl_cmd_lookup | lookup,
|  | unsigned int | node_count
| ) |  |

Allocate a CTRL interface handle.

Parameters

  [in] | ctx | Talloc allocation context to be used
  [in] | data | Pointer which will be made available to each set_..() get_..() verify_..() control command function
  [in] | lookup | Lookup function pointer, can be NULL
  [in] | node_count | Number of CTRL nodes to allocate, 0 for default.

Returns
  ctrl_handle pointer or NULL in case of errors

Please see ctrl_interface_setup_dynip2() for a detailed description of node_count semantics.

References ctrl_handle::ccon_list, ctrl_init(), ctrl_handle::data, INIT_LLIST_HEAD, and ctrl_handle::lookup.

Referenced by ctrl_handle_alloc(), and ctrl_interface_setup_dynip2().

## ctrl_handle_msg()

int ctrl_handle_msg | ( | struct ctrl_handle * | ctrl,
|  | struct ctrl_connection * | ccon,
|  | struct msgb * | msg
| ) |  |

Handle a received CTRL command contained in a Message buffers.

Parameters

  [in] | ctrl | CTRL interface handle
  [in] | ccon | CTRL connection through which the command was received
  [in] | msg | message buffer containing CTRL command including IPA+IPA_EXT headers

Returns
  0 on success; negative on error

References osmo_wqueue::bfd, ctrl_cmd::ccon, ctrl_cmd_handle(), CTRL_CMD_HANDLED, ctrl_cmd_parse3(), ctrl_cmd_send(), CTRL_TYPE_ERROR, ipaccess_head::data, ipaccess_head_ext::data, ctrl_handle::data, ctrl_cmd::defer, DLCTRL, DLINP, osmo_fd::fd, ctrl_cmd::id, ipa_ccm_send_id_ack(), ipa_ccm_send_pong(), IPAC_MSGT_ID_ACK, IPAC_MSGT_PING, IPAC_MSGT_PONG, IPAC_PROTO_EXT_CTRL, IPAC_PROTO_IPACCESS, IPAC_PROTO_OSMO, LOGL_DEBUG, LOGL_ERROR, LOGP, msg, msg_type, msgb_hexdump(), ipaccess_head::proto, ipaccess_head_ext::proto, ctrl_cmd::reply, ctrl_cmd::type, and ctrl_connection::write_queue.

Referenced by handle_control_read().

## ctrl_init()

static int ctrl_init | ( | unsigned int | node_count | ) |

static

References _LAST_CTRL_NODE, ctrl_cmd_install(), ctrl_initialized, CTRL_NODE_ROOT, ctrl_node_vec, OSMO_ASSERT, osmo_fsm_ctrl_cmds_install(), vector_free(), and vector_init().

Referenced by ctrl_handle_alloc2().

## ctrl_interface_setup()

struct ctrl_handle * ctrl_interface_setup | ( | void * | data,
|  | uint16_t | port,
|  | ctrl_cmd_lookup | lookup
| ) |  |

References ctrl_interface_setup_dynip(), ctrl_handle::data, and ctrl_handle::lookup.

## ctrl_interface_setup_dynip()

struct ctrl_handle * ctrl_interface_setup_dynip | ( | void * | data,
|  | const char * | bind_addr,
|  | uint16_t | port,
|  | ctrl_cmd_lookup | lookup
| ) |  |

Setup CTRL interface on a given address.

Parameters

  [in] | data | Pointer which will be made available to each set_..() get_..() verify_..() control command function
  [in] | bind_addr | Address on which CTRL socket shall listen
  [in] | port | Port on which CTRL socket shall listen
  [in] | lookup | Lookup function pointer, can be NULL

Returns
  ctrl_handle pointer or NULL in case of errors

References ctrl_interface_setup_dynip2(), ctrl_handle::data, and ctrl_handle::lookup.

Referenced by ctrl_interface_setup().

## ctrl_interface_setup_dynip2()

struct ctrl_handle * ctrl_interface_setup_dynip2 | ( | void * | data,
|  | const char * | bind_addr,
|  | uint16_t | port,
|  | ctrl_cmd_lookup | lookup,
|  | unsigned int | node_count
| ) |  |

Setup CTRL interface on a given address.

Parameters

  [in] | data | Pointer which will be made available to each set_..() get_..() verify_..() control command function
  [in] | bind_addr | Address on which CTRL socket shall listen
  [in] | port | Port on which CTRL socket shall listen
  [in] | lookup | Lookup function pointer, can be NULL
  [in] | node_count | Number of CTRL nodes to allocate, 0 for default.

Returns
  ctrl_handle pointer or NULL in case of errors

Control interface nodes are identified by a node handle; some of these are defined in enum ctrl_node_type, here in libosmocore. However, applications defining own nodes may add own control nodes without having to extend the enum in libosmocore. For example, in the calling application, define an enum like "enum more_ctrl_nodes { CTRL_NODE_FOO = _LAST_CTRL_NODE, CTRL_NODE_BAR, _LAST_CTRL_NODE_EXTENDED }". In order to provide space for the additional control nodes, pass _LAST_CTRL_NODE_EXTENDED to the node_count parameter. Passing 0 is identical to passing _LAST_CTRL_NODE, i.e. to not define own control nodes apart from libosmocore ones.

References osmo_fd::cb, ctrl_handle_alloc2(), osmo_fd::data, ctrl_handle::data, DLCTRL, ctrl_handle::listen_fd, listen_fd_cb(), LOGL_NOTICE, LOGP, ctrl_handle::lookup, OSMO_SOCK_F_BIND, and osmo_sock_init_ofd().

Referenced by ctrl_interface_setup_dynip().

## ctrl_lookup_register()

int ctrl_lookup_register | ( | ctrl_cmd_lookup | lookup | ) |

Install a lookup helper function for control nodes This function is used by e.g.

library code to install lookup helpers for additional nodes in the control interface.

Parameters

  [in] | lookup | The lookup helper function \retuns - on success; negative on error.

References lookup_helper::list, llist_for_each_entry, and lookup_helper::lookup.

Referenced by osmo_fsm_ctrl_cmds_install().

## ctrl_parse_get_num()

int ctrl_parse_get_num | ( | vector | vline,
|  | int | i,
|  | long * | num
| ) |  |

Parse ascii-encoded decimal number at vline[i].

Parameters

  [in] | vline | vector containing a tokenized line
  [in] | i | index into the vector vline
  [out] | num | parsed decimal integer number at vline[i]

Returns
  1 on success; 0 in case of error

References osmo_str_to_int64(), vector_active, and vector_slot.

## ctrl_rate_ctr_group_handler()

static int ctrl_rate_ctr_group_handler | ( | struct rate_ctr_group * | ctrg,
|  | void * | data
| ) |  |

static

References data, rate_ctr_group::desc, rate_ctr_group_desc::group_name_prefix, rate_ctr_group::idx, and ctrl_cmd::reply.

Referenced by get_rate_ctr().

## get_counter()

static int get_counter | ( | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

static

References CTRL_CMD_ERROR, CTRL_CMD_REPLY, osmo_counter_get_by_name(), ctrl_cmd::reply, osmo_counter::value, and ctrl_cmd::variable.

## get_rate_ctr()

static int get_rate_ctr | ( | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

static

References CTRL_CMD_ERROR, CTRL_CMD_REPLY, ctrl_rate_ctr_group_handler(), rate_ctr_group::desc, get_rate_ctr_group_idx(), get_rate_ctr_value(), rate_ctr_group_desc::group_name_prefix, rate_ctr::intv, rate_ctr_for_each_group(), rate_ctr_get_by_name(), rate_ctr_get_group_by_name_idx(), RATE_CTR_INTV_DAY, RATE_CTR_INTV_HOUR, RATE_CTR_INTV_MIN, RATE_CTR_INTV_SEC, ctrl_cmd::reply, and ctrl_cmd::variable.

## get_rate_ctr_group_idx()

static int get_rate_ctr_group_idx | ( | struct rate_ctr_group * | ctrg,
|  | int | intv,
|  | struct ctrl_cmd * | cmd
| ) |  |

static

References rate_ctr_group_desc::ctr_desc, CTRL_CMD_ERROR, CTRL_CMD_REPLY, ctrl_cmd_reply_printf, rate_ctr_group::desc, get_rate_ctr_value(), rate_ctr_group_desc::group_name_prefix, rate_ctr_desc::name, rate_ctr_group_desc::num_ctr, rate_ctr_group_get_ctr(), and ctrl_cmd::reply.

Referenced by get_rate_ctr().

## get_rate_ctr_value()

static uint64_t get_rate_ctr_value | ( | const struct rate_ctr * | ctr,
|  | int | intv,
|  | const char * | grp
| ) |  |

static

References rate_ctr::current, DLCTRL, rate_ctr::intv, LOGL_ERROR, LOGP, rate_ctr_per_intv::rate, and RATE_CTR_INTV_NUM.

Referenced by get_rate_ctr(), and get_rate_ctr_group_idx().

## get_stat_item()

static int get_stat_item | ( | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

static

References CTRL_CMD_ERROR, CTRL_CMD_REPLY, osmo_stat_item_get_by_name(), osmo_stat_item_get_group_by_name_idx(), osmo_stat_item_get_group_by_name_idxname(), osmo_stat_item_get_last(), osmo_str_to_int(), ctrl_cmd::reply, and ctrl_cmd::variable.

## handle_control_read()

static int handle_control_read | ( | struct osmo_fd * | bfd | ) |

static

References container_of, control_close_conn(), ctrl_handle_msg(), osmo_fd::data, DLCTRL, osmo_fd::fd, ipa_msg_recv_buffered(), LOGL_ERROR, LOGP, msg, msgb_free(), and ctrl_connection::pending_msg.

Referenced by osmo_ctrl_conn_alloc().

## listen_fd_cb()

static int listen_fd_cb | ( | struct osmo_fd * | listen_bfd,
|  | unsigned int | what
| ) |  |

static

References osmo_wqueue::bfd, ctrl_handle::ccon_list, osmo_fd::data, DLCTRL, osmo_fd::fd, ctrl_connection::list_entry, LOGL_ERROR, LOGL_INFO, LOGP, name, osmo_ctrl_conn_alloc(), OSMO_FD_READ, osmo_fd_register(), osmo_sock_get_name(), osmo_fd::when, and ctrl_connection::write_queue.

Referenced by ctrl_interface_setup_dynip2().

## LLIST_HEAD()

static LLIST_HEAD | ( | ctrl_lookup_helpers |  | ) |

static

References LLIST_HEAD().

## osmo_ctrl_conn_alloc()

struct ctrl_connection * osmo_ctrl_conn_alloc | ( | void * | ctx,
|  | void * | data
| ) |  |

Allocate CTRL connection.

Parameters

  [in] | ctx | Context from which talloc should allocate it
  [in] | data | caller's private data parameter which should assigned to write queue's file descriptor data parameter.

Returns
  Allocated CTRL connection structure or NULL in case of errors

References osmo_wqueue::bfd, ctrl_connection::cmds, control_write_cb(), osmo_fd::data, data, ctrl_connection::def_cmds, osmo_fd::fd, handle_control_read(), INIT_LLIST_HEAD, osmo_wqueue_init(), osmo_wqueue::read_cb, osmo_wqueue::write_cb, and ctrl_connection::write_queue.

Referenced by listen_fd_cb().

## osmo_fsm_ctrl_cmds_install()

int osmo_fsm_ctrl_cmds_install | ( | void |  | ) |

extern

References ctrl_cmd_install(), ctrl_lookup_register(), CTRL_NODE_FSM_INST, and fsm_ctrl_node_lookup().

Referenced by ctrl_init().

## set_counter()

static int set_counter | ( | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

static

References CTRL_CMD_ERROR, and ctrl_cmd::reply.

## set_rate_ctr()

static int set_rate_ctr | ( | struct ctrl_cmd * | cmd,
|  | void * | data
| ) |  |

static

References CTRL_CMD_ERROR, and ctrl_cmd::reply.

## verify_counter()

static int verify_counter | ( | struct ctrl_cmd * | cmd,
|  | const char * | value,
|  | void * | data
| ) |  |

static

## verify_rate_ctr()

static int verify_rate_ctr | ( | struct ctrl_cmd * | cmd,
|  | const char * | value,
|  | void * | data
| ) |  |

static

## Variable Documentation

## ctrl_initialized

int ctrl_initialized = 0

static

Referenced by ctrl_init().

## ctrl_node_vec

vector ctrl_node_vec

Referenced by ctrl_cmd_handle(), ctrl_cmd_install(), and ctrl_init().