]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Add a default local port as a template for any future local port.
authorVincent Bernat <vincent@bernat.im>
Sat, 22 Aug 2015 14:34:24 +0000 (16:34 +0200)
committerVincent Bernat <vincent@bernat.im>
Sat, 22 Aug 2015 14:34:24 +0000 (16:34 +0200)
This default local port can be modified through the library and any
future ports will use it as a template.

19 files changed:
NEWS
src/client/client.h
src/client/commands.c
src/client/conf-lldp.c
src/client/conf-med.c
src/client/conf-power.c
src/ctl.h
src/daemon/client.c
src/daemon/lldpd.c
src/daemon/lldpd.h
src/lib/Makefile.am
src/lib/atom.c
src/lib/atom.h
src/lib/atoms/dot3.c
src/lib/atoms/med.c
src/lib/atoms/port.c
src/lib/connection.c
src/lib/lldpctl.h
src/lib/lldpctl.map

diff --git a/NEWS b/NEWS
index af965aa75be50fe7b7ee4e7cc061593534aaf37f..8b814d8ed2801a06baa7d3d0df08514a2e176bfa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ lldpd (0.8.0)
   * Change:
     + For Linux, switch to libnl3. Be aware of the licensing issues in
       case of static linking.
+    + Introduce the notion of default local port. New interfaces will
+      use it as a base. This allows setting various MED stuff.
 
 lldpd (0.7.17)
   * Fix:
index 9e7fa46df9d0c27b5ad5ff9a9c29b48f7ae85447..64de5faabd759e526c4a02eff3f05cf00ed20bca 100644 (file)
@@ -98,6 +98,8 @@ 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 *);
+lldpctl_atom_t* cmd_iterate_on_ports(struct lldpctl_conn_t *,
+    struct cmd_env *, const char **);
 void cmd_restrict_ports(struct cmd_node *);
 void cmd_restrict_protocol(struct cmd_node *);
 
index 3fa48ace79a50081a68fb1c05794ed2ea12c4e1c..de96ea722610f65d066811c24303403b713d52e5 100644 (file)
@@ -711,6 +711,52 @@ cmd_iterate_on_interfaces(struct lldpctl_conn_t *conn, struct cmd_env *env)
        return iface;
 }
 
+/**
+ * Provide an iterator on all ports contained in "ports", as well as the
+ * default port.
+ *
+ * @warning This function is not reentrant. It uses static variables to keep
+ * track of ports that have already been provided. Moreover, to release all
+ * resources, the iterator should be used until its end.
+ *
+ * @param conn The connection.
+ * @param env  The environment.
+ * @param name Name of the interface (for logging purpose)
+ * @return The next interface in the set of ports (or in all ports if no `ports`
+ *         variable is present in the environment), including the default port
+ *         if no `ports` variable is present in the environment.
+ */
+lldpctl_atom_t*
+cmd_iterate_on_ports(struct lldpctl_conn_t *conn, struct cmd_env *env, const char **name)
+{
+       static int put_default = 0;
+       static lldpctl_atom_t *last_port = NULL;
+       const char *interfaces = cmdenv_get(env, "ports");
+
+       if (last_port) {
+               lldpctl_atom_dec_ref(last_port);
+               last_port = NULL;
+       }
+       if (!put_default) {
+               lldpctl_atom_t *iface = cmd_iterate_on_interfaces(conn, env);
+               if (iface) {
+                       *name = lldpctl_atom_get_str(iface, lldpctl_k_interface_name);
+                       last_port = lldpctl_get_port(iface);
+                       return last_port;
+               }
+               if (!iface && !interfaces) {
+                       put_default = 1;
+                       *name = "(default)";
+                       last_port = lldpctl_get_default_port(conn);
+                       return last_port;
+               }
+               return NULL;
+       } else {
+               put_default = 0;
+               return NULL;
+       }
+}
+
 /**
  * Restrict the command to some ports.
  */
index a39de5eb71b14f496074851494f1b3d47107f3a6..3c7bb3227995499b0398e29ecdbdb6d95467171b 100644 (file)
@@ -73,7 +73,8 @@ static int
 cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w,
                struct cmd_env *env, void *arg)
 {
-       lldpctl_atom_t *iface;
+       lldpctl_atom_t *port;
+       const char *name;
        const char *id = cmdenv_get(env, "port-id");
        const char *descr = cmdenv_get(env, "port-descr");
 
@@ -84,17 +85,15 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w,
                return 0;
        }
 
-       while ((iface = cmd_iterate_on_interfaces(conn, env))) {
-               lldpctl_atom_t *port = lldpctl_get_port(iface);
+       while ((port = cmd_iterate_on_ports(conn, env, &name))) {
                if (lldpctl_atom_set_str(port, lldpctl_k_port_id, id) == NULL) {
-                       log_warnx("lldpctl", "unable to set LLDP PortID."
-                         " %s", lldpctl_last_strerror(conn));
+                       log_warnx("lldpctl", "unable to set LLDP PortID for %s."
+                           " %s", name, lldpctl_last_strerror(conn));
                }
                if (descr && lldpctl_atom_set_str(port, lldpctl_k_port_descr, descr) == NULL) {
-                       log_warnx("lldpctl", "unable to set LLDP Port Description."
-                         " %s", lldpctl_last_strerror(conn));
+                       log_warnx("lldpctl", "unable to set LLDP Port Description for %s."
+                           " %s", name, lldpctl_last_strerror(conn));
                }
-               lldpctl_atom_dec_ref(port);
        }
 
        return 1;
@@ -207,8 +206,9 @@ static int
 cmd_custom_tlv_set(struct lldpctl_conn_t *conn, struct writer *w,
         struct cmd_env *env, void *arg)
 {
-       lldpctl_atom_t *iface;
+       lldpctl_atom_t *port;
        const char *s;
+       const char *name;
        uint8_t oui[LLDP_TLV_ORG_OUI_LEN];
        uint8_t oui_info[LLDP_TLV_ORG_OUI_INFO_MAXLEN];
        int oui_info_len = 0;
@@ -257,17 +257,17 @@ cmd_custom_tlv_set(struct lldpctl_conn_t *conn, struct writer *w,
        }
 
 set:
-       while ((iface = cmd_iterate_on_interfaces(conn, env))) {
-               lldpctl_atom_t *port = lldpctl_get_port(iface);
+       while ((port = cmd_iterate_on_ports(conn, env, &name))) {
                lldpctl_atom_t *custom_tlvs;
                if (!arg) {
                        lldpctl_atom_set(port, lldpctl_k_custom_tlvs_clear, NULL);
                } else if (!(custom_tlvs = lldpctl_atom_get(port, lldpctl_k_custom_tlvs))) {
-                       log_warnx("lldpctl", "unable to get custom TLVs for port");
+                       log_warnx("lldpctl", "unable to get custom TLVs for port %s", name);
                } else {
                        lldpctl_atom_t *tlv = lldpctl_atom_create(custom_tlvs);
                        if (!tlv) {
-                               log_warnx("lldpctl", "unable to create new custom TLV for port");
+                               log_warnx("lldpctl", "unable to create new custom TLV for port %s",
+                                   name);
                        } else {
                                /* Configure custom TLV */
                                lldpctl_atom_set_buffer(tlv, lldpctl_k_custom_tlv_oui, oui, sizeof(oui));
@@ -281,7 +281,6 @@ set:
                        }
                        lldpctl_atom_dec_ref(custom_tlvs);
                }
-               lldpctl_atom_dec_ref(port);
        }
 
        return 1;
index 0a8cfaf05c8cf1cae281be18399febb3d1fbd112..226b3d82c700f57089b7c2ce09f64cd5c41c27de 100644 (file)
@@ -25,10 +25,9 @@ static int
 _cmd_medlocation(struct lldpctl_conn_t *conn,
     struct cmd_env *env, int format)
 {
-       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 *port;
+       const char *name;
+       while ((port = cmd_iterate_on_ports(conn, env, &name))) {
                lldpctl_atom_t *med_location = NULL, *med_locations = NULL;
                const char *what = NULL;
                int ok = 0;
@@ -36,7 +35,7 @@ _cmd_medlocation(struct lldpctl_conn_t *conn,
                med_locations = lldpctl_atom_get(port, lldpctl_k_port_med_locations);
                if (med_locations == NULL) {
                        log_warnx("lldpctl", "unable to set LLDP-MED location: support seems unavailable");
-                       goto end;
+                       continue; /* Iterator needs to be run until end */
                }
 
                med_location = lldpctl_atom_iter_value(med_locations,
@@ -131,10 +130,8 @@ _cmd_medlocation(struct lldpctl_conn_t *conn,
                                    name);
                }
 
-       end:
                lldpctl_atom_dec_ref(med_location);
                lldpctl_atom_dec_ref(med_locations);
-               lldpctl_atom_dec_ref(port);
        }
        return 1;
 }
index b529a764af0a90c95403b949be52e760d52e9f2b..79bddb515e3c8fd55d959e7c7cd6bd3cfdf23f32 100644 (file)
@@ -26,17 +26,16 @@ 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 *port;
+       const char *name;
+       while ((port = cmd_iterate_on_ports(conn, env, &name))) {
                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;
+                       continue; /* Need to finish the loop */
                }
 
                if ((what = "device type", lldpctl_atom_set_str(med_power,
@@ -64,9 +63,7 @@ cmd_medpower(struct lldpctl_conn_t *conn, struct writer *w,
                                    name);
                }
 
-       end:
                lldpctl_atom_dec_ref(med_power);
-               lldpctl_atom_dec_ref(port);
        }
        return 1;
 }
@@ -95,10 +92,9 @@ 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 *port;
+       const char *name;
+       while ((port = cmd_iterate_on_ports(conn, env, &name))) {
                lldpctl_atom_t *dot3_power;
                const char *what = NULL;
                int ok = 1;
@@ -106,7 +102,7 @@ cmd_dot3power(struct lldpctl_conn_t *conn, struct writer *w,
                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;
+                       continue; /* Need to finish the loop */
                }
 
                if ((what = "device type", lldpctl_atom_set_str(dot3_power,
@@ -177,9 +173,7 @@ cmd_dot3power(struct lldpctl_conn_t *conn, struct writer *w,
                                    name);
                }
 
-       end:
                lldpctl_atom_dec_ref(dot3_power);
-               lldpctl_atom_dec_ref(port);
        }
        return 1;
 }
index 92c81976f347135e3e4c8ecc10c8bdfb468a8afd..86425b62948b176d4439a5e866529f5943e91545 100644 (file)
--- a/src/ctl.h
+++ b/src/ctl.h
@@ -32,6 +32,7 @@ enum hmsg_type {
        GET_INTERFACES,         /* Get list of interfaces */
        GET_CHASSIS,            /* Get local chassis */
        GET_INTERFACE,          /* Get all information related to an interface */
+       GET_DEFAULT_PORT,       /* Get all information related to default port */
        SET_PORT,               /* Set port-related information (location, power, policy) */
        SUBSCRIBE,              /* Subscribe to neighbor changes */
        NOTIFICATION,           /* Notification message (sent by lldpd!) */
index 17f19d4b510d762bf8201342983d926537480615..80d501042ee9a4ed61691db7ca5b647c63595f69 100644 (file)
@@ -246,7 +246,7 @@ static ssize_t
 client_handle_get_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
     void *input, int input_len, void **output, int *subscribed)
 {
-    struct lldpd_chassis *chassis = LOCAL_CHASSIS(cfg);
+       struct lldpd_chassis *chassis = LOCAL_CHASSIS(cfg);
        ssize_t output_len;
 
        log_debug("rpc", "client request the local chassis");
@@ -297,6 +297,23 @@ client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
        return 0;
 }
 
+/* Return all available information related to an interface
+   Input:  name of the interface (serialized)
+   Output: Information about the interface (lldpd_hardware)
+*/
+static ssize_t
+client_handle_get_default_port(struct lldpd *cfg, enum hmsg_type *type,
+    void *input, int input_len, void **output, int *subscribed)
+{
+       log_debug("rpc", "client request the default local port");
+       ssize_t output_len = lldpd_port_serialize(cfg->g_default_local_port, output);
+       if (output_len <= 0) {
+               *type = NONE;
+               return 0;
+       }
+       return output_len;
+}
+
 static int
 _client_handle_set_port(struct lldpd *cfg,
     struct lldpd_port *port, struct lldpd_port_set *set)
@@ -415,15 +432,23 @@ client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
        }
 
        /* Search the appropriate hardware */
-       log_debug("rpc", "client request change to port %s", set->ifname);
-       TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
-           if (!strcmp(hardware->h_ifname, set->ifname)) {
-                   struct lldpd_port *port = &hardware->h_lport;
-                   if (_client_handle_set_port(cfg, port, set) == -1)
-                           goto set_port_finished;
-                   ret = 1;
-                   break;
-           }
+       if (strlen(set->ifname) == 0) {
+               log_debug("rpc", "client request change to default port");
+               if (_client_handle_set_port(cfg, cfg->g_default_local_port, set) == -1)
+                       goto set_port_finished;
+               ret = 1;
+       } else {
+               log_debug("rpc", "client request change to port %s", set->ifname);
+               TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
+                   if (!strcmp(hardware->h_ifname, set->ifname)) {
+                           struct lldpd_port *port = &hardware->h_lport;
+                           if (_client_handle_set_port(cfg, port, set) == -1)
+                                   goto set_port_finished;
+                           ret = 1;
+                           break;
+                   }
+               }
+       }
 
        if (ret == 0)
                log_warn("rpc", "no interface %s found", set->ifname);
@@ -476,6 +501,7 @@ static struct client_handle client_handles[] = {
        { SET_CONFIG,           "Set configuration", client_handle_set_configuration },
        { GET_INTERFACES,       "Get interfaces",    client_handle_get_interfaces },
        { GET_INTERFACE,        "Get interface",     client_handle_get_interface },
+       { GET_DEFAULT_PORT,     "Get default port",  client_handle_get_default_port },
        { GET_CHASSIS,          "Get local chassis", client_handle_get_local_chassis },
        { SET_PORT,             "Set port",          client_handle_set_port },
        { SUBSCRIBE,            "Subscribe",         client_handle_subscribe },
index f32cd05b45df039a268e3e04dc1bd4c193c868c6..c47209de12f58e168415ece50f15e8d1079eeb0b 100644 (file)
@@ -139,6 +139,64 @@ lldpd_get_hardware(struct lldpd *cfg, char *name, int index, struct lldpd_ops *o
        return hardware;
 }
 
+/**
+ * Allocate the default local port. This port will be cloned each time we need a
+ * new local port.
+ */
+static void
+lldpd_alloc_default_local_port(struct lldpd *cfg)
+{
+       struct lldpd_port *port;
+
+       if ((port = (struct lldpd_port *)
+               calloc(1, sizeof(struct lldpd_port))) == NULL)
+               fatal("main", NULL);
+
+#ifdef ENABLE_DOT1
+       TAILQ_INIT(&port->p_vlans);
+       TAILQ_INIT(&port->p_ppvids);
+       TAILQ_INIT(&port->p_pids);
+#endif
+#ifdef ENABLE_CUSTOM
+       TAILQ_INIT(&port->p_custom_list);
+#endif
+       cfg->g_default_local_port = port;
+}
+
+/**
+ * Clone a given port. The destination needs to be already allocated.
+ */
+static int
+lldpd_clone_port(struct lldpd_port *destination, struct lldpd_port *source)
+{
+
+       u_int8_t *output = NULL;
+       ssize_t output_len;
+       struct lldpd_port *cloned = NULL;
+       output_len = lldpd_port_serialize(source, (void**)&output);
+       if (output_len == -1 ||
+           lldpd_port_unserialize(output, output_len, &cloned) <= 0) {
+               log_warnx("alloc", "unable to clone default port");
+               goto end;
+       }
+       memcpy(destination, cloned, sizeof(struct lldpd_port));
+       free(cloned); cloned = NULL;
+#ifdef ENABLE_DOT1
+       marshal_repair_tailq(lldpd_vlan, &destination->p_vlans, v_entries);
+       marshal_repair_tailq(lldpd_ppvid, &destination->p_ppvids, p_entries);
+       marshal_repair_tailq(lldpd_pi, &destination->p_pids, p_entries);
+#endif
+#ifdef ENABLE_CUSTOM
+       marshal_repair_tailq(lldpd_custom, &destination->p_custom_list, next);
+#endif
+       return 0;
+
+end:
+       free(output);
+       if (cloned != NULL) lldpd_port_cleanup(cloned, 1);
+       return -1;
+}
+
 struct lldpd_hardware *
 lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
 {
@@ -150,6 +208,13 @@ lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
                calloc(1, sizeof(struct lldpd_hardware))) == NULL)
                return NULL;
 
+       /* Clone default local port */
+       if (lldpd_clone_port(&hardware->h_lport, cfg->g_default_local_port) == -1) {
+               log_warnx("alloc", "unable to clone default port");
+               free(hardware);
+               return NULL;
+       }
+
        hardware->h_cfg = cfg;
        strlcpy(hardware->h_ifname, name, sizeof(hardware->h_ifname));
        hardware->h_ifindex = index;
@@ -164,14 +229,6 @@ lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
                        hardware->h_lport.p_med_cap_enabled |= LLDP_MED_CAP_IV;
        }
 #endif
-#ifdef ENABLE_DOT1
-       TAILQ_INIT(&hardware->h_lport.p_vlans);
-       TAILQ_INIT(&hardware->h_lport.p_ppvids);
-       TAILQ_INIT(&hardware->h_lport.p_pids);
-#endif
-#ifdef ENABLE_CUSTOM
-       TAILQ_INIT(&hardware->h_lport.p_custom_list);
-#endif
 
        levent_hardware_init(hardware);
        return hardware;
@@ -1601,6 +1658,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
            calloc(1, sizeof(struct lldpd))) == NULL)
                fatal("main", NULL);
 
+       lldpd_alloc_default_local_port(cfg);
        cfg->g_ctlname = ctlname;
        cfg->g_ctl = ctl;
        cfg->g_config.c_mgmt_pattern = mgmtp;
index cf6f2fa9953e96cdbebf27f30d09e01d0a03cfb5..07b935696d11f30b98fd850438cc930c2b9087de 100644 (file)
@@ -417,6 +417,7 @@ struct lldpd {
        struct lldpd_netlink    *g_netlink;
 #endif
 
+       struct lldpd_port       *g_default_local_port;
 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
        TAILQ_HEAD(, lldpd_chassis) g_chassis;
        TAILQ_HEAD(, lldpd_hardware) g_hardware;
index 9f5e89dea1405da723123b81583d45625d690d43..b419b551ee96334a50c460ade8ddafc311a61cdc 100644 (file)
@@ -21,7 +21,7 @@ liblldpctl_la_LIBADD  = $(top_builddir)/src/libcommon-daemon-lib.la libfixedpoin
 # -version-number could be computed from -version-info, mostly major
 # is `current` - `age`, minor is `age` and revision is `revision' and
 # major.minor should be used when updaing lldpctl.map.
-liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 11:0:7
+liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 12:0:8
 liblldpctl_la_DEPENDENCIES = libfixedpoint.la
 
 if HAVE_LD_VERSION_SCRIPT
index ddf849ee893dcabe678126413e809e1fdfdae426..708585537921cfad35ca525f33d95cdc90d01c89 100644 (file)
@@ -479,12 +479,32 @@ lldpctl_get_port(lldpctl_atom_t *atom)
            &p, &MARSHAL_INFO(lldpd_hardware));
        if (rc == 0) {
                hardware = p;
-               return _lldpctl_new_atom(conn, atom_port,
+               return _lldpctl_new_atom(conn, atom_port, 1,
                    hardware, &hardware->h_lport, NULL);
        }
        return NULL;
 }
 
+lldpctl_atom_t*
+lldpctl_get_default_port(lldpctl_conn_t *conn)
+{
+       struct lldpd_port *port;
+       void *p;
+       int rc;
+
+       RESET_ERROR(conn);
+
+       rc = _lldpctl_do_something(conn,
+           CONN_STATE_GET_DEFAULT_PORT_SEND, CONN_STATE_GET_DEFAULT_PORT_RECV, "",
+           GET_DEFAULT_PORT, NULL, NULL,
+           &p, &MARSHAL_INFO(lldpd_port));
+       if (rc == 0) {
+               port = p;
+               return _lldpctl_new_atom(conn, atom_port, 1, NULL, port, NULL);
+       }
+       return NULL;
+}
+
 static lldpctl_map_t empty_map[] = {{ 0, NULL }};
 
 static struct atom_map atom_map_list = {
index 18abf6fac4af7314c2644d144faf4f002af551dd..e179fd02e64698a76114735b93b918385e2669bf 100644 (file)
@@ -52,6 +52,8 @@ struct lldpctl_conn_t {
 #define CONN_STATE_SET_CONFIG_RECV     11
 #define CONN_STATE_GET_CHASSIS_SEND    12
 #define CONN_STATE_GET_CHASSIS_RECV    13
+#define CONN_STATE_GET_DEFAULT_PORT_SEND 14
+#define CONN_STATE_GET_DEFAULT_PORT_RECV 15
        int state;              /* Current state */
        char *state_data;       /* Data attached to the state. It is used to
                                 * check that we are using the same data as a
@@ -180,7 +182,8 @@ struct _lldpctl_atom_chassis_t {
 
 struct _lldpctl_atom_port_t {
        lldpctl_atom_t base;
-       struct lldpd_hardware *hardware; /* Local port only */
+       int local;                       /* Local or remote port? */
+       struct lldpd_hardware *hardware; /* Local port only (but optional) */
        struct lldpd_port     *port;     /* Local and remote */
        struct _lldpctl_atom_port_t *parent; /* Local port if we are a remote port */
        lldpctl_atom_t *chassis; /* Internal atom for chassis */
index 9e21abde4eb0d2ebd30deeab5b1c840ffbc14171..19d62c460b504070d967138493b8057d9cb47e93 100644 (file)
@@ -176,7 +176,7 @@ _lldpctl_atom_set_int_dot3_power(lldpctl_atom_t *atom, lldpctl_key_t key,
        struct lldpd_port *port = dpow->parent->port;
 
        /* Only local port can be modified */
-       if (dpow->parent->hardware == NULL) {
+       if (!dpow->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
index 45ee2e2f323f9c6c6034d8c2ef7d7f4e5bc13561..6c425c643bdcb3384768227c769ae37739bcff90 100644 (file)
@@ -226,7 +226,7 @@ _lldpctl_atom_set_int_med_policy(lldpctl_atom_t *atom, lldpctl_key_t key,
            (struct _lldpctl_atom_med_policy_t *)atom;
 
        /* Only local port can be modified */
-       if (m->parent->hardware == NULL) {
+       if (!m->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -399,7 +399,7 @@ _lldpctl_atom_set_int_med_location(lldpctl_atom_t *atom, lldpctl_key_t key,
            (struct _lldpctl_atom_med_location_t *)atom;
 
        /* Only local port can be modified */
-       if (mloc->parent->hardware == NULL) {
+       if (!mloc->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -568,7 +568,7 @@ _lldpctl_atom_set_str_med_location(lldpctl_atom_t *atom, lldpctl_key_t key,
        char *end = NULL;
 
        /* Only local port can be modified */
-       if (mloc->parent->hardware == NULL) {
+       if (!mloc->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -683,7 +683,7 @@ _lldpctl_atom_set_atom_med_location(lldpctl_atom_t *atom, lldpctl_key_t key,
        uint8_t *new;
 
        /* Only local port can be modified */
-       if (m->parent->hardware == NULL) {
+       if (!m->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -818,7 +818,7 @@ _lldpctl_atom_set_int_med_caelement(lldpctl_atom_t *atom, lldpctl_key_t key,
            (struct _lldpctl_atom_med_caelement_t *)atom;
 
        /* Only local port can be modified */
-       if (el->parent->parent->hardware == NULL) {
+       if (!el->parent->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -870,7 +870,7 @@ _lldpctl_atom_set_str_med_caelement(lldpctl_atom_t *atom, lldpctl_key_t key,
        size_t len;
 
        /* Only local port can be modified */
-       if (el->parent->parent->hardware == NULL) {
+       if (!el->parent->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -972,7 +972,7 @@ _lldpctl_atom_set_int_med_power(lldpctl_atom_t *atom, lldpctl_key_t key,
        struct lldpd_port *port = dpow->parent->port;
 
        /* Only local port can be modified */
-       if (dpow->parent->hardware == NULL) {
+       if (!dpow->parent->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
index 7cab6959a617a56ae1c65fc3834b8ff1dc70b1bc..5719616e589bd670f11360c863f53cdeda05b509 100644 (file)
@@ -127,7 +127,7 @@ static lldpctl_atom_t*
 _lldpctl_atom_value_ports_list(lldpctl_atom_t *atom, lldpctl_atom_iter_t *iter)
 {
        struct lldpd_port *port = (struct lldpd_port *)iter;
-       return _lldpctl_new_atom(atom->conn, atom_port, NULL, port,
+       return _lldpctl_new_atom(atom->conn, atom_port, 0, NULL, port,
            ((struct _lldpctl_atom_any_list_t *)atom)->parent);
 }
 
@@ -136,6 +136,7 @@ _lldpctl_atom_new_port(lldpctl_atom_t *atom, va_list ap)
 {
        struct _lldpctl_atom_port_t *port =
            (struct _lldpctl_atom_port_t *)atom;
+       port->local = va_arg(ap, int);
        port->hardware = va_arg(ap, struct lldpd_hardware*);
        port->port = va_arg(ap, struct lldpd_port*);
        port->parent = va_arg(ap, struct _lldpctl_atom_port_t*);
@@ -186,8 +187,10 @@ _lldpctl_atom_free_port(lldpctl_atom_t *atom)
        else if (!hardware) {
                /* No parent, no hardware, we assume a single neighbor: one
                 * port, one chassis. */
-               lldpd_chassis_cleanup(port->port->p_chassis, 1);
-               port->port->p_chassis = NULL;
+               if (port->port->p_chassis) {
+                       lldpd_chassis_cleanup(port->port->p_chassis, 1);
+                       port->port->p_chassis = NULL;
+               }
                lldpd_port_cleanup(port->port, 1);
                free(port->port);
        }
@@ -231,8 +234,12 @@ _lldpctl_atom_get_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key)
        /* Local and remote port */
        switch (key) {
        case lldpctl_k_port_chassis:
-               return _lldpctl_new_atom(atom->conn, atom_chassis,
-                   port->p_chassis, p, 0);
+               if (port->p_chassis) {
+                       return _lldpctl_new_atom(atom->conn, atom_chassis,
+                           port->p_chassis, p, 0);
+               }
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
 #ifdef ENABLE_DOT3
        case lldpctl_k_port_dot3_power:
                return _lldpctl_new_atom(atom->conn, atom_dot3_power,
@@ -265,7 +272,10 @@ _lldpctl_atom_get_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key)
 #endif
        default:
                /* Compatibility: query the associated chassis too */
-               return lldpctl_atom_get(p->chassis, key);
+               if (port->p_chassis)
+                       return lldpctl_atom_get(p->chassis, key);
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
        }
 }
 
@@ -291,8 +301,8 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato
        struct _lldpctl_atom_custom_t    *custom;
 #endif
 
-       /* Local port only */
-       if (hardware == NULL) {
+       /* Local and default port only */
+       if (!p->local) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
        }
@@ -360,7 +370,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato
                return NULL;
        }
 
-       set.ifname = hardware->h_ifname;
+       set.ifname = hardware ? hardware->h_ifname : "";
 
        if (asprintf(&canary, "%d%p%s", key, value, set.ifname) == -1) {
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
index 691b3bd2e4b00079843cf9d88c13682d3a47f3b2..aeb702e5beb2847b927f2aee3e9b9e9236105622 100644 (file)
@@ -208,7 +208,7 @@ check_for_notification(lldpctl_conn_t *conn)
                interface = _lldpctl_new_atom(conn, atom_interface,
                    change->ifname);
                if (interface == NULL) goto end;
-               neighbor = _lldpctl_new_atom(conn, atom_port,
+               neighbor = _lldpctl_new_atom(conn, atom_port, 0,
                    NULL, change->neighbor, NULL);
                if (neighbor == NULL) goto end;
                conn->watch_cb(conn, type, interface, neighbor, conn->watch_data);
index c1774e882048118e4698d7d2cde6f242fe4fc947..c76ccd5c39e0736a6ce36cc829a590b33d1374f7 100644 (file)
@@ -560,7 +560,7 @@ lldpctl_atom_t *lldpctl_get_local_chassis(lldpctl_conn_t *conn);
  *             atom retrieved from an interation on @c lldpctl_get_interfaces().
  * @return Atom related to this port which may be used in subsequent functions.
  *
- * This functions may have to do IO to get the information related to the given
+ * This function may have to do IO to get the information related to the given
  * port. Depending on the IO mode, information may not be available right now
  * and the function should be called again later. If @c NULL is returned, check
  * what the last error is. If it is @c LLDPCTL_ERR_WOULDBLOCK, try again later
@@ -568,6 +568,22 @@ lldpctl_atom_t *lldpctl_get_local_chassis(lldpctl_conn_t *conn);
  */
 lldpctl_atom_t *lldpctl_get_port(lldpctl_atom_t *port);
 
+/**
+ * Retrieve the default port information.
+ *
+ * This port contains default settings whenever a new port needs to be created.
+ *
+ * @param conn Previously allocated handler to a connection to lldpd.
+ * @return Atom of the default port which may be used in subsequent functions.
+ *
+ * This function may have to do IO to get the information related to the given
+ * port. Depending on the IO mode, information may not be available right now
+ * and the function should be called again later. If @c NULL is returned, check
+ * what the last error is. If it is @c LLDPCTL_ERR_WOULDBLOCK, try again later
+ * (when more data is available).
+ */
+lldpctl_atom_t *lldpctl_get_default_port(lldpctl_conn_t *conn);
+
 /**@}*/
 
 /**
index c8f46d5df3ed2279ae4f2a5291aee710df256bce..c725381a09e99e1947e4f12e1e83068f97017ded 100644 (file)
@@ -1,3 +1,8 @@
+LIBLLDPCTL_4.8 {
+ global:
+  lldpctl_get_default_port;
+};
+
 LIBLLDPCTL_4.7 {
  global:
   lldpctl_get_local_chassis;