From fadeddfbb2aa38a980dd959b5ec1ffba7afd43cb Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 20:02:34 +0200 Subject: Adding upstream version 1.0.18. Signed-off-by: Daniel Baumann --- src/lib/atoms/custom.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 src/lib/atoms/custom.c (limited to 'src/lib/atoms/custom.c') diff --git a/src/lib/atoms/custom.c b/src/lib/atoms/custom.c new file mode 100644 index 0000000..ffa5b03 --- /dev/null +++ b/src/lib/atoms/custom.c @@ -0,0 +1,226 @@ +/* -*- 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" + +#ifdef ENABLE_CUSTOM + +# 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_str_custom(lldpctl_atom_t *atom, lldpctl_key_t key, const char *value) +{ + struct _lldpctl_atom_custom_t *custom = (struct _lldpctl_atom_custom_t *)atom; + + if (!value || !strlen(value)) return NULL; + + /* Only local port can be modified */ + if (!custom->parent->local) { + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + + switch (key) { + case lldpctl_k_custom_tlv_op: + if (!strcmp(value, "replace")) + custom->op = CUSTOM_TLV_REPLACE; + else if (!strcmp(value, "remove")) + custom->op = CUSTOM_TLV_REMOVE; + else + custom->op = CUSTOM_TLV_ADD; + return atom; + default: + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + + SET_ERROR(atom->conn, LLDPCTL_ERR_BAD_VALUE); + return NULL; +} + +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; + + /* Only local port can be modified */ + if (!custom->parent->local) { + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + + 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; + + /* Only local port can be modified */ + if (!custom->parent->local) { + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + + 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; + if (!(custom->tlv->oui_info = _lldpctl_alloc_in_atom(atom, n))) { + custom->tlv->oui_info_len = 0; + SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM); + return NULL; + } + 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, + .set_str = _lldpctl_atom_set_str_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); + +#endif /* ENABLE_CUSTOM */ -- cgit v1.2.3