From: Alexandru Ardelean Date: Thu, 9 Apr 2015 15:00:40 +0000 (+0300) Subject: lib: add custom TLV + list atom(s) X-Git-Tag: 0.7.15~25^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c576fd21a41683f9adda66d0b933c7a246060902;p=thirdparty%2Flldpd.git lib: add custom TLV + list atom(s) Signed-off-by: Alexandru Ardelean --- diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index a7709bf1..ffb13220 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -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 diff --git a/src/lib/atom.h b/src/lib/atom.h index 1e30712d..731ff6ca 100644 --- a/src/lib/atom.h +++ b/src/lib/atom.h @@ -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 index 00000000..bcf63fa7 --- /dev/null +++ b/src/lib/atoms/custom.c @@ -0,0 +1,186 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2015 Vincent Bernat + * Copyright (c) 2015 Alexandru Ardelean + * + * 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 +#include + +#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); + diff --git a/src/lib/atoms/port.c b/src/lib/atoms/port.c index 1b870ede..20713d10 100644 --- a/src/lib/atoms/port.c +++ b/src/lib/atoms/port.c @@ -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; diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 3f07e442..5bbda098 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -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; /**