From: Vincent Bernat Date: Fri, 31 Aug 2012 15:35:05 +0000 (+0200) Subject: lldpctl: allow to display global configuration of lldpd X-Git-Tag: 0.6.1~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8729d69f28a760d45efe303b63de99c6589f4573;p=thirdparty%2Flldpd.git lldpctl: allow to display global configuration of lldpd --- diff --git a/man/lldpctl.8 b/man/lldpctl.8 index 436e7b24..efd305e1 100644 --- a/man/lldpctl.8 +++ b/man/lldpctl.8 @@ -21,7 +21,7 @@ .Nd control LLDP daemon .Sh SYNOPSIS .Nm -.Op Fl advw +.Op Fl advwC .Op Fl L Ar location .Op Fl P Ar policy .Op Fl O Ar poe @@ -52,6 +52,8 @@ version. Display all remote ports, including those hidden by the smart filter. .It Fl w Monitor neighbor changes. Each changed neighbor will be displayed. +.It Fl C +Display global configuration of lldpd daemon. .It Fl f Ar format Choose the output format. Currently .Em plain , diff --git a/src/client/client.h b/src/client/client.h index c57b7e11..0e0e4ba8 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -26,12 +26,13 @@ #include "../lldp-const.h" #include "writer.h" -#define LLDPCTL_ARGS "hdvaf:L:P:O:o:w" +#define LLDPCTL_ARGS "hdvaf:L:P:O:o:wC" /* display.c */ void display_interfaces(lldpctl_conn_t *, struct writer *, int, int, char **); void display_interface(lldpctl_conn_t *, struct writer *, int, lldpctl_atom_t *, lldpctl_atom_t *); +void display_configuration(lldpctl_conn_t *, struct writer *); /* actions.c */ void modify_interfaces(lldpctl_conn_t *, int, char **, int); diff --git a/src/client/display.c b/src/client/display.c index e29bad1e..fed28ae1 100644 --- a/src/client/display.c +++ b/src/client/display.c @@ -552,7 +552,8 @@ display_interfaces(lldpctl_conn_t *conn, struct writer *w, int hidden, iface_list = lldpctl_get_interfaces(conn); if (!iface_list) { - LLOG_WARNX("not able to get the list of interfaces: %s", lldpctl_strerror(lldpctl_last_error(conn))); + LLOG_WARNX("not able to get the list of interfaces. %s", + lldpctl_last_strerror(conn)); return; } @@ -578,3 +579,52 @@ display_interfaces(lldpctl_conn_t *conn, struct writer *w, int hidden, lldpctl_atom_dec_ref(iface_list); tag_end(w); } + +const char * +N(const char *str) { + if (str == NULL || strlen(str) == 0) return "(none)"; + return str; +} + +void +display_configuration(lldpctl_conn_t *conn, struct writer *w) +{ + lldpctl_atom_t *configuration; + + configuration = lldpctl_get_configuration(conn); + if (!configuration) { + LLOG_WARNX("not able to get configuration. %s", + lldpctl_last_strerror(conn)); + return; + } + + tag_start(w, "configuration", "Global configuration"); + tag_start(w, "config", "Configuration"); + + tag_datatag(w, "tx-delay", "Transmit delay", + lldpctl_atom_get_str(configuration, lldpctl_k_config_delay)); + tag_datatag(w, "rx-only", "Receive mode", + lldpctl_atom_get_int(configuration, lldpctl_k_config_receiveonly)? + "yes":"no"); + tag_datatag(w, "mgmt-pattern", "Pattern for management addresses", + N(lldpctl_atom_get_str(configuration, lldpctl_k_config_mgmt_pattern))); + tag_datatag(w, "iface-pattern", "Interface pattern", + N(lldpctl_atom_get_str(configuration, lldpctl_k_config_iface_pattern))); + tag_datatag(w, "cid-pattern", "Interface pattern for chassis ID", + N(lldpctl_atom_get_str(configuration, lldpctl_k_config_cid_pattern))); + tag_datatag(w, "description", "Override description with", + N(lldpctl_atom_get_str(configuration, lldpctl_k_config_description))); + tag_datatag(w, "platform", "Override platform with", + N(lldpctl_atom_get_str(configuration, lldpctl_k_config_platform))); + tag_datatag(w, "advertise-version", "Advertise version", + lldpctl_atom_get_int(configuration, lldpctl_k_config_advertise_version)? + "yes":"no"); + tag_datatag(w, "lldpmed-no-inventory", "Disable LLDP-MED inventory", + (lldpctl_atom_get_int(configuration, lldpctl_k_config_lldpmed_noinventory) == 0)? + "no":"yes"); + + tag_end(w); + tag_end(w); + + lldpctl_atom_dec_ref(configuration); +} diff --git a/src/client/lldpctl.c b/src/client/lldpctl.c index e848d05a..f1e13d2e 100644 --- a/src/client/lldpctl.c +++ b/src/client/lldpctl.c @@ -49,6 +49,7 @@ usage(void) fprintf(stderr, "-d Enable more debugging information.\n"); fprintf(stderr, "-a Display all remote ports, including hidden ones.\n"); fprintf(stderr, "-w Watch for changes.\n"); + fprintf(stderr, "-C Display global configuration of lldpd.\n"); fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n"); fprintf(stderr, "-L location Enable the transmission of LLDP-MED location TLV for the\n"); fprintf(stderr, " given interfaces. Can be repeated to enable the transmission\n"); @@ -114,7 +115,7 @@ main(int argc, char *argv[]) { int ch, debug = 1; char *fmt = "plain"; - int action = 0, hidden = 0, watch = 0; + int action = 0, hidden = 0, watch = 0, configuration = 0; lldpctl_conn_t *conn; struct cbargs args; @@ -146,6 +147,9 @@ main(int argc, char *argv[]) case 'w': watch = 1; break; + case 'C': + configuration = 1; + break; default: usage(); } @@ -172,36 +176,35 @@ main(int argc, char *argv[]) } do { - if (!action || watch) { - if (strcmp(fmt, "plain") == 0) { - args.w = txt_init(stdout); - } else if (strcmp(fmt, "keyvalue") == 0) { - args.w = kv_init(stdout); - } + if (strcmp(fmt, "plain") == 0) { + args.w = txt_init(stdout); + } else if (strcmp(fmt, "keyvalue") == 0) { + args.w = kv_init(stdout); + } #ifdef USE_XML - else if (strcmp(fmt,"xml") == 0 ) { - args.w = xml_init(stdout); - } + else if (strcmp(fmt,"xml") == 0 ) { + args.w = xml_init(stdout); + } #endif - else { - args.w = txt_init(stdout); - } + else { + args.w = txt_init(stdout); } - if (!watch && !action) { + if (!watch && !action && !configuration) { display_interfaces(conn, args.w, hidden, argc, argv); - args.w->finish(args.w); - } else if (!watch) { + } else if (action) { modify_interfaces(conn, argc, argv, optind); - } else { + } else if (watch) { if (lldpctl_watch(conn) < 0) { LLOG_WARNX("unable to watch for neighbors. %s", lldpctl_last_strerror(conn)); watch = 0; } - args.w->finish(args.w); + } else if (configuration) { + display_configuration(conn, args.w); } + args.w->finish(args.w); } while (watch); lldpctl_release(conn); diff --git a/src/client/writer.h b/src/client/writer.h index cedaee10..71713fb5 100644 --- a/src/client/writer.h +++ b/src/client/writer.h @@ -33,7 +33,7 @@ struct writer { #define tag_attr(w,...) w->attr(w,## __VA_ARGS__) #define tag_data(w,...) w->data(w,## __VA_ARGS__) #define tag_end(w,...) w->end(w,## __VA_ARGS__) -#define tag_datatag(w,t,d,v) do { if (!v) break; w->start(w,t,d); w->data(w,v); w->end(w); } while(0); +#define tag_datatag(w,t,d,v) do { if (!(v)) break; w->start(w,t,d); w->data(w,v); w->end(w); } while(0); extern struct writer * txt_init( FILE * ); extern struct writer * kv_init( FILE * ); diff --git a/src/ctl.h b/src/ctl.h index 01e88b30..5b47efd1 100644 --- a/src/ctl.h +++ b/src/ctl.h @@ -25,6 +25,7 @@ enum hmsg_type { NONE, + GET_CONFIG, /* Get global configuration */ GET_INTERFACES, /* Get list of interfaces */ GET_INTERFACE, /* Get all information related to an interface */ SET_PORT, /* Set port-related information (location, power, policy) */ diff --git a/src/daemon/client.c b/src/daemon/client.c index 94fe9a40..d060d2fe 100644 --- a/src/daemon/client.c +++ b/src/daemon/client.c @@ -26,6 +26,20 @@ client_handle_none(struct lldpd *cfg, enum hmsg_type *type, return 0; } +/* Return the global configuration */ +static int +client_handle_get_configuration(struct lldpd *cfg, enum hmsg_type *type, + void *input, int input_len, void **output, int *subscribed) +{ + ssize_t output_len; + output_len = marshal_serialize(lldpd_config, &cfg->g_config, output); + if (output_len <= 0) { + output_len = 0; + *type = NONE; + } + return output_len; +} + /* Return the list of interfaces. Input: nothing. Output: list of interface names (lldpd_interface_list) @@ -218,6 +232,7 @@ struct client_handle { static struct client_handle client_handles[] = { { NONE, client_handle_none }, + { GET_CONFIG, client_handle_get_configuration }, { GET_INTERFACES, client_handle_get_interfaces }, { GET_INTERFACE, client_handle_get_interface }, { SET_PORT, client_handle_set_port }, diff --git a/src/lib/atom-private.c b/src/lib/atom-private.c index 27c31e9e..4959db33 100644 --- a/src/lib/atom-private.c +++ b/src/lib/atom-private.c @@ -295,6 +295,67 @@ map_reverse_lookup(const struct value_string *list, const char *string) /* Atom methods */ +static int +_lldpctl_atom_new_config(lldpctl_atom_t *atom, va_list ap) +{ + struct _lldpctl_atom_config_t *c = + (struct _lldpctl_atom_config_t *)atom; + c->config = va_arg(ap, struct lldpd_config *); + return 1; +} + +static void +_lldpctl_atom_free_config(lldpctl_atom_t *atom) +{ + struct _lldpctl_atom_config_t *c = + (struct _lldpctl_atom_config_t *)atom; + lldpd_config_cleanup(c->config); + free(c->config); +} + +static const char* +_lldpctl_atom_get_str_config(lldpctl_atom_t *atom, lldpctl_key_t key) +{ + char *res = NULL; + struct _lldpctl_atom_config_t *c = + (struct _lldpctl_atom_config_t *)atom; + switch (key) { + case lldpctl_k_config_mgmt_pattern: + res = c->config->c_mgmt_pattern; break; + case lldpctl_k_config_iface_pattern: + res = c->config->c_iface_pattern; break; + case lldpctl_k_config_cid_pattern: + res = c->config->c_cid_pattern; break; + case lldpctl_k_config_description: + res = c->config->c_description; break; + case lldpctl_k_config_platform: + res = c->config->c_platform; break; + default: + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + return res?res:""; +} + +static long int +_lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key) +{ + struct _lldpctl_atom_config_t *c = + (struct _lldpctl_atom_config_t *)atom; + switch (key) { + case lldpctl_k_config_delay: + return c->config->c_delay; + case lldpctl_k_config_receiveonly: + return c->config->c_receiveonly; + case lldpctl_k_config_advertise_version: + return c->config->c_advertise_version; + case lldpctl_k_config_lldpmed_noinventory: + return c->config->c_noinventory; + default: + return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + } +} + static int _lldpctl_atom_new_interfaces_list(lldpctl_atom_t *atom, va_list ap) { @@ -2281,6 +2342,11 @@ struct atom_builder { }; struct atom_builder builders[] = { + { atom_config, sizeof(struct _lldpctl_atom_config_t), + .init = _lldpctl_atom_new_config, + .free = _lldpctl_atom_free_config, + .get_str = _lldpctl_atom_get_str_config, + .get_int = _lldpctl_atom_get_int_config }, { atom_interfaces_list, sizeof(struct _lldpctl_atom_interfaces_list_t), .init = _lldpctl_atom_new_interfaces_list, .free = _lldpctl_atom_free_interfaces_list, diff --git a/src/lib/atom.c b/src/lib/atom.c index d9fe4936..f1110716 100644 --- a/src/lib/atom.c +++ b/src/lib/atom.c @@ -386,6 +386,24 @@ lldpctl_watch(lldpctl_conn_t *conn) return 0; } +lldpctl_atom_t* +lldpctl_get_configuration(lldpctl_conn_t *conn) +{ + int rc; + struct lldpd_config *config; + + RESET_ERROR(conn); + + rc = _lldpctl_do_something(conn, + CONN_STATE_GET_CONFIG_SEND, CONN_STATE_GET_CONFIG_RECV, NULL, + GET_CONFIG, + NULL, NULL, + (void **)&config, &MARSHAL_INFO(lldpd_config)); + if (rc == 0) + return _lldpctl_new_atom(conn, atom_config, config); + return NULL; +} + lldpctl_atom_t* lldpctl_get_interfaces(lldpctl_conn_t *conn) { diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 91a84656..7d5e43f7 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -354,6 +354,20 @@ int lldpctl_watch_callback(lldpctl_conn_t *conn, */ int lldpctl_watch(lldpctl_conn_t *conn); +/** + * Retrieve global configuration of lldpd daemon. + * + * @param conn Connection with lldpd. + * @return The global configuration or @c NULL if an error happened. + * + * This function will make IO with the daemon to get the + * configuration. Depending on the IO model, information may not be available + * right now and the function should be called again later. If @c NULL is + * returned, check the last error. If it is @c LLDPCTL_ERR_WOULDBLOCK, try again + * later. + */ +lldpctl_atom_t *lldpctl_get_configuration(lldpctl_conn_t *conn); + /** * Retrieve the list of available interfaces. * @@ -433,6 +447,16 @@ lldpctl_atom_t *lldpctl_get_port(lldpctl_atom_t *port); * first write to a (A,W), then to a (A,WO)). */ typedef enum { + lldpctl_k_config_delay, /* (I) Transmit delay */ + lldpctl_k_config_receiveonly, /* (I) Receive only mode */ + lldpctl_k_config_mgmt_pattern, /* (S) Pattern to choose the management address */ + lldpctl_k_config_iface_pattern, /* (S) Pattern of enabled interfaces */ + lldpctl_k_config_cid_pattern, /* (S) Interface pattern to choose the chassis ID */ + lldpctl_k_config_description, /* (S) Chassis description overriden */ + lldpctl_k_config_platform, /* (S) Platform description overriden (CDP) */ + lldpctl_k_config_advertise_version, /* (I) Advertise version */ + lldpctl_k_config_lldpmed_noinventory, /* (I) Disable LLDP-MED inventory */ + lldpctl_k_interface_name, /**< (S) The interface name. */ lldpctl_k_port_name, /**< (S) The port name. Only works for a local port. */ diff --git a/src/lib/private.h b/src/lib/private.h index 0065f463..c06fbe9e 100644 --- a/src/lib/private.h +++ b/src/lib/private.h @@ -42,6 +42,8 @@ struct lldpctl_conn_t { #define CONN_STATE_SET_PORT_RECV 6 #define CONN_STATE_SET_WATCH_SEND 7 #define CONN_STATE_SET_WATCH_RECV 8 +#define CONN_STATE_GET_CONFIG_SEND 9 +#define CONN_STATE_GET_CONFIG_RECV 9 int state; /* Current state */ void *state_data; /* Data attached to the state. It is used to * check that we are using the same data as a @@ -76,6 +78,7 @@ int _lldpctl_do_something(lldpctl_conn_t *conn, /* atom.c and atom-private.c */ typedef enum { + atom_config, atom_interfaces_list, atom_interface, atom_ports_list, @@ -140,6 +143,11 @@ struct lldpctl_atom_t { lldpctl_atom_t *(*create)(lldpctl_atom_t *); }; +struct _lldpctl_atom_config_t { + lldpctl_atom_t base; + struct lldpd_config *config; +}; + struct _lldpctl_atom_interfaces_list_t { lldpctl_atom_t base; struct lldpd_interface_list *ifs;