]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lib: add custom TLV + list atom(s)
authorAlexandru Ardelean <ardeleanalex@gmail.com>
Thu, 9 Apr 2015 15:00:40 +0000 (18:00 +0300)
committerAlexandru Ardelean <ardeleanalex@gmail.com>
Tue, 19 May 2015 06:54:41 +0000 (09:54 +0300)
Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
src/lib/Makefile.am
src/lib/atom.h
src/lib/atoms/custom.c [new file with mode: 0644]
src/lib/atoms/port.c
src/lib/lldpctl.h

index a7709bf15a04d58f9eae9f47982de0d575f62d1f..ffb1322014badeadc4de3eec8ce0c8db1a9a8240 100644 (file)
@@ -11,7 +11,8 @@ libfixedpoint_la_SOURCES = fixedpoint.h fixedpoint.c
 liblldpctl_la_SOURCES = \
        lldpctl.h atom.h errors.c connection.c atom.c helpers.c helpers.h \
        atoms/config.c atoms/dot1.c atoms/dot3.c \
-       atoms/interface.c atoms/med.c atoms/mgmt.c atoms/port.c
+       atoms/interface.c atoms/med.c atoms/mgmt.c atoms/port.c \
+       atoms/custom.c
 liblldpctl_la_LIBADD  = $(top_builddir)/src/libcommon-daemon-lib.la libfixedpoint.la
 liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols-regex '^lldpctl_' -version-info 10:0:6
 
index 1e30712da86280d6817c3bea0c976ccea7023b9e..731ff6ca564873b3dce77b864426f36701c8e082 100644 (file)
@@ -111,6 +111,8 @@ typedef enum {
        atom_med_caelement,
        atom_med_power,
 #endif
+       atom_custom_list,
+       atom_custom,
 } atom_t;
 
 void *_lldpctl_alloc_in_atom(lldpctl_atom_t *, size_t);
@@ -249,6 +251,18 @@ struct _lldpctl_atom_med_power_t {
 };
 #endif
 
+struct _lldpctl_atom_custom_list_t {
+       lldpctl_atom_t base;
+       struct _lldpctl_atom_port_t *parent;
+       struct lldpd_custom_list *list;
+};
+
+struct _lldpctl_atom_custom_t {
+       lldpctl_atom_t base;
+       struct _lldpctl_atom_port_t *parent;
+       struct lldpd_custom *tlv;
+};
+
 struct lldpctl_atom_t *_lldpctl_new_atom(lldpctl_conn_t *conn, atom_t type, ...);
 
 struct atom_map {
diff --git a/src/lib/atoms/custom.c b/src/lib/atoms/custom.c
new file mode 100644 (file)
index 0000000..bcf63fa
--- /dev/null
@@ -0,0 +1,186 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
+ * Copyright (c) 2015 Alexandru Ardelean <ardeleanalex@gmail.com>
+ *
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "lldpctl.h"
+#include "../log.h"
+#include "atom.h"
+#include "helpers.h"
+
+#define min(x,y)       ( (x > y) ? y : x )
+
+static lldpctl_atom_iter_t*
+_lldpctl_atom_iter_custom_list(lldpctl_atom_t *atom)
+{
+       struct _lldpctl_atom_custom_list_t *custom =
+           (struct _lldpctl_atom_custom_list_t *)atom;
+       return (lldpctl_atom_iter_t*)TAILQ_FIRST(&custom->parent->port->p_custom_list);
+}
+
+static lldpctl_atom_iter_t*
+_lldpctl_atom_next_custom_list(lldpctl_atom_t *atom, lldpctl_atom_iter_t *iter)
+{
+       return (lldpctl_atom_iter_t*)TAILQ_NEXT((struct lldpd_custom *)iter, next);
+}
+
+static lldpctl_atom_t*
+_lldpctl_atom_value_custom_list(lldpctl_atom_t *atom, lldpctl_atom_iter_t *iter)
+{
+       struct _lldpctl_atom_custom_list_t *custom =
+           (struct _lldpctl_atom_custom_list_t *)atom;
+       struct lldpd_custom *tlv = (struct lldpd_custom *) iter;
+       return _lldpctl_new_atom(atom->conn, atom_custom, custom->parent, tlv);
+}
+
+static lldpctl_atom_t*
+_lldpctl_atom_create_custom_list(lldpctl_atom_t *atom)
+{
+       struct _lldpctl_atom_custom_list_t *custom =
+           (struct _lldpctl_atom_custom_list_t *)atom;
+       struct lldpd_custom *tlv;
+
+       tlv = _lldpctl_alloc_in_atom(atom, sizeof(struct lldpd_custom));
+       if (!tlv)
+               return NULL;
+       return _lldpctl_new_atom(atom->conn, atom_custom, custom->parent, tlv);
+}
+
+static int
+_lldpctl_atom_new_custom(lldpctl_atom_t *atom, va_list ap)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+
+       custom->parent = va_arg(ap, struct _lldpctl_atom_port_t *);
+       custom->tlv    = va_arg(ap, struct lldpd_custom *);
+       lldpctl_atom_inc_ref((lldpctl_atom_t *)custom->parent);
+       return 1;
+}
+
+static void
+_lldpctl_atom_free_custom(lldpctl_atom_t *atom)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+       lldpctl_atom_dec_ref((lldpctl_atom_t *)custom->parent);
+}
+
+static long int
+_lldpctl_atom_get_int_custom(lldpctl_atom_t *atom, lldpctl_key_t key)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+
+       switch (key) {
+       case lldpctl_k_custom_tlv_oui_subtype:
+               return custom->tlv->subtype;
+       default:
+               return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+       }
+}
+
+static lldpctl_atom_t*
+_lldpctl_atom_set_int_custom(lldpctl_atom_t *atom, lldpctl_key_t key,
+    long int value)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+
+       switch (key) {
+       case lldpctl_k_custom_tlv_oui_subtype:
+               if (value < 0 || value > 255) goto bad;
+               custom->tlv->subtype = value;
+               return atom;
+       default:
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
+       }
+bad:
+       SET_ERROR(atom->conn, LLDPCTL_ERR_BAD_VALUE);
+       return NULL;
+}
+
+static const uint8_t*
+_lldpctl_atom_get_buffer_custom(lldpctl_atom_t *atom, lldpctl_key_t key, size_t *n)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+
+       switch (key) {
+       case lldpctl_k_custom_tlv_oui:
+               *n = sizeof(custom->tlv->oui);
+               return (const uint8_t *)&custom->tlv->oui;
+       case lldpctl_k_custom_tlv_oui_info_string:
+               *n = custom->tlv->oui_info_len;
+               return (const uint8_t *)&custom->tlv->oui_info;
+       default:
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
+       }
+}
+
+static lldpctl_atom_t*
+_lldpctl_atom_set_buffer_custom(lldpctl_atom_t *atom, lldpctl_key_t key,
+    const u_int8_t *buf, size_t n)
+{
+       struct _lldpctl_atom_custom_t *custom =
+           (struct _lldpctl_atom_custom_t *)atom;
+
+       switch (key) {
+       case lldpctl_k_custom_tlv_oui:
+               memcpy(&custom->tlv->oui, buf, min(n, sizeof(custom->tlv->oui)));
+               return atom;
+       case lldpctl_k_custom_tlv_oui_info_string:
+               if (n == 0 || n > LLDP_TLV_ORG_OUI_INFO_MAXLEN) {
+                       SET_ERROR(atom->conn, LLDPCTL_ERR_BAD_VALUE);
+                       return NULL;
+               }
+               custom->tlv->oui_info_len = n;
+               memcpy(&custom->tlv->oui_info, buf, n);
+               return atom;
+       default:
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
+       }
+}
+
+static struct atom_builder custom_list =
+       { atom_custom_list, sizeof(struct _lldpctl_atom_any_list_t),
+         .init  = _lldpctl_atom_new_any_list,
+         .free  = _lldpctl_atom_free_any_list,
+         .iter  = _lldpctl_atom_iter_custom_list,
+         .next  = _lldpctl_atom_next_custom_list,
+         .value = _lldpctl_atom_value_custom_list, 
+         .create = _lldpctl_atom_create_custom_list };
+
+static struct atom_builder custom =
+       { atom_custom, sizeof(struct _lldpctl_atom_custom_t),
+         .init = _lldpctl_atom_new_custom,
+         .free = _lldpctl_atom_free_custom,
+         .get_int = _lldpctl_atom_get_int_custom,
+         .set_int = _lldpctl_atom_set_int_custom,
+         .get_buffer = _lldpctl_atom_get_buffer_custom,
+         .set_buffer = _lldpctl_atom_set_buffer_custom };
+
+ATOM_BUILDER_REGISTER(custom_list, 22);
+ATOM_BUILDER_REGISTER(custom,      23);
+
index 1b870ede0af391e00bf73ff1950455a897e2fa55..20713d10165444dbfd850f98cf3ecbb22623f770 100644 (file)
@@ -273,6 +273,8 @@ _lldpctl_atom_get_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key)
        case lldpctl_k_port_med_power:
                return _lldpctl_new_atom(atom->conn, atom_med_power, p);
 #endif
+       case lldpctl_k_custom_tlvs:
+               return _lldpctl_new_atom(atom->conn, atom_custom_list, p);
        default:
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
@@ -297,6 +299,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato
        struct _lldpctl_atom_med_policy_t *mpol;
        struct _lldpctl_atom_med_location_t *mloc;
 #endif
+       struct _lldpctl_atom_custom_t    *custom;
 
        /* Local port only */
        if (hardware == NULL) {
@@ -349,6 +352,17 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato
                set.med_location = mloc->location;
                break;
 #endif
+       case lldpctl_k_custom_tlvs_clear:
+               set.custom_list_clear = 1;
+               break;
+       case lldpctl_k_custom_tlv:
+               if (value->type != atom_custom) {
+                       SET_ERROR(atom->conn, LLDPCTL_ERR_INCORRECT_ATOM_TYPE);
+                       return NULL;
+               }
+               custom = (struct _lldpctl_atom_custom_t *)value;
+               set.custom = custom->tlv;
+               break;
        default:
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
index 3f07e442b2a484ce43bc69270e7f1b2e70a494d8..5bbda09880899a23b1b87f1c325a1c82c568992b 100644 (file)
@@ -740,6 +740,14 @@ typedef enum {
        lldpctl_k_config_tx_hold, /**< `(I,WO)` Transmit hold interval. */
        lldpctl_k_config_bond_slave_src_mac_type, /**< `(I,WO)` bond slave src mac type. */
        lldpctl_k_config_lldp_portid_type, /**< `(I,WO)` LLDP PortID TLV Subtype */
+
+       lldpctl_k_custom_tlvs = 5000,           /**< `(AL)` custom TLVs */
+       lldpctl_k_custom_tlvs_clear,            /** `(I,WO)` clear list of custom TLVs */
+       lldpctl_k_custom_tlv,                   /** `(AL,WO)` custom TLV **/
+       lldpctl_k_custom_tlv_oui,               /**< `(I,WO)` custom TLV Organizationally Unique Identifier. Default is 0 (3 bytes) */
+       lldpctl_k_custom_tlv_oui_subtype,       /**< `(I,WO)` custom TLV subtype. Default is 0 (1 byte) */
+       lldpctl_k_custom_tlv_oui_info_string,   /**< `(I,WO)` custom TLV Organizationally Unique Identifier Information String (up to 507 bytes) */
+
 } lldpctl_key_t;
 
 /**