2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <assert.h>
2N/A#include <stdio.h>
2N/A#include <ctype.h>
2N/A#include <door.h>
2N/A#include <errno.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <strings.h>
2N/A#include <unistd.h>
2N/A#include <sys/mman.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <sys/vlan.h>
2N/A#include <fcntl.h>
2N/A#include <libdllink.h>
2N/A#include <libdlaggr.h>
2N/A#include <libdlvnic.h>
2N/A#include <libdlvlan.h>
2N/A#include <liblldp.h>
2N/A#include <liblldp_lldpd.h>
2N/A
2N/A#define LLDP_ONSTR "on"
2N/A#define LLDP_OFFSTR "off"
2N/A
2N/Avoid lldp_bitmap2str(uint8_t, char *, uint_t);
2N/A
2N/Astruct lldp_prop_desc;
2N/Atypedef struct lldp_prop_desc lldp_prop_desc_t;
2N/A
2N/A/* property set() callback */
2N/Atypedef lldp_status_t lldp_pd_setf_t(const char *, lldp_prop_desc_t *,
2N/A void *, uint_t);
2N/A
2N/A/* property get() callback */
2N/Atypedef lldp_status_t lldp_pd_getf_t(const char *, lldp_prop_desc_t *,
2N/A char *, uint_t *, uint_t);
2N/A
2N/Astruct lldp_prop_desc {
2N/A const char *lpd_name; /* property name */
2N/A lldp_propclass_t lpd_pclass; /* property class */
2N/A lldp_proptype_t lpd_ptype; /* property ID */
2N/A lldp_val_desc_t lpd_defval;
2N/A lldp_val_desc_t *lpd_optval;
2N/A uint_t lpd_noptval;
2N/A lldp_pd_setf_t *lpd_setf; /* set callback function */
2N/A lldp_pd_getf_t *lpd_getf; /* get value callback function */
2N/A uint_t lpd_flags; /* see below */
2N/A};
2N/A
2N/A/*
2N/A * `lpd_flags' values
2N/A * LLDP_PROP_MULVAL: property is multi-valued
2N/A * LLDP_PROP_GLOBAL: property does not apply to a single agent or a
2N/A * single TLV.
2N/A */
2N/A#define LLDP_PROP_MULVAL 0x00000001
2N/A#define LLDP_PROP_GLOBAL 0x00000002
2N/A
2N/Alldp_val_desc_t lldp_mode_vals[] = {
2N/A { "txonly", LLDP_MODE_TXONLY },
2N/A { "rxonly", LLDP_MODE_RXONLY },
2N/A { "both", LLDP_MODE_RXTX },
2N/A { "disable", LLDP_MODE_DISABLE }
2N/A};
2N/A
2N/A/*
2N/A * Note: LLDP_..._NONE_TLV must be the first and LLDP_..._ALL.._TLV must
2N/A * be the last TLV in these tables. See lldp_mask2str().
2N/A */
2N/Astatic lldp_val_desc_t lldp_basic_tlvs_vals[] = {
2N/A { LLDP_BASIC_NONE_TLVNAME, LLDP_BASIC_NONE_TLV },
2N/A { LLDP_BASIC_PORTDESC_TLVNAME, LLDP_BASIC_PORTDESC_TLV },
2N/A { LLDP_BASIC_SYSNAME_TLVNAME, LLDP_BASIC_SYSNAME_TLV },
2N/A { LLDP_BASIC_SYSDESC_TLVNAME, LLDP_BASIC_SYSDESC_TLV },
2N/A { LLDP_BASIC_SYSCAPAB_TLVNAME, LLDP_BASIC_SYSCAPAB_TLV },
2N/A { LLDP_BASIC_MGMTADDR_TLVNAME, LLDP_BASIC_MGMTADDR_TLV },
2N/A { LLDP_BASIC_ALL_TLVNAME, LLDP_BASIC_ALL_TLV }
2N/A};
2N/A
2N/Astatic lldp_val_desc_t lldp_8021_tlvs_vals[] = {
2N/A { LLDP_8021_NONE_TLVNAME, LLDP_8021_NONE_TLV },
2N/A { LLDP_8021_VLAN_NAME_TLVNAME, LLDP_8021_VLAN_NAME_TLV },
2N/A { LLDP_8021_PVID_TLVNAME, LLDP_8021_PVID_TLV },
2N/A { LLDP_8021_LINK_AGGR_TLVNAME, LLDP_8021_LINK_AGGR_TLV },
2N/A { LLDP_8021_PFC_TLVNAME, LLDP_8021_PFC_TLV },
2N/A { LLDP_8021_APPLN_TLVNAME, LLDP_8021_APPLN_TLV },
2N/A { LLDP_8021_EVB_TLVNAME, LLDP_8021_EVB_TLV },
2N/A { LLDP_8021_ETSCFG_TLVNAME, LLDP_8021_ETSCFG_TLV },
2N/A { LLDP_8021_ALL_TLVNAME, LLDP_8021_ALL_TLV }
2N/A};
2N/A
2N/Astatic lldp_val_desc_t lldp_8023_tlvs_vals[] = {
2N/A { LLDP_8023_NONE_TLVNAME, LLDP_8023_NONE_TLV },
2N/A { LLDP_8023_MAXFRAMESZ_TLVNAME, LLDP_8023_MAXFRAMESZ_TLV },
2N/A { LLDP_8023_ALL_TLVNAME, LLDP_8023_ALL_TLV }
2N/A};
2N/A
2N/Astatic lldp_val_desc_t lldp_oracle_tlvs_vals[] = {
2N/A { LLDP_VIRT_NONE_TLVNAME, LLDP_VIRT_NONE_TLV },
2N/A { LLDP_VIRT_VNIC_TLVNAME, LLDP_VIRT_VNIC_TLV },
2N/A { LLDP_VIRT_ALL_TLVNAME, LLDP_VIRT_ALL_TLV }
2N/A};
2N/A
2N/Astatic lldp_val_desc_t lldp_onoff_vals[] = {
2N/A { LLDP_ONSTR, B_TRUE },
2N/A { LLDP_OFFSTR, B_FALSE }
2N/A};
2N/A
2N/Alldp_val_desc_t lldp_syscapab_vals[] = {
2N/A { LLDP_SYSCAPAB_OTHER_NAME, LLDP_SYSCAPAB_OTHER },
2N/A { LLDP_SYSCAPAB_REPEATER_NAME, LLDP_SYSCAPAB_REPEATER },
2N/A { LLDP_SYSCAPAB_MACBRIDGE_NAME, LLDP_SYSCAPAB_MACBRIDGE },
2N/A { LLDP_SYSCAPAB_WLAN_AP_NAME, LLDP_SYSCAPAB_WLAN_AP },
2N/A { LLDP_SYSCAPAB_ROUTER_NAME, LLDP_SYSCAPAB_ROUTER },
2N/A { LLDP_SYSCAPAB_TELEPHONE_NAME, LLDP_SYSCAPAB_TELEPHONE },
2N/A { LLDP_SYSCAPAB_DOCSIS_CD_NAME, LLDP_SYSCAPAB_DOCSIS_CDEV },
2N/A { LLDP_SYSCAPAB_STATION_NAME, LLDP_SYSCAPAB_STATION_ONLY },
2N/A { LLDP_SYSCAPAB_CVLAN_NAME, LLDP_SYSCAPAB_CVLAN },
2N/A { LLDP_SYSCAPAB_SVLAN_NAME, LLDP_SYSCAPAB_SVLAN },
2N/A { LLDP_SYSCAPAB_TPMR_NAME, LLDP_SYSCAPAB_TPMR }
2N/A};
2N/A
2N/A#define LLDP_DEF_SUP_SYSCAPAB_NAME "bridge,router,station"
2N/A
2N/Astatic lldp_pd_setf_t i_lldp_set_gstr, i_lldp_set_admin_status,
2N/A i_lldp_set_onoff, i_lldp_set_syscapab, i_lldp_set_tlv,
2N/A i_lldp_set_apt;
2N/A
2N/Astatic lldp_pd_getf_t i_lldp_get_str, i_lldp_get_admin_status, i_lldp_get_tlv,
2N/A i_lldp_get_onoff, i_lldp_get_sup_syscapab,
2N/A i_lldp_get_enab_syscapab, i_lldp_get_apt;
2N/A
2N/A/*
2N/A * All the supported agent/global_tlv/agent_tlv properties.
2N/A */
2N/Astatic lldp_prop_desc_t lldp_prop_table[] = {
2N/A { "mode", LLDP_PROPCLASS_AGENT, LLDP_PROPTYPE_MODE,
2N/A { "disable", LLDP_MODE_DISABLE },
2N/A lldp_mode_vals, LLDP_VALCNT(lldp_mode_vals),
2N/A i_lldp_set_admin_status, i_lldp_get_admin_status, 0 },
2N/A
2N/A { LLDP_BASICTLV_GRPNAME, LLDP_PROPCLASS_AGENT, LLDP_PROPTYPE_BASICTLV,
2N/A { LLDP_BASIC_NONE_TLVNAME, LLDP_BASIC_NONE_TLV},
2N/A lldp_basic_tlvs_vals, LLDP_VALCNT(lldp_basic_tlvs_vals),
2N/A i_lldp_set_tlv, i_lldp_get_tlv, LLDP_PROP_MULVAL },
2N/A
2N/A { LLDP_8021TLV_GRPNAME, LLDP_PROPCLASS_AGENT, LLDP_PROPTYPE_8021TLV,
2N/A { LLDP_8021_NONE_TLVNAME, LLDP_8021_NONE_TLV },
2N/A lldp_8021_tlvs_vals, LLDP_VALCNT(lldp_8021_tlvs_vals),
2N/A i_lldp_set_tlv, i_lldp_get_tlv, LLDP_PROP_MULVAL },
2N/A
2N/A { LLDP_8023TLV_GRPNAME, LLDP_PROPCLASS_AGENT, LLDP_PROPTYPE_8023TLV,
2N/A { LLDP_8023_NONE_TLVNAME, LLDP_8023_NONE_TLV },
2N/A lldp_8023_tlvs_vals, LLDP_VALCNT(lldp_8023_tlvs_vals),
2N/A i_lldp_set_tlv, i_lldp_get_tlv, LLDP_PROP_MULVAL },
2N/A
2N/A { LLDP_VIRTTLV_GRPNAME, LLDP_PROPCLASS_AGENT, LLDP_PROPTYPE_VIRTTLV,
2N/A { LLDP_VIRT_NONE_TLVNAME, LLDP_VIRT_NONE_TLV },
2N/A lldp_oracle_tlvs_vals, LLDP_VALCNT(lldp_oracle_tlvs_vals),
2N/A i_lldp_set_tlv, i_lldp_get_tlv, LLDP_PROP_MULVAL },
2N/A
2N/A { "supported", LLDP_PROPCLASS_SYSCAPAB_TLV, LLDP_PROPTYPE_SUP_SYSCAPAB,
2N/A { LLDP_DEF_SUP_SYSCAPAB_NAME, (LLDP_SYSCAPAB_ROUTER |
2N/A LLDP_SYSCAPAB_MACBRIDGE | LLDP_SYSCAPAB_STATION_ONLY) },
2N/A lldp_syscapab_vals, LLDP_VALCNT(lldp_syscapab_vals),
2N/A i_lldp_set_syscapab, i_lldp_get_sup_syscapab,
2N/A LLDP_PROP_MULVAL|LLDP_PROP_GLOBAL },
2N/A
2N/A { "enabled", LLDP_PROPCLASS_SYSCAPAB_TLV, LLDP_PROPTYPE_ENAB_SYSCAPAB,
2N/A { "", 0 }, NULL, 0, i_lldp_set_syscapab, i_lldp_get_enab_syscapab,
2N/A LLDP_PROP_MULVAL|LLDP_PROP_GLOBAL },
2N/A
2N/A { "ipaddr", LLDP_PROPCLASS_MGMTADDR_TLV, LLDP_PROPTYPE_IPADDR,
2N/A { "", 0 }, NULL, 0, i_lldp_set_gstr, i_lldp_get_str,
2N/A LLDP_PROP_GLOBAL },
2N/A
2N/A { "willing", LLDP_PROPCLASS_PFC_TLV, LLDP_PROPTYPE_WILLING,
2N/A { "on", B_TRUE }, lldp_onoff_vals, LLDP_VALCNT(lldp_onoff_vals),
2N/A i_lldp_set_onoff, i_lldp_get_onoff, 0 },
2N/A
2N/A { "apt", LLDP_PROPCLASS_APPLN_TLV, LLDP_PROPTYPE_APPLN,
2N/A { "", 0 }, NULL, 0, i_lldp_set_apt, i_lldp_get_apt,
2N/A LLDP_PROP_MULVAL },
2N/A
2N/A { "willing", LLDP_PROPCLASS_APPLN_TLV, LLDP_PROPTYPE_WILLING,
2N/A { "off", B_FALSE }, lldp_onoff_vals, LLDP_VALCNT(lldp_onoff_vals),
2N/A i_lldp_set_onoff, i_lldp_get_onoff, 0 },
2N/A
2N/A { "willing", LLDP_PROPCLASS_ETSCFG_TLV, LLDP_PROPTYPE_WILLING,
2N/A { "on", B_TRUE }, lldp_onoff_vals, LLDP_VALCNT(lldp_onoff_vals),
2N/A i_lldp_set_onoff, i_lldp_get_onoff, 0 },
2N/A
2N/A { NULL, LLDP_PROPCLASS_NONE, LLDP_PROPTYPE_NONE, {NULL, 0},
2N/A NULL, 0, NULL, NULL, 0}
2N/A};
2N/A
2N/Aconst char *
2N/Alldp_mode2str(lldp_admin_status_t mode)
2N/A{
2N/A int i, count = LLDP_VALCNT(lldp_mode_vals);
2N/A
2N/A for (i = 0; i < count; i++) {
2N/A if (lldp_mode_vals[i].lvd_val == mode)
2N/A return (lldp_mode_vals[i].lvd_name);
2N/A }
2N/A return (NULL);
2N/A
2N/A}
2N/A
2N/Astatic lldp_prop_desc_t *
2N/Ai_lldp_get_propdesc(lldp_propclass_t pclass, const char *pname)
2N/A{
2N/A lldp_prop_desc_t *pdp = lldp_prop_table;
2N/A
2N/A for (; pdp->lpd_name != NULL; pdp++) {
2N/A if ((pdp->lpd_pclass == pclass) && pname != NULL &&
2N/A strcmp(pdp->lpd_name, pname) == 0) {
2N/A break;
2N/A }
2N/A }
2N/A
2N/A return (pdp->lpd_name == NULL ? NULL : pdp);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_getvalue_from_daemon(const char *laname, lldp_prop_desc_t *pdp,
2N/A char *pval, uint_t *psize)
2N/A{
2N/A lldpd_door_lprops_t lprop;
2N/A lldpd_gprops_retval_t rval;
2N/A int err;
2N/A
2N/A bzero(&lprop, sizeof (lldpd_door_lprops_t));
2N/A bzero(&rval, sizeof (lldpd_gprops_retval_t));
2N/A lprop.lp_cmd = LLDPD_CMD_GET_PROP;
2N/A lprop.lp_pclass = pdp->lpd_pclass;
2N/A lprop.lp_ptype = pdp->lpd_ptype;
2N/A /* for global TLV properties `laname' will be NULL */
2N/A if (laname != NULL) {
2N/A (void) strlcpy(lprop.lp_laname, laname,
2N/A sizeof (lprop.lp_laname));
2N/A }
2N/A err = lldp_door_call(&lprop, sizeof (lprop), &rval,
2N/A sizeof (rval));
2N/A if (err == 0)
2N/A *psize = snprintf(pval, *psize, "%s", rval.lpr_pval);
2N/A return (lldp_errno2status(err));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_setvalue_in_daemon(const char *laname, lldp_prop_desc_t *pdp,
2N/A lldp_pval_t lpval, uint32_t flags)
2N/A{
2N/A lldpd_door_lprops_t lprop;
2N/A lldpd_sprops_retval_t rval;
2N/A int err;
2N/A
2N/A bzero(&lprop, sizeof (lldpd_door_lprops_t));
2N/A lprop.lp_cmd = LLDPD_CMD_SET_PROP;
2N/A lprop.lp_pclass = pdp->lpd_pclass;
2N/A lprop.lp_ptype = pdp->lpd_ptype;
2N/A /* for global TLV properties `laname' will be NULL */
2N/A if (laname != NULL) {
2N/A (void) strlcpy(lprop.lp_laname, laname,
2N/A sizeof (lprop.lp_laname));
2N/A }
2N/A lprop.lp_pval = lpval;
2N/A lprop.lp_flags = flags;
2N/A err = lldp_door_call(&lprop, sizeof (lprop), &rval, sizeof (rval));
2N/A return (lldp_errno2status(err));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_tlv(const char *laname, lldp_prop_desc_t *pdp, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A
2N/A if (valtype != LLDP_OPT_ACTIVE)
2N/A return (status);
2N/A
2N/A return (i_lldp_getvalue_from_daemon(laname, pdp, pval, psize));
2N/A}
2N/A
2N/A/*
2N/A * Input is a comma separated list of bandwidths. The sum of the
2N/A * bandwidths must be == 100. We can have a maximum of 8 entries
2N/A */
2N/Astatic int
2N/Ai_lldp_validate_batstr(char *batval)
2N/A{
2N/A int cnt;
2N/A int sum = 0;
2N/A uint8_t bat[8];
2N/A int err = 0;
2N/A
2N/A bzero(bat, sizeof (uint8_t) * 8);
2N/A if ((err = lldp_str2arr(batval, bat, 8)) != 0)
2N/A return (err);
2N/A
2N/A for (cnt = 0; cnt < 8; cnt++)
2N/A sum += bat[cnt];
2N/A
2N/A if (sum != 100)
2N/A return (EINVAL);
2N/A
2N/A return (err);
2N/A
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_apt(const char *laname, lldp_prop_desc_t *pdp, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A
2N/A switch (valtype) {
2N/A case LLDP_OPT_ACTIVE:
2N/A status = i_lldp_getvalue_from_daemon(laname, pdp, pval,
2N/A psize);
2N/A break;
2N/A case LLDP_OPT_POSSIBLE:
2N/A *psize = snprintf(pval, *psize, "--");
2N/A status = LLDP_STATUS_OK;
2N/A break;
2N/A }
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_apt(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A lldp_status_t status;
2N/A lldp_pval_t lpval;
2N/A
2N/A (void) strlcpy(lpval.lpv_strval, pval, sizeof (lpval.lpv_strval));
2N/A status = i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags);
2N/A if (status == LLDP_STATUS_NOTFOUND && (flags & LLDP_OPT_DEFAULT) != 0)
2N/A status = LLDP_STATUS_OK;
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_tlv(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A uint32_t tlvmask;
2N/A lldp_pval_t lpval;
2N/A lldp_status_t status;
2N/A
2N/A status = lldp_str2mask(pdp->lpd_name, pval, &tlvmask);
2N/A if (status != LLDP_STATUS_OK)
2N/A return (status);
2N/A
2N/A lpval.lpv_u32 = tlvmask;
2N/A status = i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags);
2N/A if (status == LLDP_STATUS_NOTFOUND && (flags & LLDP_OPT_DEFAULT) != 0)
2N/A status = LLDP_STATUS_OK;
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_admin_status(const char *laname, lldp_prop_desc_t *pdp,
2N/A char *pval, uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A
2N/A if (valtype != LLDP_OPT_ACTIVE)
2N/A return (status);
2N/A
2N/A return (i_lldp_getvalue_from_daemon(laname, pdp, pval, psize));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_admin_status(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A lldp_pval_t lpval;
2N/A lldp_val_desc_t *vd;
2N/A int i;
2N/A
2N/A /* check if the pval is one of the possible values */
2N/A vd = pdp->lpd_optval;
2N/A for (i = 0; i < pdp->lpd_noptval; i++, vd++) {
2N/A if (strcmp(vd->lvd_name, pval) == 0)
2N/A break;
2N/A }
2N/A if (i == pdp->lpd_noptval)
2N/A return (LLDP_STATUS_BADVAL);
2N/A
2N/A lpval.lpv_u32 = vd->lvd_val;
2N/A return (i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_str(const char *laname, lldp_prop_desc_t *pdp, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A
2N/A if (valtype != LLDP_OPT_ACTIVE)
2N/A return (status);
2N/A
2N/A return (i_lldp_getvalue_from_daemon(laname, pdp, pval, psize));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_gstr(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A lldp_status_t status;
2N/A lldp_pval_t lpval;
2N/A
2N/A (void) strlcpy(lpval.lpv_strval, pval, sizeof (lpval.lpv_strval));
2N/A status = i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags);
2N/A if (status != LLDP_STATUS_OK) {
2N/A if (status == LLDP_STATUS_NOTFOUND &&
2N/A (flags & LLDP_OPT_DEFAULT)) {
2N/A status = LLDP_STATUS_OK;
2N/A }
2N/A }
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_onoff(const char *laname, lldp_prop_desc_t *pdp, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A uint_t valsize;
2N/A int bval;
2N/A
2N/A if (valtype != LLDP_OPT_ACTIVE)
2N/A return (status);
2N/A
2N/A valsize = *psize;
2N/A status = i_lldp_getvalue_from_daemon(laname, pdp, pval, &valsize);
2N/A if (status == LLDP_STATUS_OK) {
2N/A if (valsize < *psize) {
2N/A bval = atoi(pval);
2N/A *psize = snprintf(pval, *psize, "%s",
2N/A (bval == 1 ? LLDP_ONSTR : LLDP_OFFSTR));
2N/A } else {
2N/A *psize = valsize;
2N/A }
2N/A }
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_onoff(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_OK;
2N/A lldp_pval_t lpval;
2N/A lldp_val_desc_t *vd;
2N/A int i;
2N/A
2N/A /* check if the pval is one of the possible values */
2N/A vd = pdp->lpd_optval;
2N/A for (i = 0; i < pdp->lpd_noptval; i++, vd++) {
2N/A if (strcmp(vd->lvd_name, pval) == 0)
2N/A break;
2N/A }
2N/A if (i == pdp->lpd_noptval)
2N/A return (LLDP_STATUS_BADVAL);
2N/A
2N/A lpval.lpv_u32 = vd->lvd_val;
2N/A status = i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags);
2N/A if (status == LLDP_STATUS_NOTFOUND && (flags & LLDP_OPT_DEFAULT) != 0)
2N/A status = LLDP_STATUS_OK;
2N/A return (status);
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_sup_syscapab(const char *laname, lldp_prop_desc_t *pdp,
2N/A char *pval, uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A
2N/A if (valtype != LLDP_OPT_ACTIVE)
2N/A return (status);
2N/A
2N/A return (i_lldp_getvalue_from_daemon(laname, pdp, pval, psize));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_set_syscapab(const char *laname, lldp_prop_desc_t *pdp, void *pval,
2N/A uint_t flags)
2N/A{
2N/A lldp_status_t status;
2N/A lldp_pval_t lpval;
2N/A uint16_t capab;
2N/A
2N/A if ((status = lldp_str2syscapab(pval, &capab)) != LLDP_STATUS_OK)
2N/A return (status);
2N/A
2N/A lpval.lpv_u32 = capab;
2N/A return (i_lldp_setvalue_in_daemon(laname, pdp, lpval, flags));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_get_enab_syscapab(const char *laname, lldp_prop_desc_t *pdp,
2N/A char *pval, uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_status_t status = LLDP_STATUS_NOTSUP;
2N/A lldp_prop_desc_t *tmp;
2N/A
2N/A switch (valtype) {
2N/A case LLDP_OPT_POSSIBLE:
2N/A /*
2N/A * Possible value for this property is the current value of the
2N/A * "supported" propertye.
2N/A */
2N/A tmp = i_lldp_get_propdesc(LLDP_PROPCLASS_SYSCAPAB_TLV,
2N/A "supported");
2N/A status = i_lldp_getvalue_from_daemon(laname, tmp, pval, psize);
2N/A break;
2N/A case LLDP_OPT_ACTIVE:
2N/A status = i_lldp_getvalue_from_daemon(laname, pdp, pval, psize);
2N/A break;
2N/A default:
2N/A break;
2N/A }
2N/A return (status);
2N/A}
2N/A
2N/A/*
2N/A * Private interfaces for VDP service to signal if EVB state on a port
2N/A * should be updated or not. This will be used when VDP service is enabled/
2N/A * disabled after/before LLDP service.
2N/A */
2N/Astatic lldp_status_t
2N/Ai_lldp_set_evbstate_in_daemon(const char *laname, boolean_t set)
2N/A{
2N/A lldpd_door_lprops_t lprop;
2N/A lldpd_sprops_retval_t rval;
2N/A int err;
2N/A
2N/A bzero(&lprop, sizeof (lldpd_door_lprops_t));
2N/A lprop.lp_cmd = LLDPD_CMD_SET_PROP;
2N/A lprop.lp_pclass = LLDP_PROPCLASS_EVB_TLV;
2N/A lprop.lp_ptype = set ? LLDP_PROPTYPE_EVB_SET : LLDP_PROPTYPE_EVB_UNSET;
2N/A (void) strlcpy(lprop.lp_laname, laname, sizeof (lprop.lp_laname));
2N/A err = lldp_door_call(&lprop, sizeof (lprop), &rval, sizeof (rval));
2N/A return (lldp_errno2status(err));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_set_evb_state(const char *laname)
2N/A{
2N/A return (i_lldp_set_evbstate_in_daemon(laname, B_TRUE));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_unset_evb_state(const char *laname)
2N/A{
2N/A return (i_lldp_set_evbstate_in_daemon(laname, B_FALSE));
2N/A}
2N/A
2N/Alldp_status_t
2N/Ai_lldp_setprop_common(const char *laname, const char *pname, char *pval,
2N/A lldp_propclass_t pclass, uint_t pflags)
2N/A{
2N/A lldp_prop_desc_t *pdp;
2N/A boolean_t reset = (pflags & LLDP_OPT_DEFAULT);
2N/A uint32_t flagsmask = (LLDP_OPT_ACTIVE|LLDP_OPT_DEFAULT|\
2N/A LLDP_OPT_APPEND|LLDP_OPT_REMOVE);
2N/A
2N/A if (pname == NULL || (!reset && pval == NULL) ||
2N/A ((pflags & flagsmask) != LLDP_OPT_ACTIVE &&
2N/A (pflags & flagsmask) != LLDP_OPT_DEFAULT &&
2N/A (pflags & flagsmask) != LLDP_OPT_APPEND &&
2N/A (pflags & flagsmask) != LLDP_OPT_REMOVE)) {
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A if ((pdp = i_lldp_get_propdesc(pclass, pname)) == NULL)
2N/A return (LLDP_STATUS_PROPUNKNOWN);
2N/A
2N/A /*
2N/A * if it's not a multi-valued property then there should be no
2N/A * LLDP_OPT_APPEND or LLDP_OPT_REMOVE flag.
2N/A */
2N/A if (!(pdp->lpd_flags & LLDP_PROP_MULVAL) &&
2N/A (pflags & (LLDP_OPT_APPEND|LLDP_OPT_REMOVE))) {
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A /*
2N/A * If its a global property and `laname' was provided, return error.
2N/A * If its a per-agent property and `laname' was not provided, return
2N/A * error.
2N/A */
2N/A if (pdp->lpd_flags & LLDP_PROP_GLOBAL) {
2N/A if (laname != NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A } else {
2N/A if (laname == NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A if (pflags & LLDP_OPT_DEFAULT) {
2N/A /*
2N/A * reset operation, see if a default value is specified. If
2N/A * specified we use that value as the value to be set. If
2N/A * it's NULL then we let the daemon `lldpd', to handle the
2N/A * default case.
2N/A */
2N/A if (pdp->lpd_defval.lvd_name != NULL)
2N/A pval = pdp->lpd_defval.lvd_name;
2N/A }
2N/A
2N/A return (pdp->lpd_setf(laname, pdp, pval, pflags));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_set_agentprop(const char *laname, const char *pname, char *pval,
2N/A uint_t pflags)
2N/A{
2N/A if (laname == NULL || *laname == '\0')
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_setprop_common(laname, pname, pval, LLDP_PROPCLASS_AGENT,
2N/A pflags));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_set_global_tlvprop(const char *tlvname, const char *pname, char *pval,
2N/A uint_t pflags)
2N/A{
2N/A lldp_propclass_t pclass;
2N/A
2N/A if ((pclass = lldp_tlvname2pclass(tlvname)) == LLDP_PROPCLASS_NONE)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_setprop_common(NULL, pname, pval, pclass, pflags));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_set_agent_tlvprop(const char *laname, const char *tlvname,
2N/A const char *pname, char *pval, uint_t pflags)
2N/A{
2N/A lldp_propclass_t pclass;
2N/A
2N/A if (laname == NULL || *laname == '\0')
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A if ((pclass = lldp_tlvname2pclass(tlvname)) == LLDP_PROPCLASS_NONE)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_setprop_common(laname, pname, pval, pclass, pflags));
2N/A}
2N/A
2N/Astatic lldp_status_t
2N/Ai_lldp_pd2permstr(lldp_prop_desc_t *pdp, char *buf, uint_t *bufsize)
2N/A{
2N/A uint_t perm;
2N/A
2N/A perm = 0;
2N/A if (pdp->lpd_setf != NULL)
2N/A perm |= MAC_PROP_PERM_WRITE;
2N/A if (pdp->lpd_getf != NULL)
2N/A perm |= MAC_PROP_PERM_READ;
2N/A
2N/A *bufsize = snprintf(buf, *bufsize, "%c%c",
2N/A ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
2N/A ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
2N/A
2N/A return (LLDP_STATUS_OK);
2N/A}
2N/A
2N/Avoid
2N/Alldp_bitmap2str(uint8_t val, char *buf, uint_t bufsize)
2N/A{
2N/A uint_t mask = 128;
2N/A int i;
2N/A
2N/A for (i = 0; i < 8; i++, mask >>= 1) {
2N/A if (mask & val)
2N/A (void) strlcat(buf, "1", bufsize);
2N/A else
2N/A (void) strlcat(buf, "0", bufsize);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Function to retrieve property value for a given lldp agent represented by
2N/A * link `laname'. If `laname' is set to NULL then the`pname' represents a
2N/A * global property.
2N/A *
2N/A * `valtype' determines the type of value that will be retrieved.
2N/A * LLDP_OPT_ACTIVE - current value of the property (active config)
2N/A * LLDP_OPT_DEFAULT - default hard coded value (boot-time value)
2N/A * LLDP_OPT_PERM - read/write permissions for the value
2N/A * LLDP_OPT_POSSIBLE - range of values
2N/A *
2N/A * Note: Since we do not support temporary operation, the current value is also
2N/A * the persistent value.
2N/A */
2N/Alldp_status_t
2N/Ai_lldp_getprop_common(const char *laname, const char *pname, char *pval,
2N/A uint_t *psize, uint_t valtype, lldp_propclass_t pclass)
2N/A{
2N/A lldp_prop_desc_t *pdp;
2N/A lldp_status_t status = LLDP_STATUS_OK;
2N/A uint_t cnt, i, bufsize;
2N/A
2N/A if (pname == NULL || (pval == NULL && *psize != 0))
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A if ((pdp = i_lldp_get_propdesc(pclass, pname)) == NULL)
2N/A return (LLDP_STATUS_PROPUNKNOWN);
2N/A
2N/A /*
2N/A * If its a global property and `laname' was provided, return error.
2N/A * If its a per-agent property and `laname' was not provided, return
2N/A * error.
2N/A */
2N/A if (pdp->lpd_flags & LLDP_PROP_GLOBAL) {
2N/A if (laname != NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A } else {
2N/A if (laname == NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A bzero(pval, *psize);
2N/A bufsize = *psize;
2N/A switch (valtype) {
2N/A case LLDP_OPT_PERM:
2N/A status = i_lldp_pd2permstr(pdp, pval, &bufsize);
2N/A break;
2N/A case LLDP_OPT_ACTIVE:
2N/A status = pdp->lpd_getf(laname, pdp, pval, &bufsize,
2N/A LLDP_OPT_ACTIVE);
2N/A break;
2N/A case LLDP_OPT_DEFAULT:
2N/A if (pdp->lpd_defval.lvd_name == NULL) {
2N/A status = LLDP_STATUS_NOTSUP;
2N/A break;
2N/A }
2N/A bufsize = strlcpy(pval, pdp->lpd_defval.lvd_name, bufsize);
2N/A break;
2N/A case LLDP_OPT_POSSIBLE:
2N/A cnt = pdp->lpd_noptval;
2N/A if (cnt == 0) {
2N/A status = pdp->lpd_getf(laname, pdp, pval, &bufsize,
2N/A LLDP_OPT_POSSIBLE);
2N/A } else {
2N/A uint_t nbytes = 0, tbytes = 0;
2N/A
2N/A for (i = 0; i < cnt; i++) {
2N/A if (i == cnt - 1) {
2N/A nbytes = snprintf(pval, bufsize, "%s",
2N/A pdp->lpd_optval[i].lvd_name);
2N/A } else {
2N/A nbytes = snprintf(pval, bufsize, "%s,",
2N/A pdp->lpd_optval[i].lvd_name);
2N/A }
2N/A tbytes += nbytes;
2N/A if (tbytes >= *psize) {
2N/A /*
2N/A * lets still continue and find the
2N/A * actual buffer size needed.
2N/A */
2N/A pval = NULL;
2N/A bufsize = 0;
2N/A } else {
2N/A pval += nbytes;
2N/A bufsize -= nbytes;
2N/A }
2N/A }
2N/A bufsize = tbytes;
2N/A }
2N/A break;
2N/A default:
2N/A status = LLDP_STATUS_BADARG;
2N/A break;
2N/A }
2N/A
2N/A if (status == LLDP_STATUS_OK && bufsize >= *psize) {
2N/A status = LLDP_STATUS_TOOSMALL;
2N/A *psize = bufsize;
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_get_agentprop(const char *laname, const char *pname, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A if (laname == NULL || *laname == '\0')
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_getprop_common(laname, pname, pval, psize,
2N/A valtype, LLDP_PROPCLASS_AGENT));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_get_global_tlvprop(const char *tlvname, const char *pname, char *pval,
2N/A uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_propclass_t pclass;
2N/A
2N/A if ((pclass = lldp_tlvname2pclass(tlvname)) == LLDP_PROPCLASS_NONE)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_getprop_common(NULL, pname, pval, psize, valtype,
2N/A pclass));
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_get_agent_tlvprop(const char *laname, const char *tlvname,
2N/A const char *pname, char *pval, uint_t *psize, uint_t valtype)
2N/A{
2N/A lldp_propclass_t pclass;
2N/A
2N/A if (laname == NULL || *laname == '\0')
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A if ((pclass = lldp_tlvname2pclass(tlvname)) == LLDP_PROPCLASS_NONE)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A return (i_lldp_getprop_common(laname, pname, pval, psize, valtype,
2N/A pclass));
2N/A}
2N/A
2N/A/*
2N/A * Parses the buffer, for name-value pairs and creates nvlist. The boolean
2N/A * `rvalue' defines if the `inbuf' contains just names or both names
2N/A * and values
2N/A */
2N/Aint
2N/Alldp_str2nvlist(const char *inbuf, nvlist_t **nvl, boolean_t rvalue)
2N/A{
2N/A char *nv, *name, *val, *buf, *cp, *sep, *dupbuf;
2N/A int err;
2N/A
2N/A if (inbuf == NULL || inbuf[0] == '\0' || nvl == NULL)
2N/A return (EINVAL);
2N/A *nvl = NULL;
2N/A
2N/A /*
2N/A * If `rval' is B_FALSE, then `inbuf' should not contain values
2N/A */
2N/A if (!rvalue && strchr(inbuf, '=') != NULL)
2N/A return (EINVAL);
2N/A
2N/A if ((dupbuf = buf = strdup(inbuf)) == NULL)
2N/A return (errno);
2N/A
2N/A while (isspace(*buf))
2N/A buf++;
2N/A
2N/A if (*buf == '\0') {
2N/A err = EINVAL;
2N/A goto fail;
2N/A }
2N/A /*
2N/A * Note that the values can be multi-valued with comma as the
2N/A * separator. For example:
2N/A * prop1=va11,val2,val3,prop2=val4
2N/A * We will convert the above to,
2N/A * prop1=val1,val2,val3;prop2=val4
2N/A */
2N/A if (rvalue) {
2N/A char *tmp;
2N/A
2N/A cp = buf;
2N/A while ((tmp = strchr(cp, '=')) != NULL) {
2N/A *tmp = '\0';
2N/A if ((cp = strrchr(cp, ',')) != NULL)
2N/A *cp = ';';
2N/A cp = tmp;
2N/A *cp++ = '=';
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * work on one nvpair at a time and extract the name and value.
2N/A */
2N/A sep = (rvalue ? ";" : ",");
2N/A while ((nv = strsep(&buf, sep)) != NULL) {
2N/A name = nv;
2N/A if ((val = strchr(nv, '=')) != NULL)
2N/A *val++ = '\0';
2N/A if (*nvl == NULL &&
2N/A (err = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0)) != 0)
2N/A goto fail;
2N/A if (nvlist_exists(*nvl, name)) {
2N/A err = EEXIST;
2N/A goto fail;
2N/A }
2N/A if (val == NULL)
2N/A err = nvlist_add_string(*nvl, name, "");
2N/A else
2N/A err = nvlist_add_string(*nvl, name, val);
2N/A if (err != 0)
2N/A goto fail;
2N/A }
2N/A free(dupbuf);
2N/A return (0);
2N/Afail:
2N/A free(dupbuf);
2N/A nvlist_free(*nvl);
2N/A *nvl = NULL;
2N/A return (err);
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_mask2str(const char *tlvgrpname, uint32_t tlvmask, char *buf,
2N/A uint_t *bufsize, boolean_t expand)
2N/A{
2N/A lldp_prop_desc_t *pdp;
2N/A int i, count = 0;
2N/A uint32_t mask, allmask;
2N/A
2N/A pdp = i_lldp_get_propdesc(LLDP_PROPCLASS_AGENT, tlvgrpname);
2N/A if (pdp == NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A allmask = pdp->lpd_optval[pdp->lpd_noptval - 1].lvd_val;
2N/A *buf = '\0';
2N/A if (tlvmask == 0) {
2N/A *bufsize = snprintf(buf, *bufsize, "%s",
2N/A pdp->lpd_optval[0].lvd_name);
2N/A } else if (tlvmask == allmask && !expand) {
2N/A *bufsize = snprintf(buf, *bufsize, "%s",
2N/A pdp->lpd_optval[pdp->lpd_noptval - 1].lvd_name);
2N/A } else {
2N/A uint_t nbytes = 0, sz = *bufsize, tbytes = 0;
2N/A
2N/A count = pdp->lpd_noptval - 1;
2N/A for (i = 1, mask = 1; i < count; i++, mask <<= 1) {
2N/A if (!(tlvmask & mask))
2N/A continue;
2N/A if (tbytes == 0) {
2N/A nbytes = snprintf(buf, sz, "%s",
2N/A pdp->lpd_optval[i].lvd_name);
2N/A } else {
2N/A nbytes = snprintf(buf, sz, ",%s",
2N/A pdp->lpd_optval[i].lvd_name);
2N/A }
2N/A tbytes += nbytes;
2N/A if (tbytes >= *bufsize) {
2N/A /*
2N/A * lets still continue and find the
2N/A * actual buffer size needed.
2N/A */
2N/A buf = NULL;
2N/A sz = 0;
2N/A } else {
2N/A buf += nbytes;
2N/A sz -= nbytes;
2N/A }
2N/A }
2N/A *bufsize = nbytes;
2N/A }
2N/A return (LLDP_STATUS_OK);
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_str2mask(const char *tlvgrpname, char *tlvstr, uint32_t *tlvmask)
2N/A{
2N/A lldp_prop_desc_t *pdp;
2N/A uint32_t mask;
2N/A int i, err;
2N/A nvlist_t *nvl;
2N/A nvpair_t *nvp;
2N/A uint_t tlvcnt = 0;
2N/A char *tlvname;
2N/A
2N/A pdp = i_lldp_get_propdesc(LLDP_PROPCLASS_AGENT, tlvgrpname);
2N/A if (pdp == NULL)
2N/A return (LLDP_STATUS_BADARG);
2N/A
2N/A if ((err = lldp_str2nvlist(tlvstr, &nvl, B_FALSE)) != 0)
2N/A return (lldp_errno2status(err));
2N/A
2N/A for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
2N/A nvp = nvlist_next_nvpair(nvl, nvp)) {
2N/A tlvcnt++;
2N/A }
2N/A
2N/A /*
2N/A * you cannot possibly specify more values then the possible number
2N/A * of TLV values.
2N/A */
2N/A if (tlvcnt > pdp->lpd_noptval) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A *tlvmask = 0;
2N/A for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
2N/A nvp = nvlist_next_nvpair(nvl, nvp)) {
2N/A tlvname = nvpair_name(nvp);
2N/A /*
2N/A * one cannot have `none' or `all' and at the
2N/A * same time specify other tlvs.
2N/A */
2N/A if ((strcmp(tlvname, "none") == 0 ||
2N/A strcmp(tlvname, "all") == 0) && tlvcnt > 1) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A for (i = 0; i < pdp->lpd_noptval; i++) {
2N/A if (strcmp(pdp->lpd_optval[i].lvd_name, tlvname) == 0)
2N/A break;
2N/A }
2N/A if (i == pdp->lpd_noptval) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADVAL);
2N/A }
2N/A mask = pdp->lpd_optval[i].lvd_val;
2N/A if (*tlvmask == 0)
2N/A *tlvmask = mask;
2N/A else
2N/A *tlvmask |= mask;
2N/A }
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_OK);
2N/A}
2N/A
2N/Alldp_status_t
2N/Alldp_walk_prop(lldp_prop_wfunc_t *func, void *arg, lldp_propclass_t pclass)
2N/A{
2N/A lldp_prop_desc_t *pdp = lldp_prop_table;
2N/A
2N/A /*
2N/A * We walk through all the properties for a given property class
2N/A * `pclass'.
2N/A */
2N/A for (; pdp->lpd_name != NULL; pdp++) {
2N/A if ((pdp->lpd_pclass & pclass)) {
2N/A if (!func(lldp_pclass2tlvname(pdp->lpd_pclass),
2N/A pdp->lpd_name, arg))
2N/A break;
2N/A }
2N/A }
2N/A return (LLDP_STATUS_OK);
2N/A}
2N/A
2N/Aboolean_t
2N/Alldp_is_enabled(const char *laname)
2N/A{
2N/A lldp_prop_desc_t *pdp;
2N/A lldp_status_t status;
2N/A char pval[LLDP_MAXPROPVALLEN];
2N/A uint_t psize = sizeof (pval);
2N/A
2N/A pdp = i_lldp_get_propdesc(LLDP_PROPCLASS_AGENT, "mode");
2N/A assert(pdp != NULL);
2N/A status = i_lldp_getvalue_from_daemon(laname, pdp, pval, &psize);
2N/A if (status != LLDP_STATUS_OK)
2N/A return (B_FALSE);
2N/A return (strcmp(pval, "disable") != 0);
2N/A}
2N/A
2N/A/*
2N/A * convert the comma separated string capability values into a mask
2N/A */
2N/Alldp_status_t
2N/Alldp_str2syscapab(const char *capabstr, uint16_t *capab)
2N/A{
2N/A int err;
2N/A nvlist_t *nvl;
2N/A nvpair_t *nvp;
2N/A uint_t cnt = 0, i;
2N/A char *capabname;
2N/A lldp_prop_desc_t *pdp;
2N/A
2N/A if (capabstr != NULL && strlen(capabstr) == 0) {
2N/A *capab = 0;
2N/A return (LLDP_STATUS_OK);
2N/A }
2N/A
2N/A if ((err = lldp_str2nvlist(capabstr, &nvl, B_FALSE)) != 0)
2N/A return (lldp_errno2status(err));
2N/A
2N/A if ((pdp = i_lldp_get_propdesc(LLDP_PROPCLASS_SYSCAPAB_TLV,
2N/A "supported")) == NULL) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
2N/A nvp = nvlist_next_nvpair(nvl, nvp)) {
2N/A cnt++;
2N/A }
2N/A
2N/A if (cnt > pdp->lpd_noptval) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A
2N/A *capab = 0;
2N/A for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
2N/A nvp = nvlist_next_nvpair(nvl, nvp)) {
2N/A capabname = nvpair_name(nvp);
2N/A for (i = 0; i < pdp->lpd_noptval; i++) {
2N/A if (strcmp(pdp->lpd_optval[i].lvd_name, capabname) == 0)
2N/A break;
2N/A }
2N/A if (i == pdp->lpd_noptval) {
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_BADARG);
2N/A }
2N/A *capab |= pdp->lpd_optval[i].lvd_val;
2N/A }
2N/A nvlist_free(nvl);
2N/A return (LLDP_STATUS_OK);
2N/A}
2N/A
2N/Auint_t
2N/Alldp_tlvname2pclass(const char *tlvname)
2N/A{
2N/A if (tlvname == NULL)
2N/A return (LLDP_PROPCLASS_NONE);
2N/A else if (strcmp(tlvname, LLDP_BASIC_SYSCAPAB_TLVNAME) == 0)
2N/A return (LLDP_PROPCLASS_SYSCAPAB_TLV);
2N/A else if (strcmp(tlvname, LLDP_BASIC_MGMTADDR_TLVNAME) == 0)
2N/A return (LLDP_PROPCLASS_MGMTADDR_TLV);
2N/A else if (strcmp(tlvname, LLDP_8021_PFC_TLVNAME) == 0)
2N/A return (LLDP_PROPCLASS_PFC_TLV);
2N/A else if (strcmp(tlvname, LLDP_8021_APPLN_TLVNAME) == 0)
2N/A return (LLDP_PROPCLASS_APPLN_TLV);
2N/A else if (strcmp(tlvname, LLDP_8021_ETSCFG_TLVNAME) == 0)
2N/A return (LLDP_8021_ETSCFG_TLV);
2N/A else if (strcmp(tlvname, LLDP_8021_ETSRECO_TLVNAME) == 0)
2N/A return (LLDP_8021_ETSRECO_TLV);
2N/A return (LLDP_PROPCLASS_NONE);
2N/A}
2N/A
2N/Achar *
2N/Alldp_pclass2tlvname(lldp_propclass_t pclass)
2N/A{
2N/A char *str = NULL;
2N/A
2N/A switch (pclass) {
2N/A case LLDP_PROPCLASS_SYSCAPAB_TLV:
2N/A str = LLDP_BASIC_SYSCAPAB_TLVNAME;
2N/A break;
2N/A case LLDP_PROPCLASS_MGMTADDR_TLV:
2N/A str = LLDP_BASIC_MGMTADDR_TLVNAME;
2N/A break;
2N/A case LLDP_PROPCLASS_PFC_TLV:
2N/A str = LLDP_8021_PFC_TLVNAME;
2N/A break;
2N/A case LLDP_PROPCLASS_APPLN_TLV:
2N/A str = LLDP_8021_APPLN_TLVNAME;
2N/A break;
2N/A case LLDP_8021_ETSCFG_TLV:
2N/A str = LLDP_8021_ETSCFG_TLVNAME;
2N/A break;
2N/A case LLDP_8021_ETSRECO_TLV:
2N/A str = LLDP_8021_ETSRECO_TLVNAME;
2N/A break;
2N/A default:
2N/A break;
2N/A }
2N/A return (str);
2N/A}
2N/A
2N/Achar *
2N/Alldp_ptype2pname(lldp_proptype_t ptype)
2N/A{
2N/A char *str = NULL;
2N/A
2N/A switch (ptype) {
2N/A case LLDP_PROPTYPE_MODE:
2N/A str = "mode";
2N/A break;
2N/A case LLDP_PROPTYPE_BASICTLV:
2N/A str = LLDP_BASICTLV_GRPNAME;
2N/A break;
2N/A case LLDP_PROPTYPE_8021TLV:
2N/A str = LLDP_8021TLV_GRPNAME;
2N/A break;
2N/A case LLDP_PROPTYPE_8023TLV:
2N/A str = LLDP_8023TLV_GRPNAME;
2N/A break;
2N/A case LLDP_PROPTYPE_VIRTTLV:
2N/A str = LLDP_VIRTTLV_GRPNAME;
2N/A break;
2N/A case LLDP_PROPTYPE_SUP_SYSCAPAB:
2N/A str = "supported";
2N/A break;
2N/A case LLDP_PROPTYPE_ENAB_SYSCAPAB:
2N/A str = "enabled";
2N/A break;
2N/A case LLDP_PROPTYPE_IPADDR:
2N/A str = "ipaddr";
2N/A break;
2N/A case LLDP_PROPTYPE_WILLING:
2N/A str = "willing";
2N/A break;
2N/A case LLDP_PROPTYPE_APPLN:
2N/A str = "apt";
2N/A break;
2N/A case LLDP_PROPTYPE_ETSBAT:
2N/A str = "etsbat";
2N/A break;
2N/A default:
2N/A break;
2N/A }
2N/A return (str);
2N/A}