From: Vincent Bernat Date: Tue, 22 Jan 2013 21:49:33 +0000 (+0100) Subject: lldpcli: split actions.c in several files X-Git-Tag: 0.7.2~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e15f96d2ae0e425eccfdafff7800ac420ffab0ea;p=thirdparty%2Flldpd.git lldpcli: split actions.c in several files We need `configure` to be more modulable. --- diff --git a/src/client/Makefile.am b/src/client/Makefile.am index 8d768bae..cd2b4f97 100644 --- a/src/client/Makefile.am +++ b/src/client/Makefile.am @@ -6,7 +6,8 @@ install-exec-local: lldpcli uninstall-local: cd $(DESTDIR)$(sbindir) && rm -f lldpctl -lldpcli_SOURCES = client.h lldpcli.c display.c actions.c \ +lldpcli_SOURCES = client.h lldpcli.c display.c \ + conf.c conf-med.c conf-dot3.c conf-power.c \ commands.c show.c \ misc.c tokenizer.c \ writer.h text_writer.c kv_writer.c diff --git a/src/client/client.h b/src/client/client.h index 0e1d73c6..459e4049 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -92,6 +92,8 @@ int cmd_store_env_value_and_pop2(struct lldpctl_conn_t *, struct writer *, struct cmd_env *, void *); int cmd_store_env_value_and_pop3(struct lldpctl_conn_t *, struct writer *, struct cmd_env *, void *); +int cmd_store_something_env_value_and_pop2(const char *, struct cmd_env *, + void *); lldpctl_atom_t* cmd_iterate_on_interfaces(struct lldpctl_conn_t *, struct cmd_env *); void cmd_restrict_ports(struct cmd_node *); @@ -114,8 +116,12 @@ void display_configuration(lldpctl_conn_t *, struct writer *); void register_commands_show(struct cmd_node *); void register_commands_watch(struct cmd_node *); -/* actions.c */ +/* conf*.c */ void register_commands_configure(struct cmd_node *); +void register_commands_configure_med(struct cmd_node *); +void register_commands_configure_dot3(struct cmd_node *); +void register_commands_medpow(struct cmd_node *); +void register_commands_dot3pow(struct cmd_node *); /* tokenizer.c */ int tokenize_line(const char*, int*, char***); diff --git a/src/client/commands.c b/src/client/commands.c index 869ecdac..d16259ce 100644 --- a/src/client/commands.c +++ b/src/client/commands.c @@ -606,6 +606,13 @@ cmd_store_env_value_and_pop3(struct lldpctl_conn_t *conn, struct writer *w, return (cmdenv_put(env, key, cmdenv_arg(env)) != -1 && cmdenv_pop(env, 3) != -1); } +int +cmd_store_something_env_value_and_pop2(const char *what, + struct cmd_env *env, void *value) +{ + return (cmdenv_put(env, what, value) != -1 && + cmdenv_pop(env, 2) != -1); +} /** * Provide an iterator on all interfaces contained in "ports". diff --git a/src/client/conf-dot3.c b/src/client/conf-dot3.c new file mode 100644 index 00000000..5588f757 --- /dev/null +++ b/src/client/conf-dot3.c @@ -0,0 +1,35 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2013 Vincent Bernat + * + * 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 +#include + +#include "client.h" +#include "../log.h" + +/** + * Commands to configure dot3 + */ +void +register_commands_configure_dot3(struct cmd_node *configure) +{ + struct cmd_node *configure_dot3 = commands_new( + configure, + "dot3", "Dot3 configuration", + NULL, NULL, NULL); + register_commands_dot3pow(configure_dot3); +} diff --git a/src/client/actions.c b/src/client/conf-med.c similarity index 51% rename from src/client/actions.c rename to src/client/conf-med.c index 85af9dc3..4aef70c9 100644 --- a/src/client/actions.c +++ b/src/client/conf-med.c @@ -235,150 +235,6 @@ cmd_medpolicy(struct lldpctl_conn_t *conn, struct writer *w, return 1; } -static int -cmd_medpower(struct lldpctl_conn_t *conn, struct writer *w, - struct cmd_env *env, void *arg) -{ - log_debug("lldpctl", "set MED power"); - lldpctl_atom_t *iface; - while ((iface = cmd_iterate_on_interfaces(conn, env))) { - const char *name = lldpctl_atom_get_str(iface, lldpctl_k_interface_name); - lldpctl_atom_t *port = lldpctl_get_port(iface); - lldpctl_atom_t *med_power; - const char *what = NULL; - - med_power = lldpctl_atom_get(port, lldpctl_k_port_med_power); - if (med_power == NULL) { - log_warnx("lldpctl", "unable to set LLDP-MED power: support seems unavailable"); - goto end; - } - - if ((what = "device type", lldpctl_atom_set_str(med_power, - lldpctl_k_med_power_type, - cmdenv_get(env, "device-type"))) == NULL || - (what = "power source", lldpctl_atom_set_str(med_power, - lldpctl_k_med_power_source, - cmdenv_get(env, "source"))) == NULL || - (what = "power priority", lldpctl_atom_set_str(med_power, - lldpctl_k_med_power_priority, - cmdenv_get(env, "priority"))) == NULL || - (what = "power value", lldpctl_atom_set_str(med_power, - lldpctl_k_med_power_val, - cmdenv_get(env, "value"))) == NULL) - log_warnx("lldpctl", - "unable to set LLDP MED power value for %s on %s. %s.", - what, name, lldpctl_last_strerror(conn)); - else { - if (lldpctl_atom_set(port, lldpctl_k_port_med_power, - med_power) == NULL) { - log_warnx("lldpctl", "unable to set LLDP MED power on %s. %s.", - name, lldpctl_last_strerror(conn)); - } else - log_info("lldpctl", "LLDP-MED power has been set for port %s", - name); - } - - end: - lldpctl_atom_dec_ref(med_power); - lldpctl_atom_dec_ref(port); - } - return 1; -} - -static int -cmd_dot3power(struct lldpctl_conn_t *conn, struct writer *w, - struct cmd_env *env, void *arg) -{ - log_debug("lldpctl", "set dot3 power"); - lldpctl_atom_t *iface; - while ((iface = cmd_iterate_on_interfaces(conn, env))) { - const char *name = lldpctl_atom_get_str(iface, lldpctl_k_interface_name); - lldpctl_atom_t *port = lldpctl_get_port(iface); - lldpctl_atom_t *dot3_power; - const char *what = NULL; - int ok = 1; - - dot3_power = lldpctl_atom_get(port, lldpctl_k_port_dot3_power); - if (dot3_power == NULL) { - log_warnx("lldpctl", "unable to set Dot3 power: support seems unavailable"); - goto end; - } - - if ((what = "device type", lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_devicetype, - cmdenv_get(env, "device-type"))) == NULL || - /* Flags */ - (what = "supported flag", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_supported, - cmdenv_get(env, "supported")?1:0)) == NULL || - (what = "enabled flag", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_enabled, - cmdenv_get(env, "enabled")?1:0)) == NULL || - (what = "paircontrol flag", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_paircontrol, - cmdenv_get(env, "paircontrol")?1:0)) == NULL || - /* Powerpairs */ - (what = "power pairs", lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_pairs, - cmdenv_get(env, "powerpairs"))) == NULL || - /* Class */ - (what = "power class", cmdenv_get(env, "class")? - lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_class, - cmdenv_get(env, "class")): - lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_class, 0)) == NULL || - (what = "802.3at type", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_type, 0)) == NULL) { - log_warnx("lldpctl", - "unable to set LLDP Dot3 power value for %s on %s. %s.", - what, name, lldpctl_last_strerror(conn)); - ok = 0; - } else if (cmdenv_get(env, "typeat")) { - int typeat = cmdenv_get(env, "typeat")[0] - '0'; - const char *source = cmdenv_get(env, "source"); - if ((what = "802.3at type", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_type, - typeat)) == NULL || - (what = "source", lldpctl_atom_set_int(dot3_power, - lldpctl_k_dot3_power_source, - (!strcmp(source, "primary"))?LLDP_DOT3_POWER_SOURCE_PRIMARY: - (!strcmp(source, "backup"))? LLDP_DOT3_POWER_SOURCE_BACKUP: - (!strcmp(source, "pse"))? LLDP_DOT3_POWER_SOURCE_PSE: - (!strcmp(source, "local"))? LLDP_DOT3_POWER_SOURCE_LOCAL: - (!strcmp(source, "both"))? LLDP_DOT3_POWER_SOURCE_BOTH: - LLDP_DOT3_POWER_SOURCE_UNKNOWN)) == NULL || - (what = "priority", lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_priority, - cmdenv_get(env, "priority"))) == NULL || - (what = "requested power", lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_requested, - cmdenv_get(env, "requested"))) == NULL || - (what = "allocated power", lldpctl_atom_set_str(dot3_power, - lldpctl_k_dot3_power_allocated, - cmdenv_get(env, "allocated"))) == NULL) { - log_warnx("lldpctl", "unable to set LLDP Dot3 power value for %s on %s. %s.", - what, name, lldpctl_last_strerror(conn)); - ok = 0; - } - } - if (ok) { - if (lldpctl_atom_set(port, lldpctl_k_port_dot3_power, - dot3_power) == NULL) { - log_warnx("lldpctl", "unable to set LLDP Dot3 power on %s. %s.", - name, lldpctl_last_strerror(conn)); - } else - log_info("lldpctl", "LLDP Dot3 power has been set for port %s", - name); - } - - end: - lldpctl_atom_dec_ref(dot3_power); - lldpctl_atom_dec_ref(port); - } - return 1; -} - /** * Register `configure med location coordinate` commands. */ @@ -517,31 +373,12 @@ cmd_check_application_but_no(struct cmd_env *env, void *arg) return 1; } static int -cmd_store_something_env_value_and_pop2(const char *what, - struct cmd_env *env, void *value) -{ - return (cmdenv_put(env, what, value) != -1 && - cmdenv_pop(env, 2) != -1); -} -static int cmd_store_app_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, void *value) { return cmd_store_something_env_value_and_pop2("application", env, value); } static int -cmd_store_powerpairs_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, - struct cmd_env *env, void *value) -{ - return cmd_store_something_env_value_and_pop2("powerpairs", env, value); -} -static int -cmd_store_class_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, - struct cmd_env *env, void *value) -{ - return cmd_store_something_env_value_and_pop2("class", env, value); -} -static int cmd_store_prio_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, void *value) { @@ -619,294 +456,18 @@ register_commands_medpol(struct cmd_node *configure_med) } } -static int -cmd_check_type_but_no(struct cmd_env *env, void *arg) -{ - const char *what = arg; - if (!cmdenv_get(env, "device-type")) return 0; - if (cmdenv_get(env, what)) return 0; - return 1; -} -static int -cmd_check_typeat_but_no(struct cmd_env *env, void *arg) -{ - const char *what = arg; - if (!cmdenv_get(env, "typeat")) return 0; - if (cmdenv_get(env, what)) return 0; - return 1; -} -static int -cmd_check_type(struct cmd_env *env, const char *type) -{ - const char *etype = cmdenv_get(env, "device-type"); - if (!etype) return 0; - return (!strcmp(type, etype)); -} -static int -cmd_check_pse(struct cmd_env *env, void *arg) -{ - return cmd_check_type(env, "pse"); -} -static int -cmd_check_pd(struct cmd_env *env, void *arg) -{ - return cmd_check_type(env, "pd"); -} - -static void -register_commands_pow_source(struct cmd_node *source) -{ - commands_new(source, - "unknown", "Unknown power source", - NULL, cmd_store_env_value_and_pop2, "source"); - commands_new(source, - "primary", "Primary power source", - cmd_check_pse, cmd_store_env_value_and_pop2, "source"); - commands_new(source, - "backup", "Backup power source", - cmd_check_pse, cmd_store_env_value_and_pop2, "source"); - commands_new(source, - "pse", "Power source is PSE", - cmd_check_pd, cmd_store_env_value_and_pop2, "source"); - commands_new(source, - "local", "Local power source", - cmd_check_pd, cmd_store_env_value_and_pop2, "source"); - commands_new(source, - "both", "Both PSE and local source available", - cmd_check_pd, cmd_store_env_value_and_pop2, "source"); -} - -static void -register_commands_pow_priority(struct cmd_node *priority, int key) -{ - for (lldpctl_map_t *prio_map = - lldpctl_key_get_map(key); - prio_map->string; - prio_map++) { - char *tag = strdup(totag(prio_map->string)); /* TODO: memory leak, happens once */ - commands_new( - priority, - tag, - prio_map->string, - NULL, cmd_store_prio_env_value_and_pop2, prio_map->string); - } -} - -/** - * Register `configure med power` commands. - */ -static void -register_commands_medpow(struct cmd_node *configure_med) -{ - struct cmd_node *configure_medpower = commands_new( - configure_med, - "power", "MED power configuration", - NULL, NULL, NULL); - - commands_new( - configure_medpower, - NEWLINE, "Apply new MED power configuration", - cmd_check_env, cmd_medpower, "device-type,source,priority,value"); - - /* Type: PSE or PD */ - commands_new( - configure_medpower, - "pd", "MED power consumer", - cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); - commands_new( - configure_medpower, - "pse", "MED power provider", - cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); - - /* Source */ - struct cmd_node *source = commands_new( - configure_medpower, - "source", "MED power source", - cmd_check_type_but_no, NULL, "source"); - register_commands_pow_source(source); - - /* Priority */ - struct cmd_node *priority = commands_new( - configure_medpower, - "priority", "MED power priority", - cmd_check_type_but_no, NULL, "priority"); - register_commands_pow_priority(priority, lldpctl_k_med_power_priority); - - /* Value */ - commands_new( - commands_new(configure_medpower, - "value", "MED power value", - cmd_check_type_but_no, NULL, "value"), - NULL, "MED power value in milliwatts", - NULL, cmd_store_env_value_and_pop2, "value"); -} - -static int -cmd_check_env_power(struct cmd_env *env, void *nothing) -{ - /* We need type and powerpair but if we have typeat, we also request - * source, priority, requested and allocated. */ - if (!cmdenv_get(env, "device-type")) return 0; - if (!cmdenv_get(env, "powerpairs")) return 0; - if (cmdenv_get(env, "typeat")) { - return (!!cmdenv_get(env, "source") && - !!cmdenv_get(env, "priority") && - !!cmdenv_get(env, "requested") && - !!cmdenv_get(env, "allocated")); - } - return 1; -} - /** - * Register `configure med dot3` commands. - */ -static void -register_commands_dot3pow(struct cmd_node *configure_dot3) -{ - struct cmd_node *configure_dot3power = commands_new( - configure_dot3, - "power", "Dot3 power configuration", - NULL, NULL, NULL); - - commands_new( - configure_dot3power, - NEWLINE, "Apply new Dot3 power configuration", - cmd_check_env_power, cmd_dot3power, NULL); - - /* Type: PSE or PD */ - commands_new( - configure_dot3power, - "pd", "Dot3 power consumer", - cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); - commands_new( - configure_dot3power, - "pse", "Dot3 power provider", - cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); - - /* Flags */ - commands_new( - configure_dot3power, - "supported", "MDI power support present", - cmd_check_type_but_no, cmd_store_env_and_pop, "supported"); - commands_new( - configure_dot3power, - "enabled", "MDI power support enabled", - cmd_check_type_but_no, cmd_store_env_and_pop, "enabled"); - commands_new( - configure_dot3power, - "paircontrol", "MDI power pair can be selected", - cmd_check_type_but_no, cmd_store_env_and_pop, "paircontrol"); - - /* Power pairs */ - struct cmd_node *powerpairs = commands_new( - configure_dot3power, - "powerpairs", "Which pairs are currently used for power (mandatory)", - cmd_check_type_but_no, NULL, "powerpairs"); - for (lldpctl_map_t *pp_map = - lldpctl_key_get_map(lldpctl_k_dot3_power_pairs); - pp_map->string; - pp_map++) { - commands_new( - powerpairs, - pp_map->string, - pp_map->string, - NULL, cmd_store_powerpairs_env_value_and_pop2, pp_map->string); - } - - /* Class */ - struct cmd_node *class = commands_new( - configure_dot3power, - "class", "Power class", - cmd_check_type_but_no, NULL, "class"); - for (lldpctl_map_t *class_map = - lldpctl_key_get_map(lldpctl_k_dot3_power_class); - class_map->string; - class_map++) { - const char *tag = strdup(totag(class_map->string)); - commands_new( - class, - tag, - class_map->string, - NULL, cmd_store_class_env_value_and_pop2, class_map->string); - } - - /* 802.3at type */ - struct cmd_node *typeat = commands_new( - configure_dot3power, - "type", "802.3at device type", - cmd_check_type_but_no, NULL, "typeat"); - commands_new(typeat, - "1", "802.3at type 1", - NULL, cmd_store_env_value_and_pop2, "typeat"); - commands_new(typeat, - "2", "802.3at type 2", - NULL, cmd_store_env_value_and_pop2, "typeat"); - - /* Source */ - struct cmd_node *source = commands_new( - configure_dot3power, - "source", "802.3at dot3 power source (mandatory)", - cmd_check_typeat_but_no, NULL, "source"); - register_commands_pow_source(source); - - /* Priority */ - struct cmd_node *priority = commands_new( - configure_dot3power, - "priority", "802.3at dot3 power priority (mandatory)", - cmd_check_typeat_but_no, NULL, "priority"); - register_commands_pow_priority(priority, lldpctl_k_dot3_power_priority); - - /* Values */ - commands_new( - commands_new(configure_dot3power, - "requested", "802.3at dot3 power value requested (mandatory)", - cmd_check_typeat_but_no, NULL, "requested"), - NULL, "802.3at power value requested in milliwatts", - NULL, cmd_store_env_value_and_pop2, "requested"); - commands_new( - commands_new(configure_dot3power, - "allocated", "802.3at dot3 power value allocated (mandatory)", - cmd_check_typeat_but_no, NULL, "allocated"), - NULL, "802.3at power value allocated in milliwatts", - NULL, cmd_store_env_value_and_pop2, "allocated"); -} - -/** - * Register `configure` and `no configure` commands. + * Register "configure med *" */ void -register_commands_configure(struct cmd_node *root) +register_commands_configure_med(struct cmd_node *configure) { - int has_med = (lldpctl_key_get_map( - lldpctl_k_med_policy_type)[0].string != NULL); - int has_dot3 = (lldpctl_key_get_map( - lldpctl_k_dot3_power_class)[0].string != NULL); - if (!has_med && !has_dot3) return; - - struct cmd_node *configure = commands_new( - root, - "configure", - "Change system settings", + struct cmd_node *configure_med = commands_new( + configure, + "med", "MED configuration", NULL, NULL, NULL); - cmd_restrict_ports(configure); - - if (has_med) { - struct cmd_node *configure_med = commands_new( - configure, - "med", "MED configuration", - NULL, NULL, NULL); - register_commands_medloc(configure_med); - register_commands_medpol(configure_med); - register_commands_medpow(configure_med); - } - - if (has_dot3) { - struct cmd_node *configure_dot3 = commands_new( - configure, - "dot3", "Dot3 configuration", - NULL, NULL, NULL); - - register_commands_dot3pow(configure_dot3); - } + register_commands_medloc(configure_med); + register_commands_medpol(configure_med); + register_commands_medpow(configure_med); } diff --git a/src/client/conf-power.c b/src/client/conf-power.c new file mode 100644 index 00000000..b529a764 --- /dev/null +++ b/src/client/conf-power.c @@ -0,0 +1,437 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2013 Vincent Bernat + * + * 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 +#include + +#include "client.h" +#include "../log.h" + +static int +cmd_medpower(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *arg) +{ + log_debug("lldpctl", "set MED power"); + lldpctl_atom_t *iface; + while ((iface = cmd_iterate_on_interfaces(conn, env))) { + const char *name = lldpctl_atom_get_str(iface, lldpctl_k_interface_name); + lldpctl_atom_t *port = lldpctl_get_port(iface); + lldpctl_atom_t *med_power; + const char *what = NULL; + + med_power = lldpctl_atom_get(port, lldpctl_k_port_med_power); + if (med_power == NULL) { + log_warnx("lldpctl", "unable to set LLDP-MED power: support seems unavailable"); + goto end; + } + + if ((what = "device type", lldpctl_atom_set_str(med_power, + lldpctl_k_med_power_type, + cmdenv_get(env, "device-type"))) == NULL || + (what = "power source", lldpctl_atom_set_str(med_power, + lldpctl_k_med_power_source, + cmdenv_get(env, "source"))) == NULL || + (what = "power priority", lldpctl_atom_set_str(med_power, + lldpctl_k_med_power_priority, + cmdenv_get(env, "priority"))) == NULL || + (what = "power value", lldpctl_atom_set_str(med_power, + lldpctl_k_med_power_val, + cmdenv_get(env, "value"))) == NULL) + log_warnx("lldpctl", + "unable to set LLDP MED power value for %s on %s. %s.", + what, name, lldpctl_last_strerror(conn)); + else { + if (lldpctl_atom_set(port, lldpctl_k_port_med_power, + med_power) == NULL) { + log_warnx("lldpctl", "unable to set LLDP MED power on %s. %s.", + name, lldpctl_last_strerror(conn)); + } else + log_info("lldpctl", "LLDP-MED power has been set for port %s", + name); + } + + end: + lldpctl_atom_dec_ref(med_power); + lldpctl_atom_dec_ref(port); + } + return 1; +} + +static int +cmd_store_powerpairs_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *value) +{ + return cmd_store_something_env_value_and_pop2("powerpairs", env, value); +} +static int +cmd_store_class_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *value) +{ + return cmd_store_something_env_value_and_pop2("class", env, value); +} +static int +cmd_store_prio_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *value) +{ + return cmd_store_something_env_value_and_pop2("priority", env, value); +} + +static int +cmd_dot3power(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *arg) +{ + log_debug("lldpctl", "set dot3 power"); + lldpctl_atom_t *iface; + while ((iface = cmd_iterate_on_interfaces(conn, env))) { + const char *name = lldpctl_atom_get_str(iface, lldpctl_k_interface_name); + lldpctl_atom_t *port = lldpctl_get_port(iface); + lldpctl_atom_t *dot3_power; + const char *what = NULL; + int ok = 1; + + dot3_power = lldpctl_atom_get(port, lldpctl_k_port_dot3_power); + if (dot3_power == NULL) { + log_warnx("lldpctl", "unable to set Dot3 power: support seems unavailable"); + goto end; + } + + if ((what = "device type", lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_devicetype, + cmdenv_get(env, "device-type"))) == NULL || + /* Flags */ + (what = "supported flag", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_supported, + cmdenv_get(env, "supported")?1:0)) == NULL || + (what = "enabled flag", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_enabled, + cmdenv_get(env, "enabled")?1:0)) == NULL || + (what = "paircontrol flag", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_paircontrol, + cmdenv_get(env, "paircontrol")?1:0)) == NULL || + /* Powerpairs */ + (what = "power pairs", lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_pairs, + cmdenv_get(env, "powerpairs"))) == NULL || + /* Class */ + (what = "power class", cmdenv_get(env, "class")? + lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_class, + cmdenv_get(env, "class")): + lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_class, 0)) == NULL || + (what = "802.3at type", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_type, 0)) == NULL) { + log_warnx("lldpctl", + "unable to set LLDP Dot3 power value for %s on %s. %s.", + what, name, lldpctl_last_strerror(conn)); + ok = 0; + } else if (cmdenv_get(env, "typeat")) { + int typeat = cmdenv_get(env, "typeat")[0] - '0'; + const char *source = cmdenv_get(env, "source"); + if ((what = "802.3at type", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_type, + typeat)) == NULL || + (what = "source", lldpctl_atom_set_int(dot3_power, + lldpctl_k_dot3_power_source, + (!strcmp(source, "primary"))?LLDP_DOT3_POWER_SOURCE_PRIMARY: + (!strcmp(source, "backup"))? LLDP_DOT3_POWER_SOURCE_BACKUP: + (!strcmp(source, "pse"))? LLDP_DOT3_POWER_SOURCE_PSE: + (!strcmp(source, "local"))? LLDP_DOT3_POWER_SOURCE_LOCAL: + (!strcmp(source, "both"))? LLDP_DOT3_POWER_SOURCE_BOTH: + LLDP_DOT3_POWER_SOURCE_UNKNOWN)) == NULL || + (what = "priority", lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_priority, + cmdenv_get(env, "priority"))) == NULL || + (what = "requested power", lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_requested, + cmdenv_get(env, "requested"))) == NULL || + (what = "allocated power", lldpctl_atom_set_str(dot3_power, + lldpctl_k_dot3_power_allocated, + cmdenv_get(env, "allocated"))) == NULL) { + log_warnx("lldpctl", "unable to set LLDP Dot3 power value for %s on %s. %s.", + what, name, lldpctl_last_strerror(conn)); + ok = 0; + } + } + if (ok) { + if (lldpctl_atom_set(port, lldpctl_k_port_dot3_power, + dot3_power) == NULL) { + log_warnx("lldpctl", "unable to set LLDP Dot3 power on %s. %s.", + name, lldpctl_last_strerror(conn)); + } else + log_info("lldpctl", "LLDP Dot3 power has been set for port %s", + name); + } + + end: + lldpctl_atom_dec_ref(dot3_power); + lldpctl_atom_dec_ref(port); + } + return 1; +} + +static int +cmd_check_type_but_no(struct cmd_env *env, void *arg) +{ + const char *what = arg; + if (!cmdenv_get(env, "device-type")) return 0; + if (cmdenv_get(env, what)) return 0; + return 1; +} +static int +cmd_check_typeat_but_no(struct cmd_env *env, void *arg) +{ + const char *what = arg; + if (!cmdenv_get(env, "typeat")) return 0; + if (cmdenv_get(env, what)) return 0; + return 1; +} +static int +cmd_check_type(struct cmd_env *env, const char *type) +{ + const char *etype = cmdenv_get(env, "device-type"); + if (!etype) return 0; + return (!strcmp(type, etype)); +} +static int +cmd_check_pse(struct cmd_env *env, void *arg) +{ + return cmd_check_type(env, "pse"); +} +static int +cmd_check_pd(struct cmd_env *env, void *arg) +{ + return cmd_check_type(env, "pd"); +} + +static void +register_commands_pow_source(struct cmd_node *source) +{ + commands_new(source, + "unknown", "Unknown power source", + NULL, cmd_store_env_value_and_pop2, "source"); + commands_new(source, + "primary", "Primary power source", + cmd_check_pse, cmd_store_env_value_and_pop2, "source"); + commands_new(source, + "backup", "Backup power source", + cmd_check_pse, cmd_store_env_value_and_pop2, "source"); + commands_new(source, + "pse", "Power source is PSE", + cmd_check_pd, cmd_store_env_value_and_pop2, "source"); + commands_new(source, + "local", "Local power source", + cmd_check_pd, cmd_store_env_value_and_pop2, "source"); + commands_new(source, + "both", "Both PSE and local source available", + cmd_check_pd, cmd_store_env_value_and_pop2, "source"); +} + +static void +register_commands_pow_priority(struct cmd_node *priority, int key) +{ + for (lldpctl_map_t *prio_map = + lldpctl_key_get_map(key); + prio_map->string; + prio_map++) { + char *tag = strdup(totag(prio_map->string)); /* TODO: memory leak, happens once */ + commands_new( + priority, + tag, + prio_map->string, + NULL, cmd_store_prio_env_value_and_pop2, prio_map->string); + } +} + +/** + * Register `configure med power` commands. + */ +void +register_commands_medpow(struct cmd_node *configure_med) +{ + struct cmd_node *configure_medpower = commands_new( + configure_med, + "power", "MED power configuration", + NULL, NULL, NULL); + + commands_new( + configure_medpower, + NEWLINE, "Apply new MED power configuration", + cmd_check_env, cmd_medpower, "device-type,source,priority,value"); + + /* Type: PSE or PD */ + commands_new( + configure_medpower, + "pd", "MED power consumer", + cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); + commands_new( + configure_medpower, + "pse", "MED power provider", + cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); + + /* Source */ + struct cmd_node *source = commands_new( + configure_medpower, + "source", "MED power source", + cmd_check_type_but_no, NULL, "source"); + register_commands_pow_source(source); + + /* Priority */ + struct cmd_node *priority = commands_new( + configure_medpower, + "priority", "MED power priority", + cmd_check_type_but_no, NULL, "priority"); + register_commands_pow_priority(priority, lldpctl_k_med_power_priority); + + /* Value */ + commands_new( + commands_new(configure_medpower, + "value", "MED power value", + cmd_check_type_but_no, NULL, "value"), + NULL, "MED power value in milliwatts", + NULL, cmd_store_env_value_and_pop2, "value"); +} + +static int +cmd_check_env_power(struct cmd_env *env, void *nothing) +{ + /* We need type and powerpair but if we have typeat, we also request + * source, priority, requested and allocated. */ + if (!cmdenv_get(env, "device-type")) return 0; + if (!cmdenv_get(env, "powerpairs")) return 0; + if (cmdenv_get(env, "typeat")) { + return (!!cmdenv_get(env, "source") && + !!cmdenv_get(env, "priority") && + !!cmdenv_get(env, "requested") && + !!cmdenv_get(env, "allocated")); + } + return 1; +} + +/** + * Register `configure med dot3` commands. + */ +void +register_commands_dot3pow(struct cmd_node *configure_dot3) +{ + struct cmd_node *configure_dot3power = commands_new( + configure_dot3, + "power", "Dot3 power configuration", + NULL, NULL, NULL); + + commands_new( + configure_dot3power, + NEWLINE, "Apply new Dot3 power configuration", + cmd_check_env_power, cmd_dot3power, NULL); + + /* Type: PSE or PD */ + commands_new( + configure_dot3power, + "pd", "Dot3 power consumer", + cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); + commands_new( + configure_dot3power, + "pse", "Dot3 power provider", + cmd_check_no_env, cmd_store_env_value_and_pop, "device-type"); + + /* Flags */ + commands_new( + configure_dot3power, + "supported", "MDI power support present", + cmd_check_type_but_no, cmd_store_env_and_pop, "supported"); + commands_new( + configure_dot3power, + "enabled", "MDI power support enabled", + cmd_check_type_but_no, cmd_store_env_and_pop, "enabled"); + commands_new( + configure_dot3power, + "paircontrol", "MDI power pair can be selected", + cmd_check_type_but_no, cmd_store_env_and_pop, "paircontrol"); + + /* Power pairs */ + struct cmd_node *powerpairs = commands_new( + configure_dot3power, + "powerpairs", "Which pairs are currently used for power (mandatory)", + cmd_check_type_but_no, NULL, "powerpairs"); + for (lldpctl_map_t *pp_map = + lldpctl_key_get_map(lldpctl_k_dot3_power_pairs); + pp_map->string; + pp_map++) { + commands_new( + powerpairs, + pp_map->string, + pp_map->string, + NULL, cmd_store_powerpairs_env_value_and_pop2, pp_map->string); + } + + /* Class */ + struct cmd_node *class = commands_new( + configure_dot3power, + "class", "Power class", + cmd_check_type_but_no, NULL, "class"); + for (lldpctl_map_t *class_map = + lldpctl_key_get_map(lldpctl_k_dot3_power_class); + class_map->string; + class_map++) { + const char *tag = strdup(totag(class_map->string)); + commands_new( + class, + tag, + class_map->string, + NULL, cmd_store_class_env_value_and_pop2, class_map->string); + } + + /* 802.3at type */ + struct cmd_node *typeat = commands_new( + configure_dot3power, + "type", "802.3at device type", + cmd_check_type_but_no, NULL, "typeat"); + commands_new(typeat, + "1", "802.3at type 1", + NULL, cmd_store_env_value_and_pop2, "typeat"); + commands_new(typeat, + "2", "802.3at type 2", + NULL, cmd_store_env_value_and_pop2, "typeat"); + + /* Source */ + struct cmd_node *source = commands_new( + configure_dot3power, + "source", "802.3at dot3 power source (mandatory)", + cmd_check_typeat_but_no, NULL, "source"); + register_commands_pow_source(source); + + /* Priority */ + struct cmd_node *priority = commands_new( + configure_dot3power, + "priority", "802.3at dot3 power priority (mandatory)", + cmd_check_typeat_but_no, NULL, "priority"); + register_commands_pow_priority(priority, lldpctl_k_dot3_power_priority); + + /* Values */ + commands_new( + commands_new(configure_dot3power, + "requested", "802.3at dot3 power value requested (mandatory)", + cmd_check_typeat_but_no, NULL, "requested"), + NULL, "802.3at power value requested in milliwatts", + NULL, cmd_store_env_value_and_pop2, "requested"); + commands_new( + commands_new(configure_dot3power, + "allocated", "802.3at dot3 power value allocated (mandatory)", + cmd_check_typeat_but_no, NULL, "allocated"), + NULL, "802.3at power value allocated in milliwatts", + NULL, cmd_store_env_value_and_pop2, "allocated"); +} diff --git a/src/client/conf.c b/src/client/conf.c new file mode 100644 index 00000000..3a9b8df8 --- /dev/null +++ b/src/client/conf.c @@ -0,0 +1,46 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2013 Vincent Bernat + * + * 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 +#include + +#include "client.h" +#include "../log.h" + + +/** + * Register `configure` and `no configure` commands. + */ +void +register_commands_configure(struct cmd_node *root) +{ + int has_med = (lldpctl_key_get_map( + lldpctl_k_med_policy_type)[0].string != NULL); + int has_dot3 = (lldpctl_key_get_map( + lldpctl_k_dot3_power_class)[0].string != NULL); + if (!has_med && !has_dot3) return; + + struct cmd_node *configure = commands_new( + root, + "configure", + "Change system settings", + NULL, NULL, NULL); + cmd_restrict_ports(configure); + + if (has_med) register_commands_configure_med(configure); + if (has_dot3) register_commands_configure_dot3(configure); +}