diff options
Diffstat (limited to 'src/client/conf-system.c')
-rw-r--r-- | src/client/conf-system.c | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/src/client/conf-system.c b/src/client/conf-system.c new file mode 100644 index 0000000..0700ec2 --- /dev/null +++ b/src/client/conf-system.c @@ -0,0 +1,602 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <unistd.h> +#include <string.h> +#include <sys/utsname.h> + +#include "client.h" +#include "../log.h" + +static int +cmd_iface_pattern(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + log_debug("lldpctl", "set iface pattern"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + + const char *value = cmdenv_get(env, "iface-pattern"); + if (lldpctl_atom_set_str(config, lldpctl_k_config_iface_pattern, value) == + NULL) { + log_warnx("lldpctl", "unable to set iface-pattern. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "iface-pattern set to new value %s", + value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_perm_iface_pattern(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, const void *arg) +{ + log_debug("lldpctl", "set permanent iface pattern"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + + const char *value = cmdenv_get(env, "iface-pattern"); + if (lldpctl_atom_set_str(config, lldpctl_k_config_perm_iface_pattern, value) == + NULL) { + log_warnx("lldpctl", "unable to set permanent iface pattern. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "permanent iface pattern set to new value %s", + value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_iface_promisc(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + if (lldpctl_atom_set_int(config, lldpctl_k_config_iface_promisc, arg ? 1 : 0) == + NULL) { + log_warnx("lldpctl", "unable to %s promiscuous mode: %s", + arg ? "enable" : "disable", lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "interface promiscuous mode %s", + arg ? "enabled" : "disabled"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_system_description(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, const void *arg) +{ + int platform = 0; + const char *what = arg; + const char *value; + if (!strcmp(what, "system")) { + value = cmdenv_get(env, "description"); + } else { + value = cmdenv_get(env, "platform"); + platform = 1; + } + log_debug("lldpctl", "set %s description", what); + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + if (lldpctl_atom_set_str(config, + platform ? lldpctl_k_config_platform : lldpctl_k_config_description, + value) == NULL) { + log_warnx("lldpctl", "unable to set description. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "description set to new value %s", + value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_system_chassisid(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + const char *value; + value = cmdenv_get(env, "description"); + log_debug("lldpctl", "set chassis ID"); + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + if (lldpctl_atom_set_str(config, lldpctl_k_config_cid_string, value) == NULL) { + log_warnx("lldpctl", "unable to set chassis ID. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "chassis ID set to new value %s", value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_management(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + log_debug("lldpctl", "set management pattern"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + + const char *value = cmdenv_get(env, "management-pattern"); + if (lldpctl_atom_set_str(config, lldpctl_k_config_mgmt_pattern, value) == + NULL) { + log_warnx("lldpctl", "unable to set management pattern. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "management pattern set to new value %s", + value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_hostname(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + struct utsname un; + log_debug("lldpctl", "set system name"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + + const char *value = cmdenv_get(env, "hostname"); + if (value && strlen(value) == 1 && value[0] == '.') { + if (uname(&un) < 0) { + log_warn("lldpctl", "cannot get node name"); + lldpctl_atom_dec_ref(config); + return 0; + } + char *c = strchr(un.nodename, '.'); + if (c) *c = 0; + value = un.nodename; + } + if (lldpctl_atom_set_str(config, lldpctl_k_config_hostname, value) == NULL) { + log_warnx("lldpctl", "unable to set system name. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "system name set to new value %s", + value ? value : "(none)"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_capability(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + log_debug("lldpctl", "set capabilities"); + + int ret = 0; + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + lldpctl_atom_t *chassis = NULL; + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + goto cmd_capability_end; + } + + if (!strcmp(arg, "configure")) { + + const char *s = cmdenv_get(env, "capabilities"); + if (s) { + chassis = lldpctl_get_local_chassis(conn); + if (chassis == NULL) { + log_warnx("lldpctl", + "unable to get local chassis from lldpd. %s", + lldpctl_last_strerror(conn)); + goto cmd_capability_end; + } + u_int16_t value = 0; + const char delim[] = ","; + char *s_copy = strdup(s); + char *token = strtok(s_copy, delim); + while (token != NULL) { + if (!strcmp(token, "other")) { + value |= LLDP_CAP_OTHER; + } else if (!strcmp(token, "repeater")) { + value |= LLDP_CAP_REPEATER; + } else if (!strcmp(token, "bridge")) { + value |= LLDP_CAP_BRIDGE; + } else if (!strcmp(token, "wlan")) { + value |= LLDP_CAP_WLAN; + } else if (!strcmp(token, "router")) { + value |= LLDP_CAP_ROUTER; + } else if (!strcmp(token, "telephone")) { + value |= LLDP_CAP_TELEPHONE; + } else if (!strcmp(token, "docsis")) { + value |= LLDP_CAP_DOCSIS; + } else if (!strcmp(token, "station")) { + value |= LLDP_CAP_STATION; + } else { + log_warnx("lldpctl", "capability %s not found", + token); + } + token = strtok(NULL, delim); + } + free(s_copy); + + if (lldpctl_atom_set_int(chassis, lldpctl_k_chassis_cap_enabled, + value) == NULL) { + log_warnx("lldpctl", + "unable to set system capabilities. %s", + lldpctl_last_strerror(conn)); + goto cmd_capability_end; + } + if (lldpctl_atom_set_int(config, + lldpctl_k_config_chassis_cap_override, 1) == NULL) { + log_warnx("lldpctl", + "unable to set system capabilities override. %s", + lldpctl_last_strerror(conn)); + goto cmd_capability_end; + } + log_debug("lldpctl", "system capabilities set to new value %d", + value); + } + } else { + if (lldpctl_atom_set_int(config, lldpctl_k_config_chassis_cap_override, + 0) == NULL) { + log_warnx("lldpctl", + "unable to set system capabilities to not override. %s", + lldpctl_last_strerror(conn)); + goto cmd_capability_end; + } + } + + ret = 1; +cmd_capability_end: + lldpctl_atom_dec_ref(chassis); + lldpctl_atom_dec_ref(config); + return ret; +} + +static int +cmd_update_descriptions(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, const void *arg) +{ + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + if (lldpctl_atom_set_int(config, lldpctl_k_config_ifdescr_update, + arg ? 1 : 0) == NULL) { + log_warnx("lldpctl", "unable to %s interface description update: %s", + arg ? "enable" : "disable", lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "interface description update %s", + arg ? "enabled" : "disabled"); + lldpctl_atom_dec_ref(config); + return 1; +} + +static int +cmd_bondslave_srcmac_type(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, const void *arg) +{ + const char *value_str = 0; + int value = -1; + + log_debug("lldpctl", "bond slave src mac"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + + value_str = arg; + for (lldpctl_map_t *b_map = + lldpctl_key_get_map(lldpctl_k_config_bond_slave_src_mac_type); + b_map->string; b_map++) { + if (!strcmp(b_map->string, value_str)) { + value = b_map->value; + break; + } + } + + if (value == -1) { + log_warnx("lldpctl", "invalid value"); + lldpctl_atom_dec_ref(config); + return 0; + } + + if (lldpctl_atom_set_int(config, lldpctl_k_config_bond_slave_src_mac_type, + value) == NULL) { + log_warnx("lldpctl", + "unable to set bond slave src mac type." + " %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + + log_info("lldpctl", "bond slave src mac set to new value: %s", value_str); + lldpctl_atom_dec_ref(config); + + return 1; +} + +static int +cmd_maxneighs(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, + const void *arg) +{ + log_debug("lldpctl", "set maximum neighbors"); + + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + log_warnx("lldpctl", "unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + return 0; + } + if (lldpctl_atom_set_str(config, lldpctl_k_config_max_neighbors, + cmdenv_get(env, "max-neighbors")) == NULL) { + log_warnx("lldpctl", "unable to set maximum of neighbors. %s", + lldpctl_last_strerror(conn)); + lldpctl_atom_dec_ref(config); + return 0; + } + log_info("lldpctl", "maximum neighbors set to new value %s", + cmdenv_get(env, "max-neighbors")); + lldpctl_atom_dec_ref(config); + return 1; +} + +/** + * Register `configure system bond-slave-src-mac-type` + */ +static void +register_commands_srcmac_type(struct cmd_node *configure) +{ + struct cmd_node *bond_slave_src_mac_type = + commands_new(configure, "bond-slave-src-mac-type", + "Set LLDP bond slave source MAC type", NULL, NULL, NULL); + + for (lldpctl_map_t *b_map = + lldpctl_key_get_map(lldpctl_k_config_bond_slave_src_mac_type); + b_map->string; b_map++) { + if (!strcmp(b_map->string, "real")) { + commands_new(commands_new(bond_slave_src_mac_type, + b_map->string, "Real mac", NULL, NULL, NULL), + NEWLINE, NULL, NULL, cmd_bondslave_srcmac_type, + b_map->string); + } else if (!strcmp(b_map->string, "zero")) { + commands_new(commands_new(bond_slave_src_mac_type, + b_map->string, "All zero mac", NULL, NULL, + NULL), + NEWLINE, NULL, NULL, cmd_bondslave_srcmac_type, + b_map->string); + } else if (!strcmp(b_map->string, "fixed")) { + commands_new(commands_new(bond_slave_src_mac_type, + b_map->string, "Fixed value (3Com card)", NULL, + NULL, NULL), + NEWLINE, NULL, NULL, cmd_bondslave_srcmac_type, + b_map->string); + } else if (!strcmp(b_map->string, "local")) { + commands_new(commands_new(bond_slave_src_mac_type, + b_map->string, + "Real Mac with locally " + "administered bit set", + NULL, NULL, NULL), + NEWLINE, NULL, NULL, cmd_bondslave_srcmac_type, + b_map->string); + } + } +} + +static void +register_commands_capabilities(struct cmd_node *configure, struct cmd_node *unconfigure) +{ + struct cmd_node *configure_capability = commands_new(configure, "capabilities", + "Capabilities configuration", cmd_check_no_env, NULL, "ports"); + struct cmd_node *unconfigure_capability = + commands_new(unconfigure, "capabilities", "Capabilities configuration", + cmd_check_no_env, NULL, "ports"); + + /* Override */ + commands_new(commands_new(commands_new(configure_capability, "enabled", + "Override capabilities", NULL, NULL, NULL), + NULL, " Set of capabilities separated by commas", NULL, + cmd_store_env_value, "capabilities"), + NEWLINE, "Override capabilities", NULL, cmd_capability, "configure"); + + /* Do not override */ + commands_new(commands_new(unconfigure_capability, "enabled", + "Do not override capabilities", NULL, NULL, NULL), + NEWLINE, "Do not override capabilities", NULL, cmd_capability, + "unconfigure"); +} + +/** + * Register `configure system` commands. + * + * Those are the commands to configure protocol-independant stuff. + */ +void +register_commands_configure_system(struct cmd_node *configure, + struct cmd_node *unconfigure) +{ + struct cmd_node *configure_system = commands_new(configure, "system", + "System configuration", cmd_check_no_env, NULL, "ports"); + struct cmd_node *unconfigure_system = commands_new(unconfigure, "system", + "System configuration", cmd_check_no_env, NULL, "ports"); + struct cmd_node *configure_interface = commands_new(configure_system, + "interface", "Interface related items", NULL, NULL, NULL); + struct cmd_node *unconfigure_interface = commands_new(unconfigure_system, + "interface", "Interface related items", NULL, NULL, NULL); + + commands_new(commands_new(commands_new(configure_system, "description", + "Override chassis description", NULL, NULL, NULL), + NULL, "Chassis description", NULL, cmd_store_env_value, + "description"), + NEWLINE, "Override chassis description", NULL, cmd_system_description, + "system"); + commands_new(commands_new(unconfigure_system, "description", + "Don't override chassis description", NULL, NULL, NULL), + NEWLINE, "Don't override chassis description", NULL, cmd_system_description, + "system"); + + commands_new(commands_new(commands_new(configure_system, "chassisid", + "Override chassis ID", NULL, NULL, NULL), + NULL, "Chassis ID", NULL, cmd_store_env_value, "description"), + NEWLINE, "Override chassis ID", NULL, cmd_system_chassisid, "system"); + commands_new(commands_new(unconfigure_system, "chassisid", + "Don't override chassis ID", NULL, NULL, NULL), + NEWLINE, "Don't override chassis ID", NULL, cmd_system_chassisid, "system"); + + commands_new(commands_new(commands_new(configure_system, "platform", + "Override platform description", NULL, NULL, + NULL), + NULL, "Platform description (CDP)", NULL, cmd_store_env_value, + "platform"), + NEWLINE, "Override platform description", NULL, cmd_system_description, + "platform"); + commands_new(commands_new(unconfigure_system, "platform", + "Don't override platform description", NULL, NULL, NULL), + NEWLINE, "Don't override platform description", NULL, + cmd_system_description, "platform"); + + commands_new(commands_new(commands_new(configure_system, "hostname", + "Override system name", NULL, NULL, NULL), + NULL, "System name", NULL, cmd_store_env_value, "hostname"), + NEWLINE, "Override system name", NULL, cmd_hostname, NULL); + commands_new(commands_new(unconfigure_system, "hostname", + "Don't override system name", NULL, NULL, NULL), + NEWLINE, "Don't override system name", NULL, cmd_hostname, NULL); + + commands_new(commands_new(commands_new(configure_system, "max-neighbors", + "Set maximum number of neighbors per port", + cmd_check_no_env, NULL, "ports"), + NULL, "Maximum number of neighbors", NULL, cmd_store_env_value, + "max-neighbors"), + NEWLINE, "Set maximum number of neighbors per port", NULL, cmd_maxneighs, + NULL); + + commands_new( + commands_new(commands_new(commands_new(commands_new(configure_system, "ip", + "IP related options", NULL, NULL, + NULL), + "management", "IP management related options", + NULL, NULL, NULL), + "pattern", "Set IP management pattern", NULL, NULL, NULL), + NULL, "IP management pattern (comma-separated list of wildcards)", NULL, + cmd_store_env_value, "management-pattern"), + NEWLINE, "Set IP management pattern", NULL, cmd_management, NULL); + commands_new( + commands_new(commands_new(commands_new(unconfigure_system, "ip", + "IP related options", NULL, NULL, NULL), + "management", "IP management related options", NULL, NULL, + NULL), + "pattern", "Delete any IP management pattern", NULL, NULL, NULL), + NEWLINE, "Delete any IP management pattern", NULL, cmd_management, NULL); + + commands_new(commands_new(commands_new(configure_interface, "pattern", + "Set active interface pattern", NULL, NULL, NULL), + NULL, "Interface pattern (comma-separated list of wildcards)", + NULL, cmd_store_env_value, "iface-pattern"), + NEWLINE, "Set active interface pattern", NULL, cmd_iface_pattern, NULL); + commands_new(commands_new(unconfigure_interface, "pattern", + "Delete any interface pattern", NULL, NULL, NULL), + NEWLINE, "Clear interface pattern", NULL, cmd_iface_pattern, NULL); + + commands_new( + commands_new(commands_new(configure_interface, "permanent", + "Set permanent interface pattern", NULL, NULL, NULL), + NULL, "Permanent interface pattern (comma-separated list of wildcards)", + NULL, cmd_store_env_value, "iface-pattern"), + NEWLINE, "Set permanent interface pattern", NULL, cmd_perm_iface_pattern, + NULL); + commands_new(commands_new(unconfigure_interface, "permanent", + "Clear permanent interface pattern", NULL, NULL, NULL), + NEWLINE, "Delete any interface pattern", NULL, cmd_perm_iface_pattern, + NULL); + + commands_new(commands_new(configure_interface, "description", + "Update interface descriptions with neighbor name", NULL, NULL, + NULL), + NEWLINE, "Update interface descriptions with neighbor name", NULL, + cmd_update_descriptions, "enable"); + commands_new(commands_new(unconfigure_interface, "description", + "Don't update interface descriptions with neighbor name", NULL, + NULL, NULL), + NEWLINE, "Don't update interface descriptions with neighbor name", NULL, + cmd_update_descriptions, NULL); + + commands_new(commands_new(configure_interface, "promiscuous", + "Enable promiscuous mode on managed interfaces", NULL, NULL, + NULL), + NEWLINE, "Enable promiscuous mode on managed interfaces", NULL, + cmd_iface_promisc, "enable"); + commands_new(commands_new(unconfigure_interface, "promiscuous", + "Don't enable promiscuous mode on managed interfaces", NULL, + NULL, NULL), + NEWLINE, "Don't enable promiscuous mode on managed interfaces", NULL, + cmd_iface_promisc, NULL); + + register_commands_capabilities(configure_system, unconfigure_system); + register_commands_srcmac_type(configure_system); +} |