]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpctl: allow to display global configuration of lldpd
authorVincent Bernat <bernat@luffy.cx>
Fri, 31 Aug 2012 15:35:05 +0000 (17:35 +0200)
committerVincent Bernat <bernat@luffy.cx>
Fri, 31 Aug 2012 16:07:53 +0000 (18:07 +0200)
man/lldpctl.8
src/client/client.h
src/client/display.c
src/client/lldpctl.c
src/client/writer.h
src/ctl.h
src/daemon/client.c
src/lib/atom-private.c
src/lib/atom.c
src/lib/lldpctl.h
src/lib/private.h

index 436e7b243c468c85c3b6413109ca50a080268ac1..efd305e1edb924f67a94c98ee6181fc0f406155b 100644 (file)
@@ -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 ,
index c57b7e11190670ea02d7f1645e3e2d7fa5b5b400..0e0e4ba8b2facb4e8254552c1379c3e64826e65f 100644 (file)
 #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);
index e29bad1e0ce05e06ce1db1d166cf42571788aa55..fed28ae13ff3def97df2905287cfb4b9ddaf2841 100644 (file)
@@ -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);
+}
index e848d05a1c00a917fbcb554a731a5ce55b5f1097..f1e13d2e93820334653f2a06aa1b2579356a4ccf 100644 (file)
@@ -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);
index cedaee100bcc4e5f2a05e819766bde673c9640a3..71713fb50c7f1ef107d39dfafadb1de73356a323 100644 (file)
@@ -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 * );
index 01e88b3064e58358bbec12dd7e3b56622c6a04ac..5b47efd1cbfe2c661858c7e4ba51d1d08188ff50 100644 (file)
--- 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) */
index 94fe9a40b0d094e298a68d637208413d7386052c..d060d2fe7e73b8c5489f2351b85c0676afc8a908 100644 (file)
@@ -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 },
index 27c31e9e4097d39c7c43a79fc3e0bae037bb2bc3..4959db33e820b76fcff799c260a433ce00393d56 100644 (file)
@@ -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,
index d9fe49363cfb3a3917c95158fa2a4f01c0e6c43e..f1110716d7411b605a27c043b3b5e31178e56152 100644 (file)
@@ -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)
 {
index 91a84656cce164bb8e882420e0dbfc06921debea..7d5e43f77e2857bab553d7619226928626057893 100644 (file)
@@ -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. */
index 0065f46303ddb0bc6b8ece2ebb289ec54315570a..c06fbe9e0d629b33b216775e894563c23332369b 100644 (file)
@@ -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;