Blame SOURCES/open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch

d58598
From: Aaron Conole <aconole@redhat.com>
d58598
Date: Wed, 09 Jun 2021 15:12:06 +0000
d58598
Subject: [PATCH] lldpad: Rebase to openlldp branch 1.1.0
d58598
MIME-Version: 1.0
d58598
Content-Type: text/plain; charset=UTF-8
d58598
Content-Transfer-Encoding: 8bit
d58598
d58598
Open-LLDP released 1.1.0 which includes a number of important fixes
d58598
relevant to customers.  The biggest changes are documented in the
d58598
changelog.
d58598
d58598
This patch updates the lldpad package to 1.1.0 branch as of
d58598
4c75fa274230 "tx: rename variable"
d58598
d58598
Signed-off-by: Aaron Conole <aconole@redhat.com>
d58598
---
d58598
 ChangeLog                  |   15 +++
d58598
 Makefile.am                |   26 +++++
d58598
 README                     |    4 
d58598
 config.c                   |   45 ++++++---
d58598
 configure.ac               |   39 ++++++++
d58598
 ctrl_iface.c               |    4 
d58598
 dcb_protocol.c             |   19 +---
d58598
 dcb_rule_chk.c             |    2 
d58598
 dcbtool.c                  |    2 
d58598
 dcbtool_cmds.c             |   24 -----
d58598
 docs/liblldp_clif-vdp22.3  |    2 
d58598
 docs/lldptool.8            |    4 
d58598
 event_iface.c              |   22 +++-
d58598
 include/config.h           |    3 
d58598
 include/linux/if_link.h    |  100 ++++++++++++++++++++-
d58598
 include/lldp.h             |   13 ++
d58598
 include/lldp_basman_clif.h |    6 -
d58598
 include/lldp_mod.h         |    2 
d58598
 include/lldp_tlv.h         |   16 ++-
d58598
 include/lldp_util.h        |    4 
d58598
 include/lldptool.h         |    3 
d58598
 include/qbg_ecp22.h        |    4 
d58598
 include/qbg_vdpnl.h        |    1 
d58598
 lldp/agent.c               |    4 
d58598
 lldp/l2_packet.h           |    7 -
d58598
 lldp/l2_packet_linux.c     |    6 -
d58598
 lldp/ports.c               |    2 
d58598
 lldp/rx.c                  |   41 ++++----
d58598
 lldp/states.h              |    2 
d58598
 lldp/tx.c                  |   31 ++++--
d58598
 lldp_8021qaz.c             |   52 ++++++-----
d58598
 lldp_8021qaz_clif.c        |   80 ++++++++++++-----
d58598
 lldp_8021qaz_cmds.c        |    2 
d58598
 lldp_8023.c                |   14 +--
d58598
 lldp_basman.c              |   10 --
d58598
 lldp_basman_cmds.c         |   90 +++++++++++++++++++
d58598
 lldp_dcbx.c                |  111 +++++++++---------------
d58598
 lldp_dcbx_cfg.c            |   32 ++++--
d58598
 lldp_dcbx_cmds.c           |   13 ++
d58598
 lldp_dcbx_nl.c             |   20 +---
d58598
 lldp_evb.c                 |    8 -
d58598
 lldp_evb22.c               |    8 -
d58598
 lldp_evb22_cmds.c          |    2 
d58598
 lldp_evb_cmds.c            |    2 
d58598
 lldp_mand.c                |   41 +++++---
d58598
 lldp_mand_cmds.c           |   17 ++-
d58598
 lldp_med.c                 |    8 -
d58598
 lldp_med_cmds.c            |    1 
d58598
 lldp_rtnl.c                |    3 
d58598
 lldp_tlv.c                 |   12 --
d58598
 lldp_util.c                |  206 +++++++++++++++++++++++++++++----------------
d58598
 lldpad.c                   |   21 +++-
d58598
 lldpad.service             |    2 
d58598
 lldpad.socket              |    3 
d58598
 lldpad.spec.in             |   36 +++++--
d58598
 lldptool.c                 |   38 ++------
d58598
 lldptool_cmds.c            |    3 
d58598
 log.c                      |    1 
d58598
 parse_cli.l                |    3 
d58598
 qbg/ecp.c                  |    8 -
d58598
 qbg/ecp22.c                |   21 +++-
d58598
 qbg/vdp.c                  |   16 +--
d58598
 qbg/vdp22.c                |   12 +-
d58598
 qbg/vdp22_cmds.c           |    7 -
d58598
 qbg/vdp22sm.c              |    4 
d58598
 qbg/vdp_cmds.c             |    2 
d58598
 qbg/vdpnl.c                |    8 -
d58598
 qbg_utils.c                |    3 
d58598
 tlv_dcbx.c                 |   33 ++++---
d58598
 vdptool.c                  |   23 ++---
d58598
 vdptool_cisco_oui.c        |    2 
d58598
 weak_readline.c            |   16 ++-
d58598
 72 files changed, 935 insertions(+), 512 deletions(-)
d58598
d58598
diff -upr a/ChangeLog b/ChangeLog
d58598
--- a/ChangeLog	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/ChangeLog	2021-06-09 11:00:02.478019444 -0400
d58598
@@ -1,3 +1,18 @@
d58598
+Changes from 1.1.0 to
d58598
+Changes from 1.0.1 to 1.1
d58598
+- VDP: introduce vdptool
d58598
+- VDP: support retrieving vsi parameter
d58598
+- VDP: TLV support
d58598
+- VDP: Support OUI infrastructure
d58598
+- Switch from SysV to posix shared memory
d58598
+- DCBX: ignore PG configurations
d58598
+- DCBX: Allow for read-only LLDP configuration
d58598
+- Support multicast MAC
d58598
+- autoconf: Suport systemd or sysv for init system
d58598
+- 802.1qaz: print prio map
d58598
+- lldptool: Allow to modify optional TLV content
d58598
+- CVE-2018-10932: Don't print raw bytes from mngAddr
d58598
+- Misc. bug fixes
d58598
 Changes from 0.9.46 to 1.0.1
d58598
   Mostly fixes and man page updates
d58598
   Added more testing infrastructure mostly for EVB
d58598
diff -upr a/config.c b/config.c
d58598
--- a/config.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/config.c	2020-10-23 14:12:58.973289274 -0400
d58598
@@ -56,6 +56,21 @@
d58598
 config_t lldpad_cfg;
d58598
 
d58598
 /*
d58598
+ * config_ifkey - Generates a config key
d58598
+ *
d58598
+ * Given an interface name this functions generates
d58598
+ * a key (based on interface's index) suitable
d58598
+ * to pass to libconfig.
d58598
+ *
d58598
+ */
d58598
+void config_ifkey(const char *name, char *ifkey) {
d58598
+	int index = if_nametoindex(name);
d58598
+	
d58598
+	if(index)
d58598
+		sprintf(ifkey, "if%d", index);
d58598
+}
d58598
+
d58598
+/*
d58598
  * init_cfg - initialze the global lldpad_cfg via config_init
d58598
  *
d58598
  * Returns true (1) for succes and false (0) for failed
d58598
@@ -170,7 +185,7 @@ void scan_port(UNUSED void *eloop_data,
d58598
 		LIST_FOREACH(agent, &port->agent_head, entry) {
d58598
 			LLDPAD_DBG("%s: calling ifdown for agent %p.\n",
d58598
 				   __func__, agent);
d58598
-			LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+			LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 				ops = np->ops;
d58598
 				if (ops->lldp_mod_ifdown)
d58598
 					ops->lldp_mod_ifdown(ifname, agent);
d58598
@@ -219,7 +234,7 @@ int check_cfg_file(void)
d58598
 			}
d58598
 		} else {
d58598
 			retval = errno;
d58598
-			LLDPAD_ERR("%s is not readable and writeable",
d58598
+			LLDPAD_ERR("%s is not readable and writeable\n",
d58598
 				cfg_file_name);
d58598
 		}
d58598
 	}
d58598
@@ -295,7 +310,7 @@ int get_int_config(config_setting_t *s,
d58598
 	}
d58598
 
d58598
 	if (!rval)
d58598
-		LLDPAD_ERR("invalid value for %s", attr);
d58598
+		LLDPAD_ERR("invalid value for %s\n", attr);
d58598
 
d58598
 	return rval;
d58598
 }
d58598
@@ -339,7 +354,7 @@ int get_array_config(config_setting_t *s
d58598
 	}
d58598
 
d58598
 	if (!rval)
d58598
-		LLDPAD_ERR("invalid setting for %s", attr);
d58598
+		LLDPAD_ERR("invalid setting for %s\n", attr);
d58598
 
d58598
 	return rval;
d58598
 }
d58598
@@ -379,7 +394,7 @@ void init_ports(void)
d58598
 		LIST_FOREACH(agent, &port->agent_head, entry) {
d58598
 			LLDPAD_DBG("%s: calling ifup for agent %p.\n",
d58598
 				   __func__, agent);
d58598
-			LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+			LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 				if (np->ops->lldp_mod_ifup)
d58598
 					np->ops->lldp_mod_ifup(p->if_name, agent);
d58598
 			}
d58598
@@ -451,14 +466,15 @@ static int lookup_config_value(char *pat
d58598
 int get_config_setting(const char *ifname, int agenttype, char *path,
d58598
 		       union cfg_get v, int type)
d58598
 {
d58598
-	char p[1024];
d58598
+	char p[1024], ifkey[IFNAMSIZ];
d58598
 	int rval = CONFIG_FALSE;
d58598
 	const char *section = agent_type2section(agenttype);
d58598
 
d58598
 	/* look for setting in section->ifname area first */
d58598
 	if (ifname) {
d58598
+		config_ifkey(ifname, ifkey);
d58598
 		snprintf(p, sizeof(p), "%s.%s.%s",
d58598
-			 section, ifname, path);
d58598
+			 section, ifkey, path);
d58598
 		rval = lookup_config_value(p, v, type);
d58598
 	}
d58598
 
d58598
@@ -475,15 +491,16 @@ int get_config_setting(const char *ifnam
d58598
 int remove_config_setting(const char *ifname, int agenttype, char *parent,
d58598
 			  char *name)
d58598
 {
d58598
-	char p[1024];
d58598
+	char p[1024], ifkey[IFNAMSIZ];
d58598
 	int rval = CONFIG_FALSE;
d58598
 	config_setting_t *setting = NULL;
d58598
 	const char *section = agent_type2section(agenttype);
d58598
 
d58598
 	/* look for setting in section->ifname area first */
d58598
-	if (ifname) {
d58598
+	if (ifname) { 
d58598
+		config_ifkey(ifname, ifkey);
d58598
 		snprintf(p, sizeof(p), "%s.%s.%s",
d58598
-			 section, ifname, parent);
d58598
+			 section, ifkey, parent);
d58598
 		setting = config_lookup(&lldpad_cfg, p);
d58598
 	}
d58598
 
d58598
@@ -570,15 +587,17 @@ int set_config_setting(const char *ifnam
d58598
 		       union cfg_set v, int type)
d58598
 {
d58598
 	config_setting_t *setting = NULL;
d58598
-	char p[1024];
d58598
+	char p[1024], ifkey[IFNAMSIZ];
d58598
 	int rval = cmd_success;
d58598
 	const char *section = agent_type2section(agenttype);
d58598
 
d58598
 	LLDPAD_DBG("%s(%i): \n", __func__, __LINE__);
d58598
 
d58598
-	if (strlen(ifname))
d58598
+	if (strlen(ifname)){
d58598
+		config_ifkey(ifname, ifkey);
d58598
 		snprintf(p, sizeof(p), "%s.%s.%s",
d58598
-			 section, ifname, path);
d58598
+			 section, ifkey, path);
d58598
+	}
d58598
 	else
d58598
 		snprintf(p, sizeof(p), "%s.%s.%s",
d58598
 			 section, LLDP_COMMON, path);
d58598
diff -upr a/configure.ac b/configure.ac
d58598
--- a/configure.ac	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/configure.ac	2021-06-09 11:00:02.479019457 -0400
d58598
@@ -1,4 +1,4 @@
d58598
-AC_INIT([lldpad], [1.0.1], [lldp-devel@open-lldp.org])
d58598
+AC_INIT([lldpad], [1.1.0], [lldp-devel@open-lldp.org])
d58598
 AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
d58598
 
d58598
 m4_pattern_allow([AM_PROG_AR])
d58598
@@ -25,6 +25,43 @@ then
d58598
  AC_MSG_ERROR([no suitable flex found. Please install the 'flex' package.])
d58598
 fi
d58598
 
d58598
+dnl Begin determine the systemd use and location
d58598
+PKG_CHECK_MODULES([SYSTEMD], [systemd], use_systemd=yes, use_systemd=no)
d58598
+
d58598
+dnl Configure developer type flags
d58598
+OPENLLDP_CHECK_WARNINGS
d58598
+OPENLLDP_CHECK_ERROR
d58598
+
d58598
+dnl Set sysvinit values, if system has systemd it will be rewritten
d58598
+AC_SUBST(SPEC_BUILD_REQUIRES_POST, "chkconfig")
d58598
+AC_SUBST(SPEC_BUILD_REQUIRES_PREUN, "chkconfig initscripts")
d58598
+AC_SUBST(SPEC_BUILD_REQUIRES_POSTUN, "initscripts")
d58598
+specfile_install="%{_sysconfdir}/init.d/lldpad"
d58598
+specfile_install_socket=""
d58598
+
d58598
+if test "x$use_systemd" == xyes; then
d58598
+        dir=""
d58598
+        AC_ARG_WITH([systemdsystemunitdir],
d58598
+                AS_HELP_STRING([--with-systemdsystem unitdir=DIR],
d58598
+                 [Directory for systemd service files default from pkg-config variable systemdsystemunitdir]),
d58598
+                [dir=${withval}],
d58598
+                [dir="$($PKG_CONFIG --variable=systemdsystemunitdir systemd)"])
d58598
+
d58598
+	systemdsystemunitdir=${dir}
d58598
+	AC_SUBST(SYSTEMD_SYSTEM_UNIT_DIR, [$systemdsystemunitdir])
d58598
+	specfile_install="$systemdsystemunitdir/lldpad.service"	
d58598
+	specfile_install_socket="$systemdsystemunitdir/lldpad.socket"
d58598
+
d58598
+	AC_SUBST(SPEC_BUILD_REQUIRES_POST, "systemd")
d58598
+	AC_SUBST(SPEC_BUILD_REQUIRES_PREUN, "systemd")
d58598
+	AC_SUBST(SPEC_BUILD_REQUIRES_POSTUN, "systemd")
d58598
+fi
d58598
+
d58598
+AM_CONDITIONAL(SYSTEMD_SYSTEM, test "x$use_systemd" == xyes)
d58598
+AC_SUBST(SPEC_FILE_LLDPAD_SERVICE, $specfile_install)
d58598
+AC_SUBST(SPEC_FILE_LLDPAD_SOCKET, $specfile_install_socket)
d58598
+dnl End systemd stuff
d58598
+
d58598
 PKG_CHECK_MODULES([LIBCONFIG], [libconfig >= 1.3.2])
d58598
 PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.2])
d58598
 
d58598
diff -upr a/ctrl_iface.c b/ctrl_iface.c
d58598
--- a/ctrl_iface.c	2021-06-09 10:58:59.208200552 -0400
d58598
+++ b/ctrl_iface.c	2020-11-03 09:08:48.057229002 -0500
d58598
@@ -53,8 +53,6 @@
d58598
 #include "lldp_util.h"
d58598
 #include "messages.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 struct ctrl_dst {
d58598
 	struct ctrl_dst *next;
d58598
 	struct sockaddr_un addr;
d58598
@@ -116,7 +114,7 @@ int clif_iface_module(struct clif_data *
d58598
 		return cmd_invalid;
d58598
 	}
d58598
 
d58598
-	mod = find_module_by_id(&lldp_head, module_id);
d58598
+	mod = find_module_by_id(&lldp_mod_head, module_id);
d58598
 	if (mod && mod->ops && mod->ops->client_cmd)
d58598
 		return  (mod->ops->client_cmd)(clifd, from, fromlen,
d58598
 			 cmd_start, cmd_len, rbuf+strlen(rbuf), rlen);
d58598
diff -upr a/dcb_protocol.c b/dcb_protocol.c
d58598
--- a/dcb_protocol.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/dcb_protocol.c	2020-09-23 08:50:52.647813847 -0400
d58598
@@ -75,7 +75,7 @@ void pg_insert(struct pghead *head, char
d58598
 	entry = (struct pg_store1 *)malloc(sizeof(struct pg_store1));
d58598
 	if (!entry)
d58598
 		return;
d58598
-	strncpy(entry->ifname, ifname, sizeof(entry->ifname));
d58598
+	STRNCPY_TERMINATED(entry->ifname, ifname, sizeof(entry->ifname));
d58598
 	entry->second = store;
d58598
 	LIST_INSERT_HEAD(head, entry, entries);
d58598
 }
d58598
@@ -1100,7 +1100,7 @@ int dcbx_remove_adapter(char *device_nam
d58598
 	assert(device_name);
d58598
 	not_default = memcmp(DEF_CFG_STORE, device_name,
d58598
 		strlen(DEF_CFG_STORE));
d58598
-	strncpy (devName, device_name, MAX_DEVICE_NAME_LEN);
d58598
+	STRNCPY_TERMINATED (devName, device_name, MAX_DEVICE_NAME_LEN);
d58598
 
d58598
 	if (not_default)
d58598
 		handle_opermode_true(device_name);
d58598
@@ -2257,13 +2257,8 @@ cmd_status get_bwg_descrpt(char *device_
d58598
 
d58598
 	if ((it != NULL) &&
d58598
 		(bwgid < it->second->max_pgid_desc)) {
d58598
-		size = (int)strlen(it->second->pgid_desc[bwgid]) +
d58598
-			sizeof(char);  /* Localization OK */
d58598
-		*name = (char*)malloc(size);
d58598
-		if (*name != NULL) {
d58598
-			strncpy(*name, it->second->pgid_desc[bwgid],
d58598
-					size); /* Localization OK */
d58598
-		} else {
d58598
+		*name = strdup(it->second->pgid_desc[bwgid]);
d58598
+		if (*name == NULL) {
d58598
 			goto Error;
d58598
 		}
d58598
 	} else {
d58598
@@ -2272,11 +2267,9 @@ cmd_status get_bwg_descrpt(char *device_
d58598
 			size = (int)strlen(
d58598
 				attribs.descript.pgid_desc[bwgid]) +
d58598
 				sizeof(char);
d58598
-			*name = (char*)malloc(size);
d58598
+			*name = (char*)calloc(size, sizeof(char));
d58598
 			if (*name != NULL) {
d58598
-				strncpy(*name,
d58598
-					attribs.descript.pgid_desc[bwgid],
d58598
-					size); /* Localization OK */
d58598
+				memcpy(*name, attribs.descript.pgid_desc[bwgid], size - 1); /* Localization OK */
d58598
 			} else {
d58598
 				goto Error;
d58598
 			}
d58598
diff -upr a/dcb_rule_chk.c b/dcb_rule_chk.c
d58598
--- a/dcb_rule_chk.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/dcb_rule_chk.c	2020-09-23 08:50:52.647813847 -0400
d58598
@@ -206,6 +206,8 @@ static int dcb_fixup_pg(struct pg_attrib
d58598
 					strict = 0;
d58598
 				if (be == cbe)
d58598
 					be = 0;
d58598
+				if (pgid < 0)
d58598
+					continue;
d58598
 			}
d58598
 
d58598
 			if (pg_done[i] == false) {
d58598
diff -upr a/dcbtool.c b/dcbtool.c
d58598
--- a/dcbtool.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/dcbtool.c	2020-09-23 08:50:52.647813847 -0400
d58598
@@ -47,6 +47,7 @@
d58598
 #define UNUSED __attribute__((__unused__))
d58598
 
d58598
 static int show_raw;
d58598
+extern void close_history(void);
d58598
 
d58598
 static const char *cli_version =
d58598
 "dcbtool v" DCBTOOL_VERSION "\n"
d58598
@@ -460,6 +461,7 @@ static void cli_interactive(int raw)
d58598
 			request(clif_conn, argc, argv, raw);
d58598
 		free(cmd);
d58598
 	} while (!cli_quit);
d58598
+	close_history();
d58598
 }
d58598
 
d58598
 static void cli_terminate(UNUSED int sig)
d58598
diff -upr a/dcbtool_cmds.c b/dcbtool_cmds.c
d58598
--- a/dcbtool_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/dcbtool_cmds.c	2020-09-23 08:50:52.647813847 -0400
d58598
@@ -27,6 +27,7 @@
d58598
 #include <stdlib.h>
d58598
 #include <stdio.h>
d58598
 #include <ctype.h>
d58598
+#include <sys/types.h>
d58598
 #include "clif.h"
d58598
 #include "dcbtool.h"
d58598
 #include "lldp_dcbx_cmds.h"
d58598
@@ -38,7 +39,6 @@
d58598
 
d58598
 static char *print_status(cmd_status status);
d58598
 static char *get_pgdesc_args(int cmd);
d58598
-static int hex2int(char *b);
d58598
 static void free_cmd_args(char *args);
d58598
 static char *get_dcb_args(void);
d58598
 static char *get_dcbx_args(void);
d58598
@@ -93,28 +93,6 @@ static char *print_status(cmd_status sta
d58598
 	return str;
d58598
 }
d58598
 
d58598
-/* assumes input is pointer to two hex digits */
d58598
-/* returns -1 on error */
d58598
-static int hex2int(char *b)
d58598
-{
d58598
-	int i;
d58598
-	int n=0;
d58598
-	int m;
d58598
-	
d58598
-	for (i=0,m=1; i<2; i++,m--) {
d58598
-		if (isxdigit(*(b+i))) {
d58598
-			if (*(b+i) <= '9')
d58598
-				n |= (*(b+i) & 0x0f) << (4*m);
d58598
-			else
d58598
-				n |= ((*(b+i) & 0x0f) + 9) << (4*m);
d58598
-		}
d58598
-		else {
d58598
-			return -1;
d58598
-		}
d58598
-	}
d58598
-	return n;
d58598
-}
d58598
-
d58598
 static char *get_dcb_args(void)
d58598
 {
d58598
 	char buf[8];
d58598
diff -upr a/docs/liblldp_clif-vdp22.3 b/docs/liblldp_clif-vdp22.3
d58598
--- a/docs/liblldp_clif-vdp22.3	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/docs/liblldp_clif-vdp22.3	2020-11-03 09:08:48.058229019 -0500
d58598
@@ -1,6 +1,6 @@
d58598
 .TH liblldp_clif 3 "February 2014" "open-lldp" "Linux"
d58598
 .SH NAME
d58598
-clif_vsi,clif_vsievt,clif_vsiwait \- Manipulate VDP IEEE 802.1 Ratified Standard Assocications
d58598
+clif_vsi,clif_vsievt,clif_vsiwait \- Manipulate VDP IEEE 802.1 Ratified Standard Associations
d58598
 .SH SYNOPSIS
d58598
 #include "include/clif.h"
d58598
 .sp 1
d58598
diff -upr a/docs/lldptool.8 b/docs/lldptool.8
d58598
--- a/docs/lldptool.8	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/docs/lldptool.8	2020-11-03 09:08:48.058229019 -0500
d58598
@@ -160,9 +160,9 @@ Query the LLDP adminStatus for interface
d58598
 
d58598
 .TP
d58598
 Query the LLDP statistics for interface \fIeth3\fR
d58598
-.B lldptool -S -i eth3 adminStatus
d58598
+.B lldptool -S -i eth3
d58598
 .br
d58598
-.B lldptool stats -i eth3 adminStatus
d58598
+.B lldptool stats -i eth3
d58598
 
d58598
 .TP
d58598
 Query the local TLVs which are being transmitted for a given interface:
d58598
diff -upr a/event_iface.c b/event_iface.c
d58598
--- a/event_iface.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/event_iface.c	2021-01-06 11:05:30.808649405 -0500
d58598
@@ -77,7 +77,7 @@ static void event_if_decode_rta(int type
d58598
 		LLDPAD_DBG(" IFLA_BROADCAST\n");
d58598
 		break;
d58598
 	case IFLA_IFNAME:
d58598
-		strncpy(d, (char *)RTA_DATA(rta), IFNAMSIZ);
d58598
+		STRNCPY_TERMINATED(d, (char *)RTA_DATA(rta), IFNAMSIZ);
d58598
 		LLDPAD_DBG(" IFLA_IFNAME\n");
d58598
 		LLDPAD_DBG("        device name is %s\n", d);
d58598
 		break;
d58598
@@ -205,6 +205,9 @@ int oper_add_device(char *device_name)
d58598
 		port = newport;
d58598
 	} else if (is_bond(device_name) || !port->portEnabled)
d58598
 		reinit_port(device_name);
d58598
+	else if (port->portEnabled) {
d58598
+		return 0;
d58598
+	}
d58598
 
d58598
 	lldp_add_agent(device_name, NEAREST_BRIDGE);
d58598
 	lldp_add_agent(device_name, NEAREST_NONTPMR_BRIDGE);
d58598
@@ -213,7 +216,7 @@ int oper_add_device(char *device_name)
d58598
 	LIST_FOREACH(agent, &port->agent_head, entry) {
d58598
 		LLDPAD_DBG("%s: calling ifup for agent %p.\n",
d58598
 			   __func__, agent);
d58598
-		LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+		LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 			if (np->ops->lldp_mod_ifup)
d58598
 				np->ops->lldp_mod_ifup(device_name, agent);
d58598
 		}
d58598
@@ -280,7 +283,7 @@ static void event_if_decode_nlmsg(int ro
d58598
 			LIST_FOREACH(agent, &port->agent_head, entry) {
d58598
 				LLDPAD_DBG("%s: calling ifdown for agent %p.\n",
d58598
 					   __func__, agent);
d58598
-				LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+				LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 					ops = np->ops;
d58598
 					if (ops->lldp_mod_ifdown)
d58598
 						ops->lldp_mod_ifdown(device_name,
d58598
@@ -415,7 +418,8 @@ event_iface_receive(int sock, UNUSED voi
d58598
 int event_iface_init()
d58598
 {
d58598
 	int fd;
d58598
-	int rcv_size = MAX_PAYLOAD;
d58598
+	int rcv_size = 0;
d58598
+	socklen_t rcv_len = sizeof(int);
d58598
 	struct sockaddr_nl snl;
d58598
 
d58598
 	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
d58598
@@ -423,10 +427,18 @@ int event_iface_init()
d58598
 	if (fd < 0)
d58598
 		return fd;
d58598
 
d58598
-	if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, sizeof(int)) < 0) {
d58598
+	/* is receive buffer size too small? */
d58598
+	if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, &rcv_len) < 0) {
d58598
 		close(fd);
d58598
 		return -EIO;
d58598
 	}
d58598
+	if (rcv_size < MIN_RCVBUF_SIZE) {
d58598
+		rcv_size = MIN_RCVBUF_SIZE >> 1;	/* we get back 2x what we set */
d58598
+		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, rcv_len) < 0) {
d58598
+			close(fd);
d58598
+			return -EIO;
d58598
+		}
d58598
+	}
d58598
 
d58598
 	memset((void *)&snl, 0, sizeof(struct sockaddr_nl));
d58598
 	snl.nl_family = AF_NETLINK;
d58598
diff -upr a/include/config.h b/include/config.h
d58598
--- a/include/config.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/config.h	2020-09-23 08:50:52.647813847 -0400
d58598
@@ -111,4 +111,7 @@ void destroy_cfg(void);
d58598
 int check_cfg_file(void);
d58598
 int check_for_old_file_format(void);
d58598
 void init_ports(void);
d58598
+
d58598
+void config_ifkey(const char *name, char *ifkey);
d58598
+
d58598
 #endif /* _CONFIG_H_ */
d58598
diff -upr a/include/linux/if_link.h b/include/linux/if_link.h
d58598
--- a/include/linux/if_link.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/linux/if_link.h	2020-09-23 08:50:52.648813865 -0400
d58598
@@ -116,15 +116,34 @@ enum {
d58598
 	IFLA_STATS64,
d58598
 	IFLA_VF_PORTS,
d58598
 	IFLA_PORT_SELF,
d58598
-        IFLA_AF_SPEC,
d58598
-        IFLA_GROUP,             /* Group the device belongs to */
d58598
-        IFLA_NET_NS_FD,
d58598
-        IFLA_EXT_MASK,          /* Extended info mask, VFs, etc */
d58598
-        IFLA_PROMISCUITY,       /* Promiscuity count: > 0 means acts PROMISC */
d58598
+	IFLA_AF_SPEC,
d58598
+	IFLA_GROUP,		/* Group the device belongs to */
d58598
+	IFLA_NET_NS_FD,
d58598
+	IFLA_EXT_MASK,		/* Extended info mask, VFs, etc */
d58598
+	IFLA_PROMISCUITY,	/* Promiscuity count: > 0 means acts PROMISC */
d58598
 #define IFLA_PROMISCUITY IFLA_PROMISCUITY
d58598
-        IFLA_NUM_TX_QUEUES,
d58598
-        IFLA_NUM_RX_QUEUES,
d58598
-        IFLA_CARRIER,
d58598
+	IFLA_NUM_TX_QUEUES,
d58598
+	IFLA_NUM_RX_QUEUES,
d58598
+	IFLA_CARRIER,
d58598
+	IFLA_PHYS_PORT_ID,
d58598
+	IFLA_CARRIER_CHANGES,
d58598
+	IFLA_PHYS_SWITCH_ID,
d58598
+	IFLA_LINK_NETNSID,
d58598
+	IFLA_PHYS_PORT_NAME,
d58598
+	IFLA_PROTO_DOWN,
d58598
+	IFLA_GSO_MAX_SEGS,
d58598
+	IFLA_GSO_MAX_SIZE,
d58598
+	IFLA_PAD,
d58598
+	IFLA_XDP,
d58598
+	IFLA_EVENT,
d58598
+	IFLA_NEW_NETNSID,
d58598
+	IFLA_IF_NETNSID,
d58598
+	IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */
d58598
+	IFLA_CARRIER_UP_COUNT,
d58598
+	IFLA_CARRIER_DOWN_COUNT,
d58598
+	IFLA_NEW_IFINDEX,
d58598
+	IFLA_MIN_MTU,
d58598
+	IFLA_MAX_MTU,
d58598
 	__IFLA_MAX
d58598
 };
d58598
 
d58598
@@ -192,6 +211,8 @@ enum {
d58598
 	IFLA_INFO_KIND,
d58598
 	IFLA_INFO_DATA,
d58598
 	IFLA_INFO_XSTATS,
d58598
+	IFLA_INFO_SLAVE_KIND,
d58598
+	IFLA_INFO_SLAVE_DATA,
d58598
 	__IFLA_INFO_MAX,
d58598
 };
d58598
 
d58598
@@ -243,6 +264,69 @@ enum macvlan_mode {
d58598
 	MACVLAN_MODE_BRIDGE  = 4, /* talk to bridge ports directly */
d58598
 };
d58598
 
d58598
+/* Bonding section */
d58598
+
d58598
+enum {
d58598
+	IFLA_BOND_UNSPEC,
d58598
+	IFLA_BOND_MODE,
d58598
+	IFLA_BOND_ACTIVE_SLAVE,
d58598
+	IFLA_BOND_MIIMON,
d58598
+	IFLA_BOND_UPDELAY,
d58598
+	IFLA_BOND_DOWNDELAY,
d58598
+	IFLA_BOND_USE_CARRIER,
d58598
+	IFLA_BOND_ARP_INTERVAL,
d58598
+	IFLA_BOND_ARP_IP_TARGET,
d58598
+	IFLA_BOND_ARP_VALIDATE,
d58598
+	IFLA_BOND_ARP_ALL_TARGETS,
d58598
+	IFLA_BOND_PRIMARY,
d58598
+	IFLA_BOND_PRIMARY_RESELECT,
d58598
+	IFLA_BOND_FAIL_OVER_MAC,
d58598
+	IFLA_BOND_XMIT_HASH_POLICY,
d58598
+	IFLA_BOND_RESEND_IGMP,
d58598
+	IFLA_BOND_NUM_PEER_NOTIF,
d58598
+	IFLA_BOND_ALL_SLAVES_ACTIVE,
d58598
+	IFLA_BOND_MIN_LINKS,
d58598
+	IFLA_BOND_LP_INTERVAL,
d58598
+	IFLA_BOND_PACKETS_PER_SLAVE,
d58598
+	IFLA_BOND_AD_LACP_RATE,
d58598
+	IFLA_BOND_AD_SELECT,
d58598
+	IFLA_BOND_AD_INFO,
d58598
+	IFLA_BOND_AD_ACTOR_SYS_PRIO,
d58598
+	IFLA_BOND_AD_USER_PORT_KEY,
d58598
+	IFLA_BOND_AD_ACTOR_SYSTEM,
d58598
+	IFLA_BOND_TLB_DYNAMIC_LB,
d58598
+	__IFLA_BOND_MAX,
d58598
+};
d58598
+
d58598
+#define IFLA_BOND_MAX	(__IFLA_BOND_MAX - 1)
d58598
+
d58598
+enum {
d58598
+	IFLA_BOND_AD_INFO_UNSPEC,
d58598
+	IFLA_BOND_AD_INFO_AGGREGATOR,
d58598
+	IFLA_BOND_AD_INFO_NUM_PORTS,
d58598
+	IFLA_BOND_AD_INFO_ACTOR_KEY,
d58598
+	IFLA_BOND_AD_INFO_PARTNER_KEY,
d58598
+	IFLA_BOND_AD_INFO_PARTNER_MAC,
d58598
+	__IFLA_BOND_AD_INFO_MAX,
d58598
+};
d58598
+
d58598
+#define IFLA_BOND_AD_INFO_MAX	(__IFLA_BOND_AD_INFO_MAX - 1)
d58598
+
d58598
+enum {
d58598
+	IFLA_BOND_SLAVE_UNSPEC,
d58598
+	IFLA_BOND_SLAVE_STATE,
d58598
+	IFLA_BOND_SLAVE_MII_STATUS,
d58598
+	IFLA_BOND_SLAVE_LINK_FAILURE_COUNT,
d58598
+	IFLA_BOND_SLAVE_PERM_HWADDR,
d58598
+	IFLA_BOND_SLAVE_QUEUE_ID,
d58598
+	IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
d58598
+	IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
d58598
+	IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
d58598
+	__IFLA_BOND_SLAVE_MAX,
d58598
+};
d58598
+
d58598
+#define IFLA_BOND_SLAVE_MAX	(__IFLA_BOND_SLAVE_MAX - 1)
d58598
+
d58598
 /* SR-IOV virtual function management section */
d58598
 
d58598
 enum {
d58598
diff -upr a/include/lldp_basman_clif.h b/include/lldp_basman_clif.h
d58598
--- a/include/lldp_basman_clif.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/lldp_basman_clif.h	2020-09-23 08:50:52.648813865 -0400
d58598
@@ -31,7 +31,7 @@ struct lldp_module *basman_cli_register(
d58598
 void basman_cli_unregister(struct lldp_module *);
d58598
 int basman_print_tlv(u32, u16, char *);
d58598
 
d58598
-#define ARG_IPV4_ADDR "ipv4"
d58598
-#define ARG_IPV6_ADDR "ipv6"
d58598
-
d58598
+#define ARG_IPV4_ADDR	"ipv4"
d58598
+#define ARG_IPV6_ADDR	"ipv6"
d58598
+#define ARG_TLVINFO	"info"
d58598
 #endif
d58598
diff -upr a/include/lldp.h b/include/lldp.h
d58598
--- a/include/lldp.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/lldp.h	2020-09-23 08:50:52.648813865 -0400
d58598
@@ -51,6 +51,13 @@ typedef __u64 u64;
d58598
 		__x > __y ? __x : __y;	\
d58598
 	 })
d58598
 
d58598
+/* Use strncpy with N-1 and ensure the string is terminated.  */
d58598
+#define STRNCPY_TERMINATED(DEST, SRC, N) \
d58598
+  do { \
d58598
+    strncpy (DEST, SRC, N - 1); \
d58598
+    DEST[N - 1] = '\0'; \
d58598
+  } while (false)
d58598
+
d58598
 /*
d58598
  * Organizationally Unique Identifier (OUI)
d58598
  * http://standards.ieee.org/regauth/oui/oui.txt
d58598
@@ -248,5 +255,11 @@ enum {
d58598
 #define LLDP_EVB_DEFAULT_RTE				15
d58598
 #define LLDP_EVB_DEFAULT_MAX_RTE			31
d58598
 
d58598
+#ifndef _MSC_VER
d58598
+#define STRUCT_PACKED(STRUCT) STRUCT __attribute__((__packed__))
d58598
+#else
d58598
+#define STRUCT_PACKED(STRUCT) __pragma(pack(push, 1)) STRUCT __pragma(pack(pop))
d58598
+#endif
d58598
+
d58598
 void somethingChangedLocal(const char *ifname, int type);
d58598
 #endif /* _LLDP_H */
d58598
diff -upr a/include/lldp_mod.h b/include/lldp_mod.h
d58598
--- a/include/lldp_mod.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/lldp_mod.h	2020-10-23 14:12:58.974289292 -0400
d58598
@@ -96,7 +96,7 @@ struct lldp_module {
d58598
 };
d58598
 
d58598
 LIST_HEAD(lldp_head, lldp_module);
d58598
-struct lldp_head lldp_head;
d58598
+extern struct lldp_head lldp_mod_head;
d58598
 
d58598
 static inline struct lldp_module *find_module_by_id(struct lldp_head *head, int id)
d58598
 {
d58598
diff -upr a/include/lldp_tlv.h b/include/lldp_tlv.h
d58598
--- a/include/lldp_tlv.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/lldp_tlv.h	2020-09-23 08:50:52.648813865 -0400
d58598
@@ -104,8 +104,8 @@ struct packed_tlv *pack_tlv(struct unpac
d58598
 struct unpacked_tlv *unpack_tlv(struct packed_tlv *tlv);
d58598
 int pack_tlv_after(struct unpacked_tlv *, struct packed_tlv *, int);
d58598
 
d58598
-struct unpacked_tlv *free_unpkd_tlv(struct unpacked_tlv *tlv);
d58598
-struct packed_tlv *free_pkd_tlv(struct packed_tlv *tlv);
d58598
+void free_unpkd_tlv(struct unpacked_tlv *tlv);
d58598
+void free_pkd_tlv(struct packed_tlv *tlv);
d58598
 struct unpacked_tlv *create_tlv(void);
d58598
 struct packed_tlv *create_ptlv(void);
d58598
 struct unpacked_tlv *bld_end_tlv(void);
d58598
@@ -115,14 +115,18 @@ int tlv_ok(struct unpacked_tlv *tlv);
d58598
 
d58598
 #define FREE_UNPKD_TLV(d, f) \
d58598
 { \
d58598
-	if ((d)->f) \
d58598
-		(d)->f = free_unpkd_tlv((d)->f); \
d58598
+	if ((d)->f) {				 \
d58598
+		free_unpkd_tlv((d)->f);		 \
d58598
+		(d)->f = NULL;			 \
d58598
+	}					 \
d58598
 }
d58598
 
d58598
 #define FREE_PKD_TLV(d, f) \
d58598
 { \
d58598
-	if ((d)->f) \
d58598
-		(d)->f = free_pkd_tlv((d)->f); \
d58598
+	if ((d)->f) {			       \
d58598
+		free_pkd_tlv((d)->f);	       \
d58598
+		(d)->f = NULL;		       \
d58598
+	}				       \
d58598
 }
d58598
 
d58598
 #define PACK_TLV_AFTER(t, p, l, g) 		\
d58598
diff -upr a/include/lldptool.h b/include/lldptool.h
d58598
--- a/include/lldptool.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/lldptool.h	2020-09-23 08:50:52.648813865 -0400
d58598
@@ -29,9 +29,8 @@
d58598
 
d58598
 #include "clif.h"
d58598
 
d58598
-struct lldp_head lldp_cli_head;
d58598
+extern struct lldp_head lldp_cli_head;
d58598
 
d58598
-int hex2int(char *b);
d58598
 int clif_command(struct clif *clif, char *cmd, int raw);
d58598
 void print_raw_message(char *msg, int print);
d58598
 int parse_print_message(char *msg, int print);
d58598
diff -upr a/include/lldp_util.h b/include/lldp_util.h
d58598
--- a/include/lldp_util.h	2021-06-09 10:58:59.214200629 -0400
d58598
+++ b/include/lldp_util.h	2021-04-05 12:02:17.318590504 -0400
d58598
@@ -119,6 +119,7 @@
d58598
 
d58598
 int hexstr2bin(const char *hex, u8 *buf, size_t len);
d58598
 int bin2hexstr(const u8 *hex, size_t hexlen, char *buf, size_t buflen);
d58598
+int hex2int(char *b);
d58598
 
d58598
 int is_valid_lldp_device(const char *ifname);
d58598
 int is_active(const char *ifname);
d58598
@@ -149,8 +150,7 @@ int get_mautype(const char *);
d58598
 int get_ifpflags(const char *);
d58598
 int get_iftype(const char *);
d58598
 int get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr);
d58598
-int get_mac(const char *ifname, u8 mac[]);
d58598
-int get_macstr(const char *ifname, char *addr, size_t size);
d58598
+int get_mac(const char *ifname, u8 mac[], bool perm_mac);
d58598
 int get_saddr(const char *ifname, struct sockaddr_in *saddr);
d58598
 int get_ipaddr(const char *ifname, struct in_addr *);
d58598
 int get_ipaddrstr(const char *ifname, char *ipaddr, size_t size);
d58598
diff -upr a/include/qbg_ecp22.h b/include/qbg_ecp22.h
d58598
--- a/include/qbg_ecp22.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/include/qbg_ecp22.h	2020-09-23 08:50:52.649813883 -0400
d58598
@@ -49,10 +49,10 @@ enum {					/* ECP Transmit states */
d58598
 	ECP22_TX_ERROR
d58598
 };
d58598
 
d58598
-enum {
d58598
+enum ecp22_mode {
d58598
 	ECP22_REQUEST = 0,
d58598
 	ECP22_ACK
d58598
-} ecp22_mode;
d58598
+};
d58598
 
d58598
 struct ecp22_hdr {		/* ECP22 header */
d58598
 	u16 ver_op_sub;		/* ECP22 version, operation, subtype */
d58598
diff -upr a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h
d58598
--- a/include/qbg_vdpnl.h	2021-06-09 10:58:59.201200461 -0400
d58598
+++ b/include/qbg_vdpnl.h	2021-01-06 11:05:30.810649436 -0500
d58598
@@ -33,6 +33,7 @@
d58598
 #include <linux/if_ether.h>
d58598
 
d58598
 #define	MAX_PAYLOAD	4096	/* Maximum Payload Size */
d58598
+#define	MIN_RCVBUF_SIZE	(MAX_PAYLOAD << 5)	/* SO_RCVBUF min */
d58598
 
d58598
 enum {
d58598
 	vdpnl_nlf1 = 1,		/* Netlink message format 1 (draft 0.2) */
d58598
diff -upr a/lldp/agent.c b/lldp/agent.c
d58598
--- a/lldp/agent.c	2021-06-09 10:58:59.215200642 -0400
d58598
+++ b/lldp/agent.c	2021-01-06 11:05:30.811649451 -0500
d58598
@@ -163,7 +163,7 @@ static void timer(UNUSED void *eloop_dat
d58598
 			run_rx_sm(port, agent);
d58598
 			update_rx_timers(agent);
d58598
 
d58598
-			LIST_FOREACH(n, &lldp_head, lldp) {
d58598
+			LIST_FOREACH(n, &lldp_mod_head, lldp) {
d58598
 				if (n->ops && n->ops->timer)
d58598
 					n->ops->timer(port, agent);
d58598
 			}
d58598
@@ -200,7 +200,7 @@ void clean_lldp_agents(void)
d58598
 			LLDPAD_DBG("Send shutdown frame on port %s\n",
d58598
 				port->ifname);
d58598
 			LIST_FOREACH(agent, &port->agent_head, entry) {
d58598
-				process_tx_shutdown_frame(port, agent);
d58598
+				process_tx_shutdown_frame(port, agent, false);
d58598
 			}
d58598
 		} else {
d58598
 			LLDPAD_DBG("No shutdown frame is sent on port %s\n",
d58598
diff -upr a/lldp/l2_packet.h b/lldp/l2_packet.h
d58598
--- a/lldp/l2_packet.h	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp/l2_packet.h	2020-09-23 08:50:52.649813883 -0400
d58598
@@ -37,7 +37,9 @@
d58598
 #define IP2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
d58598
 #define IPSTR "%02x:%02x:%02x:%02x:%02x:%02x"
d58598
 
d58598
+#ifndef ETH_P_LLDP
d58598
 #define ETH_P_LLDP 0x88cc
d58598
+#endif
d58598
 
d58598
 #define ETH_P_ECP	0x88b7		/* Draft 0.2 */
d58598
 #define ETH_P_ECP22	0x8940		/* Ratified standard */
d58598
@@ -56,12 +58,11 @@
d58598
  */
d58598
 struct l2_packet_data;
d58598
 
d58598
-
d58598
-struct l2_ethhdr {
d58598
+STRUCT_PACKED(struct l2_ethhdr {
d58598
 	u8 h_dest[ETH_ALEN];
d58598
 	u8 h_source[ETH_ALEN];
d58598
 	u16 h_proto;
d58598
-} STRUCT_PACKED;
d58598
+});
d58598
 
d58598
 /**
d58598
  * l2_packet_init - Initialize l2_packet interface
d58598
diff -upr a/lldp/l2_packet_linux.c b/lldp/l2_packet_linux.c
d58598
--- a/lldp/l2_packet_linux.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp/l2_packet_linux.c	2020-09-23 08:50:52.649813883 -0400
d58598
@@ -60,7 +60,7 @@ struct l2_packet_data {
d58598
 
d58598
 int l2_packet_get_own_src_addr(struct l2_packet_data *l2, u8 *addr)
d58598
 {
d58598
-	if (is_san_mac(l2->san_mac_addr))
d58598
+	if (is_valid_mac(l2->san_mac_addr))
d58598
 		memcpy(addr, l2->san_mac_addr, ETH_ALEN);
d58598
 	else {
d58598
 		/* get an appropriate src MAC to use if the port is
d58598
@@ -169,7 +169,7 @@ struct l2_packet_data * l2_packet_init(
d58598
 	if (l2 == NULL)
d58598
 		return NULL;
d58598
 	memset(l2, 0, sizeof(*l2));
d58598
-	strncpy(l2->ifname, ifname, sizeof(l2->ifname));
d58598
+	STRNCPY_TERMINATED(l2->ifname, ifname, sizeof(l2->ifname));
d58598
 	l2->rx_callback = rx_callback;
d58598
 	l2->rx_callback_ctx = rx_callback_ctx;
d58598
 	l2->l2_hdr = l2_hdr;
d58598
@@ -183,7 +183,7 @@ struct l2_packet_data * l2_packet_init(
d58598
 		return NULL;
d58598
 	}
d58598
 
d58598
-	strncpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
d58598
+	STRNCPY_TERMINATED(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
d58598
 	if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
d58598
 		perror("ioctl[SIOCGIFINDEX]");
d58598
 		close(l2->fd);
d58598
diff -upr a/lldp/ports.c b/lldp/ports.c
d58598
--- a/lldp/ports.c	2021-06-09 10:58:59.211200590 -0400
d58598
+++ b/lldp/ports.c	2020-12-07 13:15:10.579203256 -0500
d58598
@@ -264,7 +264,7 @@ struct port *add_port(int ifindex, const
d58598
 	memset(newport, 0, sizeof(*newport));
d58598
 	newport->ifindex = ifindex;
d58598
 	newport->next = NULL;
d58598
-	strncpy(newport->ifname, ifname, IFNAMSIZ);
d58598
+	strncpy(newport->ifname, ifname, IFNAMSIZ - 1);
d58598
 
d58598
 	newport->bond_master = is_bond(ifname);
d58598
 	/* Initialize relevant port variables */
d58598
diff -upr a/lldp/rx.c b/lldp/rx.c
d58598
--- a/lldp/rx.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp/rx.c	2021-06-09 11:00:02.480019469 -0400
d58598
@@ -139,7 +139,16 @@ void rxProcessFrame(struct port *port, s
d58598
 	int err;
d58598
 	struct lldp_module *np;
d58598
 
d58598
-	assert(agent->rx.framein && agent->rx.sizein);
d58598
+	if (!agent->rx.framein) {
d58598
+		LLDPAD_DBG("ERROR - agent framein not set, "
d58598
+			   "has the neighbour MAC changed? "
d58598
+			   "Ignoring packet.\n");
d58598
+		return;
d58598
+	}
d58598
+	if (!agent->rx.sizein) {
d58598
+		LLDPAD_DBG("Size-0 packet received, ignoring packet\n");
d58598
+		return;
d58598
+	}
d58598
 	agent->lldpdu = 0;
d58598
 	agent->rx.dupTlvs = 0;
d58598
 
d58598
@@ -359,7 +368,7 @@ void rxProcessFrame(struct port *port, s
d58598
 		}
d58598
 
d58598
 		/* rx per lldp module */
d58598
-		LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+		LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 			if (!np->ops || !np->ops->lldp_mod_rchange)
d58598
 				continue;
d58598
 
d58598
@@ -377,7 +386,7 @@ void rxProcessFrame(struct port *port, s
d58598
 		if (!tlv_stored) {
d58598
 			LLDPAD_INFO("%s: allocated TLV %u was not stored! %p\n",
d58598
 				   __func__, tlv->type, tlv);
d58598
-			tlv = free_unpkd_tlv(tlv);
d58598
+			free_unpkd_tlv(tlv);
d58598
 			agent->stats.statsTLVsUnrecognizedTotal++;
d58598
 		}
d58598
 		tlv = NULL;
d58598
@@ -402,7 +411,7 @@ u8 mibDeleteObjects(struct port *port, s
d58598
 {
d58598
 	struct lldp_module *np;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops || !np->ops->lldp_mod_mibdelete)
d58598
 			continue;
d58598
 		np->ops->lldp_mod_mibdelete(port, agent);
d58598
@@ -638,29 +647,21 @@ void rx_change_state(struct lldp_agent *
d58598
 void clear_manifest(struct lldp_agent *agent)
d58598
 {
d58598
 	if (agent->rx.manifest->mgmtadd)
d58598
-		agent->rx.manifest->mgmtadd =
d58598
-			free_unpkd_tlv(agent->rx.manifest->mgmtadd);
d58598
+		free_unpkd_tlv(agent->rx.manifest->mgmtadd);
d58598
 	if (agent->rx.manifest->syscap)
d58598
-		agent->rx.manifest->syscap =
d58598
-			free_unpkd_tlv(agent->rx.manifest->syscap);
d58598
+		free_unpkd_tlv(agent->rx.manifest->syscap);
d58598
 	if (agent->rx.manifest->sysdesc)
d58598
-		agent->rx.manifest->sysdesc =
d58598
-			free_unpkd_tlv(agent->rx.manifest->sysdesc);
d58598
+		free_unpkd_tlv(agent->rx.manifest->sysdesc);
d58598
 	if (agent->rx.manifest->sysname)
d58598
-		agent->rx.manifest->sysname =
d58598
-			free_unpkd_tlv(agent->rx.manifest->sysname);
d58598
+		free_unpkd_tlv(agent->rx.manifest->sysname);
d58598
 	if (agent->rx.manifest->portdesc)
d58598
-		agent->rx.manifest->portdesc =
d58598
-			free_unpkd_tlv(agent->rx.manifest->portdesc);
d58598
+		free_unpkd_tlv(agent->rx.manifest->portdesc);
d58598
 	if (agent->rx.manifest->ttl)
d58598
-		agent->rx.manifest->ttl =
d58598
-			free_unpkd_tlv(agent->rx.manifest->ttl);
d58598
+		free_unpkd_tlv(agent->rx.manifest->ttl);
d58598
 	if (agent->rx.manifest->portid)
d58598
-		agent->rx.manifest->portid =
d58598
-			free_unpkd_tlv(agent->rx.manifest->portid);
d58598
+		free_unpkd_tlv(agent->rx.manifest->portid);
d58598
 	if (agent->rx.manifest->chassis)
d58598
-		agent->rx.manifest->chassis =
d58598
-			free_unpkd_tlv(agent->rx.manifest->chassis);
d58598
+		free_unpkd_tlv(agent->rx.manifest->chassis);
d58598
 	free(agent->rx.manifest);
d58598
 	agent->rx.manifest = NULL;
d58598
 }
d58598
diff -upr a/lldp/states.h b/lldp/states.h
d58598
--- a/lldp/states.h	2021-06-09 10:58:59.211200590 -0400
d58598
+++ b/lldp/states.h	2021-01-06 11:05:30.811649451 -0500
d58598
@@ -85,7 +85,7 @@ u8 txFrame(struct port *port, struct lld
d58598
 void run_tx_sm(struct port *, struct lldp_agent *);
d58598
 void process_tx_initialize_sm(struct port *);
d58598
 void process_tx_idle(struct lldp_agent *);
d58598
-void process_tx_shutdown_frame(struct port *, struct lldp_agent *);
d58598
+void process_tx_shutdown_frame(struct port *, struct lldp_agent *, bool);
d58598
 void process_tx_info_frame(struct port *, struct lldp_agent *);
d58598
 void update_tx_timers(struct lldp_agent *);
d58598
 void run_tx_timers_sm(struct port *, struct lldp_agent *);
d58598
diff -upr a/lldp/tx.c b/lldp/tx.c
d58598
--- a/lldp/tx.c	2021-06-09 10:58:59.211200590 -0400
d58598
+++ b/lldp/tx.c	2021-01-06 11:05:30.812649467 -0500
d58598
@@ -71,7 +71,7 @@ bool mibConstrInfoLLDPDU(struct port *po
d58598
 	fb_offset += sizeof(struct l2_ethhdr);
d58598
 
d58598
 	/* Generic TLV Pack */
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops || !np->ops->lldp_mod_gettlv)
d58598
 			continue;
d58598
 
d58598
@@ -83,7 +83,7 @@ bool mibConstrInfoLLDPDU(struct port *po
d58598
 			       ptlv->tlv, ptlv->size);
d58598
 			datasize += ptlv->size;
d58598
 			fb_offset += ptlv->size;
d58598
-			ptlv =  free_pkd_tlv(ptlv);
d58598
+			free_pkd_tlv(ptlv);
d58598
 		}
d58598
 	}
d58598
 
d58598
@@ -94,7 +94,7 @@ bool mibConstrInfoLLDPDU(struct port *po
d58598
 	memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size);
d58598
 	datasize += ptlv->size;
d58598
 	fb_offset += ptlv->size;
d58598
-	ptlv =  free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 
d58598
 	if (datasize < ETH_MIN_DATA_LEN)
d58598
 		agent->tx.sizeout = ETH_ZLEN;
d58598
@@ -104,7 +104,7 @@ bool mibConstrInfoLLDPDU(struct port *po
d58598
 	return true;
d58598
 
d58598
 error:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 	if (agent->tx.frameout)
d58598
 		free(agent->tx.frameout);
d58598
 	agent->tx.frameout = NULL;
d58598
@@ -206,7 +206,7 @@ bool mibConstrShutdownLLDPDU(struct port
d58598
 	memcpy(agent->tx.frameout, (void *)&eth, sizeof(struct l2_ethhdr));
d58598
 	fb_offset += sizeof(struct l2_ethhdr);
d58598
 
d58598
-	np = find_module_by_id(&lldp_head, LLDP_MOD_MAND);
d58598
+	np = find_module_by_id(&lldp_mod_head, LLDP_MOD_MAND);
d58598
 	if (!np)
d58598
 		goto error;
d58598
 	if (!np->ops || !np->ops->lldp_mod_gettlv)
d58598
@@ -220,7 +220,7 @@ bool mibConstrShutdownLLDPDU(struct port
d58598
 		memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size);
d58598
 		datasize += ptlv->size;
d58598
 		fb_offset += ptlv->size;
d58598
-		ptlv =  free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
 	}
d58598
 
d58598
 	/* The End TLV marks the end of the LLDP PDU */
d58598
@@ -230,7 +230,7 @@ bool mibConstrShutdownLLDPDU(struct port
d58598
 	memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size);
d58598
 	datasize += ptlv->size;
d58598
 	fb_offset += ptlv->size;
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 
d58598
 	if (datasize < ETH_MIN_DATA_LEN)
d58598
 		agent->tx.sizeout = ETH_ZLEN;
d58598
@@ -239,7 +239,7 @@ bool mibConstrShutdownLLDPDU(struct port
d58598
 	return true;
d58598
 
d58598
 error:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 	if (agent->tx.frameout)
d58598
 		free(agent->tx.frameout);
d58598
 	agent->tx.frameout = NULL;
d58598
@@ -270,7 +270,7 @@ void run_tx_sm(struct port *port, struct
d58598
 			process_tx_idle(agent);
d58598
 			break;
d58598
 		case TX_SHUTDOWN_FRAME:
d58598
-			process_tx_shutdown_frame(port, agent);
d58598
+			process_tx_shutdown_frame(port, agent, true);
d58598
 			break;
d58598
 		case TX_INFO_FRAME:
d58598
 			process_tx_info_frame(port, agent);
d58598
@@ -330,8 +330,19 @@ void process_tx_idle(UNUSED struct lldp_
d58598
 	return;
d58598
 }
d58598
 
d58598
-void process_tx_shutdown_frame(struct port *port, struct lldp_agent *agent)
d58598
+/* we ignore 'adminStatus' in the case that we have recently transitioned
d58598
+ * to the shutdown state (in the case of the 'tx' state change) to allow
d58598
+ * for transmitting the ttl==0 as required by the IEEE standard. */
d58598
+void process_tx_shutdown_frame(struct port *port, struct lldp_agent *agent,
d58598
+				bool ignoreStatus)
d58598
 {
d58598
+	if (agent->adminStatus != enabledRxTx &&
d58598
+	    agent->adminStatus != enabledTxOnly) {
d58598
+		if (!ignoreStatus) {
d58598
+			return;
d58598
+		}
d58598
+	}
d58598
+
d58598
 	if (agent->timers.txShutdownWhile == 0) {
d58598
 		if (mibConstrShutdownLLDPDU(port, agent))
d58598
 			txFrame(port, agent);
d58598
diff -upr a/lldp_8021qaz.c b/lldp_8021qaz.c
d58598
--- a/lldp_8021qaz.c	2021-06-09 10:58:59.217200668 -0400
d58598
+++ b/lldp_8021qaz.c	2020-11-03 09:08:48.059229036 -0500
d58598
@@ -48,8 +48,8 @@
d58598
 #include "lldp_dcbx.h"
d58598
 
d58598
 
d58598
-struct lldp_head lldp_head;
d58598
-struct config_t lldpad_cfg;
d58598
+extern config_t lldpad_cfg;
d58598
+extern bool read_only_8021qaz;
d58598
 
d58598
 static int ieee8021qaz_check_pending(struct port *port, struct lldp_agent *);
d58598
 static void run_all_sm(struct port *port, struct lldp_agent *agent);
d58598
@@ -83,7 +83,7 @@ static int ieee8021qaz_check_pending(str
d58598
 	if (!port->portEnabled)
d58598
 		return 0;
d58598
 
d58598
-	iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ);
d58598
+	iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ);
d58598
 	if (iud) {
d58598
 		LIST_FOREACH(tlv, &iud->head, entry) {
d58598
 			if (!strncmp(port->ifname, tlv->ifname, IFNAMSIZ)) {
d58598
@@ -111,14 +111,14 @@ struct lldp_module *ieee8021qaz_register
d58598
 
d58598
 	mod = malloc(sizeof(*mod));
d58598
 	if (!mod) {
d58598
-		LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module data");
d58598
+		LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module data\n");
d58598
 		goto out_err;
d58598
 	}
d58598
 
d58598
 	iud = malloc(sizeof(*iud));
d58598
 	if (!iud) {
d58598
 		free(mod);
d58598
-		LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module user data");
d58598
+		LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module user data\n");
d58598
 		goto out_err;
d58598
 	}
d58598
 	memset((void *) iud, 0, sizeof(struct ieee8021qaz_user_data));
d58598
@@ -142,7 +142,7 @@ struct ieee8021qaz_tlvs *ieee8021qaz_dat
d58598
 	struct ieee8021qaz_user_data *iud;
d58598
 	struct ieee8021qaz_tlvs *tlv = NULL;
d58598
 
d58598
-	iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ);
d58598
+	iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ);
d58598
 	if (iud) {
d58598
 		LIST_FOREACH(tlv, &iud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
@@ -396,7 +396,7 @@ static int read_cfg_file(char *ifname, s
d58598
 	return 0;
d58598
 }
d58598
 
d58598
-inline int get_prio_map(u32 prio_map, int prio)
d58598
+static int get_prio_map(u32 prio_map, int prio)
d58598
 {
d58598
 	if (prio > 7)
d58598
 		return 0;
d58598
@@ -404,7 +404,7 @@ inline int get_prio_map(u32 prio_map, in
d58598
 	return (prio_map >> (4 * (7-prio))) & 0xF;
d58598
 }
d58598
 
d58598
-inline void set_prio_map(u32 *prio_map, u8 prio, int tc)
d58598
+static void set_prio_map(u32 *prio_map, u8 prio, int tc)
d58598
 {
d58598
 	u32 mask = ~(0xffffffff & (0xF << (4 * (7-prio))));
d58598
 	*prio_map &= mask;
d58598
@@ -590,7 +590,7 @@ void ieee8021qaz_ifup(char *ifname, stru
d58598
 	memset(tlvs->rx, 0, sizeof(*tlvs->rx));
d58598
 
d58598
 	/* Initializing the ieee8021qaz_tlvs struct */
d58598
-	strncpy(tlvs->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(tlvs->ifname, ifname, IFNAMSIZ);
d58598
 	tlvs->port = port;
d58598
 	tlvs->ieee8021qazdu = 0;
d58598
 	l2_packet_get_own_src_addr(port->l2, tlvs->local_mac);
d58598
@@ -628,7 +628,7 @@ void ieee8021qaz_ifup(char *ifname, stru
d58598
 	LIST_INIT(&tlvs->app_head);
d58598
 	read_cfg_file(port->ifname, agent, tlvs);
d58598
 
d58598
-	iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ);
d58598
+	iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ);
d58598
 	LIST_INSERT_HEAD(&iud->head, tlvs, entry);
d58598
 
d58598
 initialized:
d58598
@@ -959,6 +959,9 @@ static int del_ieee_hw(const char *ifnam
d58598
 			   .dcb_pad = 0
d58598
 			  };
d58598
 
d58598
+	if (read_only_8021qaz)
d58598
+		return 0;
d58598
+
d58598
 	nlsocket = nl_socket_alloc();
d58598
 	if (!nlsocket) {
d58598
 		LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n",
d58598
@@ -1042,6 +1045,9 @@ static int set_ieee_hw(const char *ifnam
d58598
 			   .dcb_pad = 0
d58598
 			  };
d58598
 
d58598
+	if (read_only_8021qaz)
d58598
+		return 0;
d58598
+
d58598
 	nlsocket = nl_socket_alloc();
d58598
 	if (!nlsocket) {
d58598
 		LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n",
d58598
@@ -1618,15 +1624,15 @@ static void clear_ieee8021qaz_rx(struct
d58598
 		return;
d58598
 
d58598
 	if (tlvs->rx->ieee8021qaz)
d58598
-		tlvs->rx->ieee8021qaz = free_unpkd_tlv(tlvs->rx->ieee8021qaz);
d58598
+		free_unpkd_tlv(tlvs->rx->ieee8021qaz);
d58598
 	if (tlvs->rx->etscfg)
d58598
-		tlvs->rx->etscfg = free_unpkd_tlv(tlvs->rx->etscfg);
d58598
+		free_unpkd_tlv(tlvs->rx->etscfg);
d58598
 	if (tlvs->rx->etsrec)
d58598
-		tlvs->rx->etsrec = free_unpkd_tlv(tlvs->rx->etsrec);
d58598
+		free_unpkd_tlv(tlvs->rx->etsrec);
d58598
 	if (tlvs->rx->pfc)
d58598
-		tlvs->rx->pfc = free_unpkd_tlv(tlvs->rx->pfc);
d58598
+		free_unpkd_tlv(tlvs->rx->pfc);
d58598
 	if (tlvs->rx->app)
d58598
-		tlvs->rx->app =	free_unpkd_tlv(tlvs->rx->app);
d58598
+		free_unpkd_tlv(tlvs->rx->app);
d58598
 
d58598
 	free(tlvs->rx);
d58598
 	tlvs->rx = NULL;
d58598
@@ -2014,13 +2020,13 @@ static void ieee8021qaz_free_rx(struct i
d58598
 		return;
d58598
 
d58598
 	if (rx->etscfg)
d58598
-		rx->etscfg = free_unpkd_tlv(rx->etscfg);
d58598
+		free_unpkd_tlv(rx->etscfg);
d58598
 	if (rx->etsrec)
d58598
-		rx->etsrec = free_unpkd_tlv(rx->etsrec);
d58598
+		free_unpkd_tlv(rx->etsrec);
d58598
 	if (rx->pfc)
d58598
-		rx->pfc = free_unpkd_tlv(rx->pfc);
d58598
+		free_unpkd_tlv(rx->pfc);
d58598
 	if (rx->app)
d58598
-		rx->app = free_unpkd_tlv(rx->app);
d58598
+		free_unpkd_tlv(rx->app);
d58598
 
d58598
 	return;
d58598
 }
d58598
@@ -2106,9 +2112,9 @@ static void ieee8021qaz_free_tlv(struct
d58598
 		return;
d58598
 
d58598
 	if (tlvs->ets)
d58598
-		tlvs->ets = free_ets_tlv(tlvs->ets);
d58598
+		free_ets_tlv(tlvs->ets);
d58598
 	if (tlvs->pfc)
d58598
-		tlvs->pfc = free_pfc_tlv(tlvs->pfc);
d58598
+		free_pfc_tlv(tlvs->pfc);
d58598
 
d58598
 	/* Remove _all_ existing application data */
d58598
 	LIST_FOREACH(np, &tlvs->app_head, entry)
d58598
@@ -2172,7 +2178,7 @@ int ieee8021qaz_tlvs_rxed(const char *if
d58598
 	struct ieee8021qaz_user_data *iud;
d58598
 	struct ieee8021qaz_tlvs *tlv = NULL;
d58598
 
d58598
-	iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ);
d58598
+	iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ);
d58598
 	if (iud) {
d58598
 		LIST_FOREACH(tlv, &iud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
@@ -2191,7 +2197,7 @@ int ieee8021qaz_check_active(const char
d58598
 	struct ieee8021qaz_user_data *iud;
d58598
 	struct ieee8021qaz_tlvs *tlv = NULL;
d58598
 
d58598
-	iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ);
d58598
+	iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ);
d58598
 	if (iud) {
d58598
 		LIST_FOREACH(tlv, &iud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
diff -upr a/lldp_8021qaz_clif.c b/lldp_8021qaz_clif.c
d58598
--- a/lldp_8021qaz_clif.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_8021qaz_clif.c	2020-09-23 08:50:52.650813901 -0400
d58598
@@ -251,40 +251,70 @@ static void ieee8021qaz_print_pfc_tlv(UN
d58598
 
d58598
 static void ieee8021qaz_print_app_tlv(u16 len, char *info)
d58598
 {
d58598
-	u8 offset = 2;
d58598
-	u8 app;
d58598
-	u16 proto;
d58598
+	u8 app, app_idx, app_prio, app_sel;
d58598
+	u16 proto, offset = 2;
d58598
+	u8 dscp[MAX_USER_PRIORITIES][MAX_APP_ENTRIES];
d58598
+	u8 dscp_count[MAX_USER_PRIORITIES] = {0};
d58598
+	u8 i, j;
d58598
+	bool first_app = true;
d58598
 
d58598
 	while (offset < len*2) {
d58598
 		hexstr2bin(info + offset, &app, 1);
d58598
 		hexstr2bin(info + offset + 2, (u8 *)&proto, 2);
d58598
 
d58598
-		if (offset > 6)
d58598
-			printf("\t");
d58598
-		printf("App#%i:\n", offset/6);
d58598
-		printf("\t Priority: %i\n", (app & 0xE0) >> 5);
d58598
-		printf("\t Sel: %i\n", app & 0x07);
d58598
-		switch (app & 0x07) {
d58598
-		case 1:
d58598
-			printf("\t Ethertype: 0x%04x\n", ntohs(proto));
d58598
-			break;
d58598
-		case 2:
d58598
-			printf("\t {S}TCP Port: %i\n", ntohs(proto));
d58598
-			break;
d58598
-		case 3:
d58598
-			printf("\t UDP or DCCP Port: %i\n", ntohs(proto));
d58598
-			break;
d58598
-		case 4:
d58598
-			printf("\t TCP/STCP/UDP/DCCP Port: %i\n", ntohs(proto));
d58598
-			break;
d58598
-		default:
d58598
-			printf("\t Reserved Port: %i\n", ntohs(proto));
d58598
-			break;
d58598
+		app_idx = offset/6;
d58598
+		app_prio = (app & 0xE0) >> 5;
d58598
+		app_sel = app & 0x07;
d58598
+
d58598
+		// Selector five is DSCP. Save value to print table at the end
d58598
+		if (app_sel == 5) {
d58598
+			dscp[app_prio][dscp_count[app_prio]] = ntohs(proto) & 0x3F;
d58598
+			dscp_count[app_prio]++;
d58598
+		} else {
d58598
+			if (first_app)
d58598
+				first_app = false;
d58598
+			else
d58598
+				printf("\t");
d58598
+			printf("App# %3i \t Prio %1i \t Sel %1i \t P-ID", 
d58598
+				app_idx, app_prio, app_sel);
d58598
+	
d58598
+			switch (app_sel) {
d58598
+			case 1:
d58598
+				printf("\t Ethertype: 0x%04x\n", ntohs(proto));
d58598
+				break;
d58598
+			case 2:
d58598
+				printf("\t {S}TCP Port: %i\n", ntohs(proto));
d58598
+				break;
d58598
+			case 3:
d58598
+				printf("\t UDP or DCCP Port: %i\n", ntohs(proto));
d58598
+				break;
d58598
+			case 4:
d58598
+				printf("\t TCP/STCP/UDP/DCCP Port: %i\n", ntohs(proto));
d58598
+				break;
d58598
+			default:
d58598
+				printf("\t Reserved Port: %i\n", ntohs(proto));
d58598
+				break;
d58598
+			}
d58598
 		}
d58598
 
d58598
-		printf("\n");
d58598
 		offset += 6;
d58598
 	}
d58598
+
d58598
+	for(i=0; i
d58598
+		if (dscp_count[i] == 0)
d58598
+			continue;
d58598
+
d58598
+		if (first_app)
d58598
+		        first_app = false;
d58598
+		else
d58598
+		        printf("\t");
d58598
+		printf("Prio:%i \t dscp: ", i);
d58598
+
d58598
+		for(j=0; j
d58598
+			printf(" %02i,", dscp[i][j]);
d58598
+		}
d58598
+		printf("\b \n");
d58598
+	}
d58598
 }
d58598
 
d58598
 int ieee8021qaz_print_tlv(u32 tlvid, u16 len, char *info)
d58598
diff -upr a/lldp_8021qaz_cmds.c b/lldp_8021qaz_cmds.c
d58598
--- a/lldp_8021qaz_cmds.c	2021-06-09 10:58:59.218200681 -0400
d58598
+++ b/lldp_8021qaz_cmds.c	2020-09-23 08:50:52.651813919 -0400
d58598
@@ -665,7 +665,7 @@ _set_arg_tcbw(struct cmd *cmd, char *arg
d58598
 
d58598
 	strncat(obuf, "tcbw = ", obuf_len - strlen(obuf) - 1);
d58598
 	for (i = 0; i < 8; i++) {
d58598
-		char cat[5];
d58598
+		char cat[6];
d58598
 		snprintf(cat, sizeof(cat), "%i%% ", percent[i]);
d58598
 		printf("%i%% ", percent[i]);
d58598
 		strncat(obuf, cat, obuf_len - strlen(obuf) - 1);
d58598
diff -upr a/lldp_8023.c b/lldp_8023.c
d58598
--- a/lldp_8023.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_8023.c	2020-11-03 09:08:48.059229036 -0500
d58598
@@ -39,8 +39,6 @@
d58598
 #include "lldp_8023_clif.h"
d58598
 #include "lldp_8023_cmds.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 struct tlv_info_8023_maccfg {
d58598
 	u8 oui[3];
d58598
 	u8 sub;
d58598
@@ -84,7 +82,7 @@ static struct ieee8023_data *ieee8023_da
d58598
 	struct ieee8023_user_data *ud;
d58598
 	struct ieee8023_data *bd = NULL;
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8023);
d58598
 	if (ud) {
d58598
 		LIST_FOREACH(bd, &ud->head, entry) {
d58598
 			if (!strncmp(ifname, bd->ifname, IFNAMSIZ) &&
d58598
@@ -401,7 +399,7 @@ struct packed_tlv *ieee8023_gettlv(struc
d58598
 	PACK_TLV_AFTER(bd->maxfs, ptlv, size, out_free);
d58598
 	return ptlv;
d58598
 out_free:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 out_err:
d58598
 	LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname);
d58598
 	return NULL;
d58598
@@ -447,7 +445,7 @@ void ieee8023_ifup(char *ifname, struct
d58598
 		goto out_err;
d58598
 	}
d58598
 	memset(bd, 0, sizeof(struct ieee8023_data));
d58598
-	strncpy(bd->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(bd->ifname, ifname, IFNAMSIZ);
d58598
 	bd->agenttype = agent->type;
d58598
 
d58598
 	if (ieee8023_bld_tlv(bd, agent)) {
d58598
@@ -456,7 +454,7 @@ void ieee8023_ifup(char *ifname, struct
d58598
 		goto out_err;
d58598
 	}
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8023);
d58598
 	LIST_INSERT_HEAD(&ud->head, bd, entry);
d58598
 	LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
d58598
 	return;
d58598
@@ -472,13 +470,13 @@ struct lldp_module *ieee8023_register(vo
d58598
 
d58598
 	mod = malloc(sizeof(*mod));
d58598
 	if (!mod) {
d58598
-		LLDPAD_ERR("failed to malloc LLDP 802.3 module data");
d58598
+		LLDPAD_ERR("failed to malloc LLDP 802.3 module data\n");
d58598
 		goto out_err;
d58598
 	}
d58598
 	ud = malloc(sizeof(struct ieee8023_user_data));
d58598
 	if (!ud) {
d58598
 		free(mod);
d58598
-		LLDPAD_ERR("failed to malloc LLDP 802.3 module user data");
d58598
+		LLDPAD_ERR("failed to malloc LLDP 802.3 module user data\n");
d58598
 		goto out_err;
d58598
 	}
d58598
 	LIST_INIT(&ud->head);
d58598
diff -upr a/lldpad.c b/lldpad.c
d58598
--- a/lldpad.c	2021-06-09 10:58:59.208200552 -0400
d58598
+++ b/lldpad.c	2021-04-05 12:02:17.320590536 -0400
d58598
@@ -80,10 +80,13 @@ struct lldp_module *(*register_tlv_table
d58598
 	NULL,
d58598
 };
d58598
 
d58598
+struct lldp_head lldp_mod_head;
d58598
+
d58598
 char *cfg_file_name = NULL;
d58598
 bool daemonize = 0;
d58598
 int loglvl = LOG_WARNING;
d58598
 int omit_tstamp;
d58598
+bool read_only_8021qaz = false;
d58598
 
d58598
 static const char *lldpad_version =
d58598
 "lldpad v" VERSION_STR "\n"
d58598
@@ -97,7 +100,7 @@ static void init_modules(void)
d58598
 	struct lldp_module *premod = NULL;
d58598
 	int i = 0;
d58598
 
d58598
-	LIST_INIT(&lldp_head);
d58598
+	LIST_INIT(&lldp_mod_head);
d58598
 	for (i = 0; register_tlv_table[i]; i++) {
d58598
 		module = register_tlv_table[i]();
d58598
 		if (!module)
d58598
@@ -105,7 +108,7 @@ static void init_modules(void)
d58598
 		if (premod)
d58598
 			LIST_INSERT_AFTER(premod, module, lldp);
d58598
 		else
d58598
-			LIST_INSERT_HEAD(&lldp_head, module, lldp);
d58598
+			LIST_INSERT_HEAD(&lldp_mod_head, module, lldp);
d58598
 		premod = module;
d58598
 	}
d58598
 }
d58598
@@ -114,9 +117,9 @@ void deinit_modules(void)
d58598
 {
d58598
 	struct lldp_module *module;
d58598
 
d58598
-	while (lldp_head.lh_first != NULL) {
d58598
-		module = lldp_head.lh_first;
d58598
-		LIST_REMOVE(lldp_head.lh_first, lldp);
d58598
+	while (lldp_mod_head.lh_first != NULL) {
d58598
+		module = lldp_mod_head.lh_first;
d58598
+		LIST_REMOVE(lldp_mod_head.lh_first, lldp);
d58598
 		module->ops->lldp_mod_unregister(module);
d58598
 	}
d58598
 }
d58598
@@ -136,7 +139,8 @@ static void usage(void)
d58598
 		"   -t  omit timestamps in log messages\n"
d58598
 		"   -v  show version\n"
d58598
 		"   -f  use configfile instead of default\n"
d58598
-		"   -V  set syslog level\n");
d58598
+		"   -V  set syslog level\n"
d58598
+		"   -R  run 8021qaz module in read_only mode\n");
d58598
 
d58598
 	exit(1);
d58598
 }
d58598
@@ -236,7 +240,7 @@ int main(int argc, char *argv[])
d58598
 	int rc = 1;
d58598
 
d58598
 	for (;;) {
d58598
-		c = getopt(argc, argv, "hdksptvf:V:");
d58598
+		c = getopt(argc, argv, "hdksptvf:RV:");
d58598
 		if (c < 0)
d58598
 			break;
d58598
 		switch (c) {
d58598
@@ -259,6 +263,9 @@ int main(int argc, char *argv[])
d58598
 		case 'p':
d58598
 			pid_file = 0;
d58598
 			break;
d58598
+		case 'R':
d58598
+			read_only_8021qaz = true;
d58598
+			break;
d58598
 		case 't':
d58598
 			omit_tstamp = 1;
d58598
 			break;
d58598
diff -upr a/lldpad.service b/lldpad.service
d58598
--- a/lldpad.service	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldpad.service	2020-09-23 08:50:52.655813990 -0400
d58598
@@ -1,9 +1,11 @@
d58598
 [Unit]
d58598
 Description=Link Layer Discovery Protocol Agent Daemon.
d58598
 After=syslog.target network.target
d58598
+Requires=lldpad.socket
d58598
 
d58598
 [Service]
d58598
 Type=simple
d58598
+Restart=always
d58598
 ExecStart=/usr/sbin/lldpad -t
d58598
 ExecReload=/bin/kill -HUP $MAINPID
d58598
 
d58598
diff -upr a/lldpad.socket b/lldpad.socket
d58598
--- a/lldpad.socket	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldpad.socket	2020-09-23 08:50:52.655813990 -0400
d58598
@@ -1,3 +1,6 @@
d58598
+[Unit]
d58598
+Description=Link Layer Discovery Protocol Agent Socket.
d58598
+
d58598
 [Socket]
d58598
 ListenDatagram=@/com/intel/lldpad
d58598
 PassCredentials=true
d58598
diff -upr a/lldpad.spec.in b/lldpad.spec.in
d58598
--- a/lldpad.spec.in	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldpad.spec.in	2020-09-23 08:50:52.655813990 -0400
d58598
@@ -10,9 +10,9 @@ Source0:        http://downloads.sourcef
d58598
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
d58598
 
d58598
 # BuildRequires:  
d58598
-Requires(post):   chkconfig
d58598
-Requires(preun):  chkconfig initscripts
d58598
-Requires(postun): initscripts
d58598
+Requires(post):   @SPEC_BUILD_REQUIRES_POST@
d58598
+Requires(preun):  @SPEC_BUILD_REQUIRES_PREUN@
d58598
+Requires(postun): @SPEC_BUILD_REQUIRES_POSTUN@
d58598
 
d58598
 %description
d58598
 This package contains the Linux user space daemon and configuration tool for
d58598
@@ -46,20 +46,36 @@ rm -rf $RPM_BUILD_ROOT
d58598
 
d58598
 
d58598
 %post
d58598
-/sbin/chkconfig --add lldpad 
d58598
+if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then
d58598
+	/sbin/chkconfig --add %{name}
d58598
+fi
d58598
+if type systemctl >/dev/null 2>&1; then
d58598
+	# Scriplet only runs preset. Run enable/start manually
d58598
+	%systemd_post %{name}.socket %{name}.service
d58598
+fi
d58598
 
d58598
 %preun
d58598
 if [ $1 = 0 ]; then
d58598
-        /sbin/service lldpad stop
d58598
-        /sbin/chkconfig --del lldpad 
d58598
+	if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then
d58598
+		/sbin/service %{name} stop
d58598
+		/sbin/chkconfig --del %{name}
d58598
+	fi
d58598
+	if type systemctl >/dev/null 2>&1; then
d58598
+		%systemd_preun %{name}.service %{name}.socket
d58598
+	fi
d58598
 fi
d58598
 
d58598
 %postun
d58598
 if [ $1 = 1 ]; then
d58598
-        /sbin/service lldpad condrestart
d58598
+	# Package upgrade, not uninstall
d58598
+	if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then
d58598
+		/sbin/service %{name} condrestart
d58598
+	fi
d58598
+	if type systemctl >/dev/null 2>&1; then
d58598
+		%systemd_postun_with_restart %{name}.socket %{name}.service
d58598
+	fi
d58598
 fi
d58598
 
d58598
-
d58598
 %files
d58598
 %defattr(-,root,root,-)
d58598
 %doc COPYING
d58598
@@ -67,11 +83,13 @@ fi
d58598
 %doc ChangeLog
d58598
 %{_sbindir}/*
d58598
 %dir /var/lib/lldpad
d58598
-%{_sysconfdir}/init.d/lldpad
d58598
+@SPEC_FILE_LLDPAD_SERVICE@
d58598
+@SPEC_FILE_LLDPAD_SOCKET@
d58598
 %{_sysconfdir}/bash_completion.d/lldpad
d58598
 %{_sysconfdir}/bash_completion.d/lldptool
d58598
 %{_mandir}/man8/*
d58598
 %{_libdir}/liblldp_clif.*
d58598
+%{_mandir}/man3/liblldp_clif-vdp22.*
d58598
 
d58598
 %files devel
d58598
 %defattr(-,root,root,-)
d58598
diff -upr a/lldp_basman.c b/lldp_basman.c
d58598
--- a/lldp_basman.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_basman.c	2020-11-03 09:08:48.059229036 -0500
d58598
@@ -75,8 +75,6 @@ struct tlv_info_manaddr {
d58598
 	struct tlv_info_maoid o;
d58598
 } __attribute__ ((__packed__));
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 static const struct lldp_mod_ops basman_ops =  {
d58598
 	.lldp_mod_register 	= basman_register,
d58598
 	.lldp_mod_unregister 	= basman_unregister,
d58598
@@ -91,7 +89,7 @@ static struct basman_data *basman_data(c
d58598
 	struct basman_user_data *bud;
d58598
 	struct basman_data *bd = NULL;
d58598
 
d58598
-	bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC);
d58598
+	bud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_BASIC);
d58598
 	if (bud) {
d58598
 		LIST_FOREACH(bd, &bud->head, entry) {
d58598
 			if (!strncmp(ifname, bd->ifname, IFNAMSIZ) &&
d58598
@@ -636,7 +634,7 @@ struct packed_tlv *basman_gettlv(struct
d58598
 		PACK_TLV_AFTER(bd->manaddr[i], ptlv, size, out_free);
d58598
 	return ptlv;
d58598
 out_free:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 out_err:
d58598
 	LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname);
d58598
 	return NULL;
d58598
@@ -679,7 +677,7 @@ void basman_ifup(char *ifname, struct ll
d58598
 		goto out_err;
d58598
 	}
d58598
 	memset(bd, 0, sizeof(struct basman_data));
d58598
-	strncpy(bd->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(bd->ifname, ifname, IFNAMSIZ);
d58598
 	bd->agenttype = agent->type;
d58598
 
d58598
 	if (basman_bld_tlv(bd, agent)) {
d58598
@@ -688,7 +686,7 @@ void basman_ifup(char *ifname, struct ll
d58598
 		goto out_err;
d58598
 	}
d58598
 
d58598
-	bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC);
d58598
+	bud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_BASIC);
d58598
 	LIST_INSERT_HEAD(&bud->head, bd, entry);
d58598
 	LLDPAD_DBG("%s:port %s added\n", __func__, ifname);
d58598
 	return;
d58598
diff -upr a/lldp_basman_cmds.c b/lldp_basman_cmds.c
d58598
--- a/lldp_basman_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_basman_cmds.c	2020-09-23 08:50:52.652813936 -0400
d58598
@@ -51,6 +51,9 @@ static int test_arg_ipv6(struct cmd *, c
d58598
 static int get_arg_tlvtxenable(struct cmd *, char *, char *, char *, int);
d58598
 static int set_arg_tlvtxenable(struct cmd *, char *, char *, char *, int);
d58598
 static int test_arg_tlvtxenable(struct cmd *, char *, char *, char *, int);
d58598
+static int get_arg_info(struct cmd *, char *, char *, char *, int);
d58598
+static int set_arg_info(struct cmd *, char *, char *, char *, int);
d58598
+static int test_arg_info(struct cmd *, char *, char *, char *, int);
d58598
 
d58598
 static struct arg_handlers arg_handlers[] = {
d58598
 	{	.arg = ARG_IPV4_ADDR, .arg_class = TLV_ARG,
d58598
@@ -65,6 +68,10 @@ static struct arg_handlers arg_handlers[
d58598
 		.handle_get = get_arg_tlvtxenable,
d58598
 		.handle_set = set_arg_tlvtxenable,
d58598
 		.handle_test = test_arg_tlvtxenable },
d58598
+	{	.arg = ARG_TLVINFO, .arg_class = TLV_ARG,
d58598
+		.handle_get = get_arg_info,
d58598
+		.handle_set = set_arg_info,
d58598
+		.handle_test = test_arg_info },
d58598
 	{	.arg = 0 }
d58598
 };
d58598
 
d58598
@@ -166,6 +173,89 @@ static int test_arg_tlvtxenable(struct c
d58598
 	return _set_arg_tlvtxenable(cmd, arg, argvalue, obuf, obuf_len, true);
d58598
 }
d58598
 
d58598
+static int get_arg_info(struct cmd *cmd, char *arg, UNUSED char *argvalue,
d58598
+			char *obuf, int obuf_len)
d58598
+{
d58598
+	const char *info_str = NULL;
d58598
+	char arg_path[256];
d58598
+
d58598
+	if (cmd->cmd != cmd_gettlv)
d58598
+		return cmd_invalid;
d58598
+
d58598
+	switch (cmd->tlvid) {
d58598
+	case PORT_DESCRIPTION_TLV:
d58598
+	case SYSTEM_NAME_TLV:
d58598
+	case SYSTEM_DESCRIPTION_TLV:
d58598
+	case SYSTEM_CAPABILITIES_TLV:
d58598
+	case MANAGEMENT_ADDRESS_TLV:
d58598
+		snprintf(arg_path, sizeof(arg_path), "%s%08x.%s",
d58598
+			 TLVID_PREFIX, cmd->tlvid, arg);
d58598
+
d58598
+		get_config_setting(cmd->ifname, cmd->type, arg_path,
d58598
+				   &info_str, CONFIG_TYPE_STRING);
d58598
+		break;
d58598
+	case INVALID_TLVID:
d58598
+		return cmd_invalid;
d58598
+	default:
d58598
+		return cmd_not_applicable;
d58598
+	}
d58598
+
d58598
+	if (info_str)
d58598
+		snprintf(obuf, obuf_len, "%02x%s%04x%s",
d58598
+			 (unsigned int)strlen(arg), arg,
d58598
+			 (unsigned int)strlen(info_str), info_str);
d58598
+
d58598
+	return cmd_success;
d58598
+}
d58598
+
d58598
+static int _set_arg_info(struct cmd *cmd, UNUSED char *arg, char *argvalue, 
d58598
+			 char *obuf, int obuf_len, bool test)
d58598
+{
d58598
+	if (cmd->cmd != cmd_settlv)
d58598
+		return cmd_invalid;
d58598
+
d58598
+	switch (cmd->tlvid) {
d58598
+	case PORT_DESCRIPTION_TLV:
d58598
+	case SYSTEM_NAME_TLV:
d58598
+	case SYSTEM_DESCRIPTION_TLV:
d58598
+	case SYSTEM_CAPABILITIES_TLV:
d58598
+	case MANAGEMENT_ADDRESS_TLV:
d58598
+		break;
d58598
+	case INVALID_TLVID:
d58598
+		return cmd_invalid;
d58598
+	default:
d58598
+		return cmd_not_applicable;
d58598
+	}
d58598
+
d58598
+        if (strlen(argvalue) < 1)
d58598
+		return cmd_invalid;
d58598
+
d58598
+	if (test)
d58598
+		return cmd_success;
d58598
+
d58598
+	if (set_config_tlvinfo_str(cmd->ifname, cmd->type, 
d58598
+				   cmd->tlvid, argvalue))
d58598
+		return cmd_failed;
d58598
+
d58598
+	snprintf(obuf, obuf_len, "enableTx = %s\n", argvalue);
d58598
+
d58598
+	somethingChangedLocal(cmd->ifname, cmd->type);
d58598
+
d58598
+	return cmd_success;
d58598
+}
d58598
+
d58598
+static int set_arg_info(struct cmd *cmd, char *arg, char *argvalue, 
d58598
+			char *obuf, int obuf_len)
d58598
+{
d58598
+	return _set_arg_info(cmd, arg, argvalue, obuf, obuf_len, false);
d58598
+}
d58598
+
d58598
+static int test_arg_info(struct cmd *cmd, char *arg, char *argvalue,
d58598
+			 char *obuf, int obuf_len)
d58598
+{
d58598
+	return _set_arg_info(cmd, arg, argvalue, obuf, obuf_len, true);
d58598
+}
d58598
+
d58598
 struct arg_handlers *basman_get_arg_handlers()
d58598
 {
d58598
 	return &arg_handlers[0];
d58598
diff -upr a/lldp_dcbx.c b/lldp_dcbx.c
d58598
--- a/lldp_dcbx.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_dcbx.c	2020-10-23 14:12:58.975289310 -0400
d58598
@@ -129,7 +129,7 @@ struct dcbx_tlvs *dcbx_data(const char *
d58598
 	struct dcbd_user_data *dud;
d58598
 	struct dcbx_tlvs *tlv = NULL;
d58598
 
d58598
-	dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
d58598
+	dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX);
d58598
 	if (dud) {
d58598
 		LIST_FOREACH(tlv, &dud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
@@ -148,7 +148,7 @@ int dcbx_tlvs_rxed(const char *ifname, s
d58598
 	if (agent->type != NEAREST_BRIDGE)
d58598
 		return 0;
d58598
 
d58598
-	dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
d58598
+	dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX);
d58598
 	if (dud) {
d58598
 		LIST_FOREACH(tlv, &dud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
@@ -172,7 +172,7 @@ int dcbx_check_active(const char *ifname
d58598
 	struct dcbd_user_data *dud;
d58598
 	struct dcbx_tlvs *tlv = NULL;
d58598
 
d58598
-	dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
d58598
+	dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX);
d58598
 	if (dud) {
d58598
 		LIST_FOREACH(tlv, &dud->head, entry) {
d58598
 			if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
d58598
@@ -194,6 +194,8 @@ int dcbx_bld_tlv(struct port *newport, s
d58598
 		return 0;
d58598
 
d58598
 	tlvs = dcbx_data(newport->ifname);
d58598
+	if (!tlvs)
d58598
+		return 0;
d58598
 
d58598
 	get_config_setting(newport->ifname, agent->type, ARG_ADMINSTATUS,
d58598
 			  &adminstatus, CONFIG_TYPE_INT);
d58598
@@ -283,20 +285,20 @@ void dcbx_free_manifest(struct dcbx_mani
d58598
 		return;
d58598
 
d58598
 	if (manifest->dcbx1)
d58598
-		manifest->dcbx1 = free_unpkd_tlv(manifest->dcbx1);
d58598
+		free_unpkd_tlv(manifest->dcbx1);
d58598
 	if (manifest->dcbx2)
d58598
-		manifest->dcbx2 = free_unpkd_tlv(manifest->dcbx2);
d58598
+		free_unpkd_tlv(manifest->dcbx2);
d58598
 	if (manifest->dcbx_ctrl)
d58598
-		manifest->dcbx_ctrl = free_unpkd_tlv(manifest->dcbx_ctrl);
d58598
+		free_unpkd_tlv(manifest->dcbx_ctrl);
d58598
 	if (manifest->dcbx_pg)
d58598
-		manifest->dcbx_pg = free_unpkd_tlv(manifest->dcbx_pg);
d58598
+		free_unpkd_tlv(manifest->dcbx_pg);
d58598
 	if (manifest->dcbx_pfc)
d58598
-		manifest->dcbx_pfc = free_unpkd_tlv(manifest->dcbx_pfc);
d58598
+		free_unpkd_tlv(manifest->dcbx_pfc);
d58598
 	if (manifest->dcbx_app)
d58598
-		manifest->dcbx_app = free_unpkd_tlv(manifest->dcbx_app);
d58598
+		free_unpkd_tlv(manifest->dcbx_app);
d58598
 	if (manifest->dcbx_llink)
d58598
-		manifest->dcbx_llink = free_unpkd_tlv(manifest->dcbx_llink);
d58598
-
d58598
+		free_unpkd_tlv(manifest->dcbx_llink);
d58598
+	free(manifest);
d58598
 	return;
d58598
 }
d58598
 
d58598
@@ -305,44 +307,27 @@ void dcbx_free_tlv(struct dcbx_tlvs *tlv
d58598
 	if (!tlvs)
d58598
 		return;
d58598
 
d58598
-	if (tlvs->control != NULL) {
d58598
-		tlvs->control = free_unpkd_tlv(tlvs->control);
d58598
-	}
d58598
-
d58598
-	if (tlvs->pg1 != NULL) {
d58598
-		tlvs->pg1 = free_unpkd_tlv(tlvs->pg1);
d58598
-	}
d58598
-
d58598
-	if (tlvs->pg2 != NULL) {
d58598
-		tlvs->pg2 = free_unpkd_tlv(tlvs->pg2);
d58598
-	}
d58598
-
d58598
-	if (tlvs->pfc1 != NULL) {
d58598
-		tlvs->pfc1 = free_unpkd_tlv(tlvs->pfc1);
d58598
-	}
d58598
-
d58598
-	if (tlvs->pfc2 != NULL) {
d58598
-		tlvs->pfc2 = free_unpkd_tlv(tlvs->pfc2);
d58598
-	}
d58598
-
d58598
-	if (tlvs->app1 != NULL) {
d58598
-		tlvs->app1 = free_unpkd_tlv(tlvs->app1);
d58598
-	}
d58598
-
d58598
-	if (tlvs->app2 != NULL)
d58598
-		tlvs->app2 = free_unpkd_tlv(tlvs->app2);
d58598
+	if (tlvs->control)
d58598
+		free_unpkd_tlv(tlvs->control);
d58598
+	if (tlvs->pg1)
d58598
+		free_unpkd_tlv(tlvs->pg1);
d58598
+	if (tlvs->pg2)
d58598
+		free_unpkd_tlv(tlvs->pg2);
d58598
+	if (tlvs->pfc1)
d58598
+		free_unpkd_tlv(tlvs->pfc1);
d58598
+	if (tlvs->pfc2)
d58598
+		free_unpkd_tlv(tlvs->pfc2);
d58598
+	if (tlvs->app1)
d58598
+		free_unpkd_tlv(tlvs->app1);
d58598
+	if (tlvs->app2)
d58598
+		free_unpkd_tlv(tlvs->app2);
d58598
+	if (tlvs->llink)
d58598
+		free_unpkd_tlv(tlvs->llink);
d58598
+	if (tlvs->dcbx1)
d58598
+		free_unpkd_tlv(tlvs->dcbx1);
d58598
+	if (tlvs->dcbx2)
d58598
+		free_unpkd_tlv(tlvs->dcbx2);
d58598
 
d58598
-	if (tlvs->llink != NULL) {
d58598
-		tlvs->llink = free_unpkd_tlv(tlvs->llink);
d58598
-	}
d58598
-
d58598
-	if (tlvs->dcbx1 != NULL) {
d58598
-		tlvs->dcbx1 = free_unpkd_tlv(tlvs->dcbx1);
d58598
-	}
d58598
-
d58598
-	if (tlvs->dcbx2 != NULL) {
d58598
-		tlvs->dcbx2 = free_unpkd_tlv(tlvs->dcbx2);
d58598
-	}
d58598
 	return;
d58598
 }
d58598
 
d58598
@@ -362,6 +347,7 @@ struct packed_tlv* dcbx_gettlv(struct po
d58598
 		return NULL;
d58598
 
d58598
 	dcbx_free_tlv(tlvs);
d58598
+	memset(tlvs, 0, sizeof(struct dcbx_tlvs));
d58598
 
d58598
 	dcbx_bld_tlv(port, agent);
d58598
 	if (tlvs->dcbx_st == DCBX_SUBTYPE2) {
d58598
@@ -386,7 +372,6 @@ static void dcbx_free_data(struct dcbd_u
d58598
 			LIST_REMOVE(dd, entry);
d58598
 			dcbx_free_tlv(dd);
d58598
 			dcbx_free_manifest(dd->manifest);
d58598
-			free(dd->manifest);
d58598
 			free(dd);
d58598
 		}
d58598
 	}
d58598
@@ -408,7 +393,7 @@ struct lldp_module * dcbx_register(void)
d58598
 	if (get_dcbx_version(&dcbx_version)) {
d58598
 		gdcbx_subtype = dcbx_version;
d58598
 	} else {
d58598
-		LLDPAD_ERR("failed to get DCBX version");
d58598
+		LLDPAD_ERR("failed to get DCBX version\n");
d58598
 		goto out_err;
d58598
 	}
d58598
 
d58598
@@ -505,7 +490,7 @@ void dcbx_ifup(char *ifname, struct lldp
d58598
 	ifindex = get_ifidx(ifname);
d58598
 	port = port_find_by_ifindex(ifindex);
d58598
 
d58598
-	dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
d58598
+	dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX);
d58598
 	tlvs = dcbx_data(ifname);
d58598
 
d58598
 	if (!port)
d58598
@@ -582,7 +567,7 @@ void dcbx_ifup(char *ifname, struct lldp
d58598
 	memset(manifest, 0, sizeof(*manifest));
d58598
 
d58598
 	tlvs->manifest = manifest;
d58598
-	strncpy(tlvs->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(tlvs->ifname, ifname, IFNAMSIZ);
d58598
 	tlvs->port = port;
d58598
 	tlvs->dcbdu = 0;
d58598
 	tlvs->dcbx_st = gdcbx_subtype & MASK_DCBX_FORCE;
d58598
@@ -654,7 +639,6 @@ void dcbx_ifdown(char *device_name, stru
d58598
 	LIST_REMOVE(tlvs, entry);
d58598
 	dcbx_free_tlv(tlvs);
d58598
 	dcbx_free_manifest(tlvs->manifest);
d58598
-	free(tlvs->manifest);
d58598
 	free(tlvs);
d58598
 }
d58598
 
d58598
@@ -664,26 +648,19 @@ void clear_dcbx_manifest(struct dcbx_tlv
d58598
 		return;
d58598
 
d58598
 	if (dcbx->manifest->dcbx_llink)
d58598
-		dcbx->manifest->dcbx_llink =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx_llink);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx_llink);
d58598
 	if (dcbx->manifest->dcbx_app)
d58598
-		dcbx->manifest->dcbx_app =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx_app);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx_app);
d58598
 	if (dcbx->manifest->dcbx_pfc)
d58598
-		dcbx->manifest->dcbx_pfc =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx_pfc);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx_pfc);
d58598
 	if (dcbx->manifest->dcbx_pg)
d58598
-		dcbx->manifest->dcbx_pg =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx_pg);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx_pg);
d58598
 	if (dcbx->manifest->dcbx_ctrl)
d58598
-		dcbx->manifest->dcbx_ctrl =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx_ctrl);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx_ctrl);
d58598
 	if (dcbx->manifest->dcbx1)
d58598
-		dcbx->manifest->dcbx1 =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx1);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx1);
d58598
 	if (dcbx->manifest->dcbx2)
d58598
-		dcbx->manifest->dcbx2 =
d58598
-			free_unpkd_tlv(dcbx->manifest->dcbx2);
d58598
+		free_unpkd_tlv(dcbx->manifest->dcbx2);
d58598
 	free(dcbx->manifest);
d58598
 	dcbx->manifest = NULL;
d58598
 }
d58598
diff -upr a/lldp_dcbx_cfg.c b/lldp_dcbx_cfg.c
d58598
--- a/lldp_dcbx_cfg.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_dcbx_cfg.c	2020-09-23 08:50:52.652813936 -0400
d58598
@@ -99,12 +99,15 @@ static config_setting_t *construct_new_s
d58598
 	config_setting_t *tmp2_setting = NULL;
d58598
 	char abuf[32];
d58598
 	int i;
d58598
+	char device_name_sanitized[IFNAMSIZ];
d58598
 
d58598
 	dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING);
d58598
 	if (!dcbx_setting)
d58598
 		return NULL;
d58598
 
d58598
-	eth_setting = config_setting_add(dcbx_setting, device_name,
d58598
+	config_ifkey(device_name, device_name_sanitized);
d58598
+
d58598
+	eth_setting = config_setting_add(dcbx_setting, device_name_sanitized,
d58598
 		CONFIG_TYPE_GROUP);
d58598
 	if (!eth_setting)
d58598
 		goto set_error;
d58598
@@ -371,11 +374,13 @@ static int _set_persistent(char *device_
d58598
 	config_setting_t *setting_value = NULL;
d58598
 	char abuf[2*DCB_MAX_TLV_LENGTH + 1];
d58598
 	int result, i;
d58598
+	char device_name_sanitized[IFNAMSIZ];
d58598
 
d58598
 	dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING);
d58598
+	config_ifkey(device_name, device_name_sanitized);
d58598
 	if (dcbx_setting)
d58598
 		eth_settings = config_setting_get_member(dcbx_setting,
d58598
-							 device_name);
d58598
+							 device_name_sanitized);
d58598
 
d58598
 	/* init the internal data store for device_name */
d58598
 	if (NULL == eth_settings) {
d58598
@@ -698,7 +703,7 @@ static int _set_persistent(char *device_
d58598
 	return 0;
d58598
 
d58598
 set_error:
d58598
-	LLDPAD_ERR("update of config file %s failed for %s",
d58598
+	LLDPAD_ERR("update of config file %s failed for %s\n",
d58598
 		   cfg_file_name, device_name);
d58598
 	return cmd_failed;
d58598
 }
d58598
@@ -782,22 +787,20 @@ int get_persistent(char *device_name, fu
d58598
 	int result = cmd_failed, i;
d58598
 	int results[MAX_USER_PRIORITIES];
d58598
 	int len;
d58598
-	char abuf[32];
d58598
+	char abuf[32], device_name_sanitized[IFNAMSIZ];
d58598
 
d58598
 	memset(attribs, 0, sizeof(*attribs));
d58598
 	dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING);
d58598
+
d58598
+	config_ifkey(device_name, device_name_sanitized);
d58598
 	if (dcbx_setting)
d58598
-		eth_settings = config_setting_get_member(dcbx_setting,
d58598
-							 device_name);
d58598
+		eth_settings = config_setting_get_member(dcbx_setting, 
d58598
+							 device_name_sanitized);
d58598
 
d58598
 	/* init the internal data store for device_name */
d58598
 	result = get_default_persistent(device_name, attribs);
d58598
-	if (NULL == eth_settings) {
d58598
-		assert(memcmp(device_name, DEF_CFG_STORE, 
d58598
-			strlen(DEF_CFG_STORE)));
d58598
-
d58598
+	if (NULL == eth_settings)
d58598
 		return result;
d58598
-	}
d58598
 
d58598
 	/* Read pfc setting */
d58598
 	if (get_int_config(eth_settings, "pfc_enable", TYPE_BOOL,
d58598
@@ -1071,13 +1074,16 @@ int get_dcb_enable_state(char *ifname, i
d58598
 	int rc = EINVAL;
d58598
 	config_setting_t *settings = NULL;
d58598
 	char path[sizeof(DCBX_SETTING) + IFNAMSIZ + 16];
d58598
+	char ifkey[IFNAMSIZ];
d58598
+
d58598
+	config_ifkey(ifname, ifkey);
d58598
 
d58598
 	memset(path, 0, sizeof(path));
d58598
-	snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifname);
d58598
+	snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifkey); 
d58598
 	settings = config_lookup(&lldpad_cfg, path);
d58598
 	if (!settings) {
d58598
 		LLDPAD_INFO("### %s:%s:failed on %s\n", __func__, ifname, path);
d58598
-		snprintf(path, sizeof(path), "%s.dcb_enable", ifname);
d58598
+		snprintf(path, sizeof(path), "%s.dcb_enable", ifkey); 
d58598
 		settings = config_lookup(&lldpad_cfg, path);
d58598
 		if (!settings) {
d58598
 			LLDPAD_INFO("### %s:%s:failed again %s\n", __func__, ifname, path);
d58598
diff -upr a/lldp_dcbx_cmds.c b/lldp_dcbx_cmds.c
d58598
--- a/lldp_dcbx_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_dcbx_cmds.c	2020-09-23 08:50:52.653813954 -0400
d58598
@@ -259,8 +259,12 @@ static cmd_status set_dcb_state(char *po
d58598
 
d58598
 	if (ilen == (off + CFG_DCB_DLEN)) {
d58598
 		state = (*(ibuf+off+DCB_STATE)) ^ '0';
d58598
-		set_hw_state(port_id, state);
d58598
-		rval = save_dcb_enable_state(port_id, state);
d58598
+
d58598
+		if(set_hw_state(port_id, state) < 0) {
d58598
+		    rval = cmd_not_capable;
d58598
+		} else {
d58598
+		    rval = save_dcb_enable_state(port_id, state);
d58598
+		}
d58598
 	} else {
d58598
 		printf("error - setcommand has invalid argument length\n");
d58598
 		rval = cmd_bad_params;
d58598
@@ -943,6 +947,10 @@ static int set_pg_config(pg_attribs *pg_
d58598
 	bool used[MAX_BANDWIDTH_GROUPS];
d58598
 	bool uppcts_changed = false;
d58598
 
d58598
+	/* If PG is disabled, skip changing any other attributes */
d58598
+	if (!(pg_data->protocol.Enable))
d58598
+		goto done;
d58598
+
d58598
 	plen=strlen(port_id);
d58598
 	off = DCB_PORT_OFF + plen + CFG_LEN;
d58598
 
d58598
@@ -1067,6 +1075,7 @@ static int set_pg_config(pg_attribs *pg_
d58598
 		return status;
d58598
 	}
d58598
 
d58598
+done:
d58598
 	is_pfc = get_pfc(port_id, &pfc_data);
d58598
 	if (is_pfc == cmd_success)
d58598
 		status = put_pg(port_id, pg_data, &pfc_data);
d58598
diff -upr a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c
d58598
--- a/lldp_dcbx_nl.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_dcbx_nl.c	2020-09-23 08:50:52.653813954 -0400
d58598
@@ -152,16 +152,17 @@ static int send_msg(struct nlmsghdr *nlh
d58598
 {
d58598
 	struct sockaddr_nl nladdr;
d58598
 	void *buf = (void *)nlh;
d58598
-	int r, len = nlh->nlmsg_len;
d58598
+	int r;
d58598
 
d58598
 	if (nlh == NULL)
d58598
 		return 1;
d58598
 
d58598
 	memset(&nladdr, 0, sizeof(nladdr));
d58598
 	nladdr.nl_family = AF_NETLINK;
d58598
-	
d58598
+
d58598
 	do {
d58598
-		r = sendto(nl_sd, buf, len, 0, (struct sockaddr *)&nladdr,
d58598
+		r = sendto(nl_sd, buf, nlh->nlmsg_len, 0,
d58598
+			   (struct sockaddr *)&nladdr,
d58598
 			sizeof(nladdr));
d58598
 		LLDPAD_DBG("send_msg: sendto = %d\n", r);
d58598
 
d58598
@@ -561,7 +562,7 @@ int get_dcb_numtcs(const char *ifname, u
d58598
 
d58598
 	seq = nlh->nlmsg_seq;
d58598
 
d58598
-	strncpy(name, ifname, sizeof(name));
d58598
+	STRNCPY_TERMINATED (name, ifname, sizeof(name));
d58598
 	add_rta(nlh, DCB_ATTR_IFNAME, (void *)name, strlen(name) + 1);
d58598
 	rta_parent = add_rta(nlh, DCB_ATTR_NUMTCS, NULL, 0);
d58598
 
d58598
@@ -801,17 +802,6 @@ int set_hw_app(char *ifname, appgroup_at
d58598
 	return(recv_msg(DCB_CMD_SAPP, DCB_ATTR_APP, seq));
d58598
 }
d58598
 
d58598
-int run_cmd(char *cmd, ...)
d58598
-{
d58598
-	char cbuf[128];
d58598
-	va_list args;
d58598
-
d58598
-	va_start(args, cmd);
d58598
-	vsprintf(cbuf, cmd, args);
d58598
-	va_end(args);
d58598
-	return system(cbuf);
d58598
-}
d58598
-
d58598
 int set_hw_all(char *ifname)
d58598
 {
d58598
 	struct nlmsghdr *nlh;
d58598
diff -upr a/lldp_evb22.c b/lldp_evb22.c
d58598
--- a/lldp_evb22.c	2021-06-09 10:58:59.218200681 -0400
d58598
+++ b/lldp_evb22.c	2020-11-03 09:08:48.060229053 -0500
d58598
@@ -37,14 +37,12 @@
d58598
 #include "messages.h"
d58598
 #include "config.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 struct evb22_data *evb22_data(char *ifname, enum agent_type type)
d58598
 {
d58598
 	struct evb22_user_data *ud;
d58598
 	struct evb22_data *ed = NULL;
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB22);
d58598
 	if (ud) {
d58598
 		LIST_FOREACH(ed, &ud->head, entry) {
d58598
 			if (!strncmp(ifname, ed->ifname, IFNAMSIZ) &&
d58598
@@ -450,10 +448,10 @@ static void evb22_ifup(char *ifname, str
d58598
 			   __func__, ifname, agent->type, sizeof *ed);
d58598
 		return;
d58598
 	}
d58598
-	strncpy(ed->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(ed->ifname, ifname, IFNAMSIZ);
d58598
 	ed->agenttype = agent->type;
d58598
 	evb22_init_tlv(ed, agent);
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB22);
d58598
 	LIST_INSERT_HEAD(&ud->head, ed, entry);
d58598
 	LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type);
d58598
 }
d58598
diff -upr a/lldp_evb22_cmds.c b/lldp_evb22_cmds.c
d58598
--- a/lldp_evb22_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_evb22_cmds.c	2020-09-23 08:50:52.653813954 -0400
d58598
@@ -225,7 +225,7 @@ int evb22_conf_enabletx(char *ifname, en
d58598
 				TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE));
d58598
 }
d58598
 
d58598
-static int evb22_cmdok(struct cmd *cmd, cmd_status expected)
d58598
+static int evb22_cmdok(struct cmd *cmd, int expected)
d58598
 {
d58598
 	if (cmd->cmd != expected)
d58598
 		return cmd_invalid;
d58598
diff -upr a/lldp_evb.c b/lldp_evb.c
d58598
--- a/lldp_evb.c	2021-06-09 10:58:59.217200668 -0400
d58598
+++ b/lldp_evb.c	2021-04-05 12:02:17.318590504 -0400
d58598
@@ -36,14 +36,12 @@
d58598
 #include "messages.h"
d58598
 #include "config.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 struct evb_data *evb_data(char *ifname, enum agent_type type)
d58598
 {
d58598
 	struct evb_user_data *ud;
d58598
 	struct evb_data *ed = NULL;
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB);
d58598
 	if (ud) {
d58598
 		LIST_FOREACH(ed, &ud->head, entry) {
d58598
 			if (!strncmp(ifname, ed->ifname, IFNAMSIZ) &&
d58598
@@ -342,12 +340,12 @@ static void evb_ifup(char *ifname, struc
d58598
 			   __func__, ifname, agent->type, sizeof(*ed));
d58598
 		return;
d58598
 	}
d58598
-	strncpy(ed->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(ed->ifname, ifname, IFNAMSIZ);
d58598
 	ed->agenttype = agent->type;
d58598
 
d58598
 	evb_init_tlv(ed, agent);
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB);
d58598
 	LIST_INSERT_HEAD(&ud->head, ed, entry);
d58598
 	LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type);
d58598
 }
d58598
diff -upr a/lldp_evb_cmds.c b/lldp_evb_cmds.c
d58598
--- a/lldp_evb_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_evb_cmds.c	2020-09-23 08:50:52.653813954 -0400
d58598
@@ -163,7 +163,7 @@ int evb_conf_enabletx(char *ifname, enum
d58598
 	return is_tlv_txenabled(ifname, type, TLVID_8021Qbg(LLDP_EVB_SUBTYPE));
d58598
 }
d58598
 
d58598
-static int evb_cmdok(struct cmd *cmd, cmd_status expected)
d58598
+static int evb_cmdok(struct cmd *cmd, int expected)
d58598
 {
d58598
 	if (cmd->cmd != expected)
d58598
 		return cmd_invalid;
d58598
diff -upr a/lldp_mand.c b/lldp_mand.c
d58598
--- a/lldp_mand.c	2021-06-09 10:58:59.211200590 -0400
d58598
+++ b/lldp_mand.c	2020-11-03 09:08:48.061229070 -0500
d58598
@@ -42,8 +42,6 @@
d58598
 #include "lldp/l2_packet.h"
d58598
 #include "lldp_tlv.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 static const struct lldp_mod_ops mand_ops = {
d58598
 	.lldp_mod_register 	= mand_register,
d58598
 	.lldp_mod_unregister 	= mand_unregister,
d58598
@@ -59,7 +57,7 @@ struct mand_data *mand_data(const char *
d58598
 	struct mand_user_data *mud;
d58598
 	struct mand_data *md = NULL;
d58598
 
d58598
-	mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND);
d58598
+	mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MAND);
d58598
 	if (mud) {
d58598
 		LIST_FOREACH(md, &mud->head, entry) {
d58598
 			if (!strncmp(ifname, md->ifname, IFNAMSIZ) &&
d58598
@@ -100,7 +98,7 @@ static int mand_bld_end_tlv(struct mand_
d58598
 static int mand_bld_mac_chassis(struct mand_data *md,
d58598
 				struct tlv_info_chassis *chassis)
d58598
 {
d58598
-	get_mac(md->ifname, chassis->id.mac);
d58598
+	get_mac(md->ifname, chassis->id.mac, false);
d58598
 	if (is_valid_mac(chassis->id.mac))
d58598
 		chassis->sub = CHASSIS_ID_MAC_ADDRESS;
d58598
 	return sizeof(chassis->id.mac) + sizeof(chassis->sub);
d58598
@@ -112,11 +110,13 @@ static int mand_bld_ip_chassis(struct ma
d58598
 {
d58598
 	unsigned int len;
d58598
 
d58598
-	if (!get_ipaddr(md->ifname, &chassis->id.na.ip.v4)) {
d58598
+	void *v4_ptr = &chassis->id.na.ip.v4;
d58598
+	void *v6_ptr = &chassis->id.na.ip.v6;
d58598
+	if (!get_ipaddr(md->ifname, v4_ptr)) {
d58598
 		chassis->sub = CHASSIS_ID_NETWORK_ADDRESS;
d58598
 		chassis->id.na.type = MANADDR_IPV4;
d58598
 		len = sizeof(chassis->id.na.ip.v4);
d58598
-	} else  if (!get_ipaddr6(md->ifname, &chassis->id.na.ip.v6)) {
d58598
+	} else  if (!get_ipaddr6(md->ifname, v6_ptr)) {
d58598
 		chassis->sub = CHASSIS_ID_NETWORK_ADDRESS;
d58598
 		chassis->id.na.type = MANADDR_IPV6;
d58598
 		len = sizeof(chassis->id.na.ip.v6);
d58598
@@ -217,6 +217,7 @@ static int mand_bld_chassis_tlv(struct m
d58598
 			if (length > 0)
d58598
 				break;
d58598
 			/* Fall through on IP error */
d58598
+			/* FALLTHROUGH */ 
d58598
 		case CHASSIS_ID_MAC_ADDRESS:
d58598
 		default:
d58598
 			length = mand_bld_mac_chassis(md, &chassis);
d58598
@@ -234,6 +235,7 @@ static int mand_bld_chassis_tlv(struct m
d58598
 			if (length > 0)
d58598
 				break;
d58598
 			/* Fall through on IP error */
d58598
+			/* FALLTHROUGH */
d58598
 		case LLDP_MED_DEVTYPE_NETWORK_CONNECTIVITY:
d58598
 		default:
d58598
 			length =  mand_bld_ifname_chassis(md, &chassis);
d58598
@@ -361,16 +363,18 @@ static int mand_bld_portid_tlv(struct ma
d58598
 	switch (subtype) {
d58598
 	default:
d58598
 	case PORT_ID_MAC_ADDRESS:
d58598
-		get_mac(md->ifname, portid.id.mac);
d58598
+		get_mac(md->ifname, portid.id.mac, true);
d58598
 		if (is_valid_mac(portid.id.mac)) {
d58598
 			portid.sub = PORT_ID_MAC_ADDRESS;
d58598
 			length = sizeof(portid.id.mac) +
d58598
 				 sizeof(portid.sub);
d58598
 			break;
d58598
 		}
d58598
-	case PORT_ID_NETWORK_ADDRESS:
d58598
+		/* FALLTHROUGH */
d58598
+	case PORT_ID_NETWORK_ADDRESS: {
d58598
 		/* uses ipv4 first */
d58598
-		if (!get_ipaddr(md->ifname, &portid.id.na.ip.v4)) {
d58598
+		void *v4_ptr = &portid.id.na.ip.v4;
d58598
+		if (!get_ipaddr(md->ifname, v4_ptr)) {
d58598
 			portid.sub = PORT_ID_NETWORK_ADDRESS;
d58598
 			portid.id.na.type = MANADDR_IPV4;
d58598
 			length = sizeof(portid.id.na.type) +
d58598
@@ -379,7 +383,8 @@ static int mand_bld_portid_tlv(struct ma
d58598
 			break;
d58598
 		}
d58598
 		/* ipv4 fails, get ipv6 */
d58598
-		if (!get_ipaddr6(md->ifname, &portid.id.na.ip.v6)) {
d58598
+		void *v6_ptr = &portid.id.na.ip.v6;
d58598
+		if (!get_ipaddr6(md->ifname, v6_ptr)) {
d58598
 			portid.sub = PORT_ID_NETWORK_ADDRESS;
d58598
 			portid.id.na.type = MANADDR_IPV6;
d58598
 			length = sizeof(portid.id.na.type) +
d58598
@@ -387,6 +392,8 @@ static int mand_bld_portid_tlv(struct ma
d58598
 				 sizeof(portid.sub);
d58598
 			break;
d58598
 		}
d58598
+  }
d58598
+		/* FALLTHROUGH */
d58598
 	case PORT_ID_INTERFACE_NAME:
d58598
 		portid.sub = PORT_ID_INTERFACE_NAME;
d58598
 		strncpy((char *)portid.id.ifname, md->ifname, IFNAMSIZ);
d58598
@@ -508,9 +515,11 @@ struct packed_tlv *mand_gettlv(struct po
d58598
 	}
d58598
 
d58598
 	err = mand_bld_tlv(md, agent);
d58598
-	if (err)
d58598
+	if (err) {
d58598
 		LLDPAD_DBG("%s:%s: building mandotory TLV error.\n",
d58598
 			   __func__, port->ifname);
d58598
+		goto out_err;
d58598
+	}
d58598
 
d58598
 	size = TLVSIZE(md->chassis)
d58598
 		+ TLVSIZE(md->portid)
d58598
@@ -532,7 +541,7 @@ struct packed_tlv *mand_gettlv(struct po
d58598
 	PACK_TLV_AFTER(md->ttl, ptlv, size, out_free);
d58598
 	return ptlv;
d58598
 out_free:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 out_err:
d58598
 	LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname);
d58598
 	return NULL;
d58598
@@ -596,10 +605,10 @@ void mand_ifup(char *ifname, struct lldp
d58598
 			return;
d58598
 		}
d58598
 		memset(md, 0, sizeof(struct mand_data));
d58598
-		strncpy(md->ifname, ifname, IFNAMSIZ);
d58598
+		STRNCPY_TERMINATED(md->ifname, ifname, IFNAMSIZ);
d58598
 		md->agenttype = agent->type;
d58598
 
d58598
-		mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND);
d58598
+		mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MAND);
d58598
 		LIST_INSERT_HEAD(&mud->head, md, entry);
d58598
 	}
d58598
 
d58598
@@ -627,7 +636,7 @@ struct lldp_module *mand_register(void)
d58598
 		LLDPAD_ERR("failed to malloc LLDP Mandatory module data\n");
d58598
 		goto out_err;
d58598
 	}
d58598
-	mud = malloc(sizeof(struct mand_user_data));
d58598
+    mud = malloc(sizeof(struct mand_user_data));
d58598
 	if (!mud) {
d58598
 		free(mod);
d58598
 		LLDPAD_ERR("failed to malloc LLDP Mandatory module user data\n");
d58598
@@ -635,8 +644,8 @@ struct lldp_module *mand_register(void)
d58598
 	}
d58598
 	LIST_INIT(&mud->head);
d58598
  	mod->id = LLDP_MOD_MAND;
d58598
+    mod->data = mud;
d58598
 	mod->ops = &mand_ops;
d58598
-	mod->data = mud;
d58598
 	LLDPAD_INFO("%s:done\n", __func__);
d58598
 	return mod;
d58598
 out_err:
d58598
diff -upr a/lldp_mand_cmds.c b/lldp_mand_cmds.c
d58598
--- a/lldp_mand_cmds.c	2021-06-09 10:58:59.211200590 -0400
d58598
+++ b/lldp_mand_cmds.c	2020-10-23 14:12:58.975289310 -0400
d58598
@@ -44,6 +44,9 @@
d58598
 #include "lldp/states.h"
d58598
 #include "lldp_util.h"
d58598
 #include "messages.h"
d58598
+#include "lldp_8021qaz.h"
d58598
+
d58598
+extern bool read_only_8021qaz;
d58598
 
d58598
 static int get_arg_adminstatus(struct cmd *, char *, char *, char *, int);
d58598
 static int set_arg_adminstatus(struct cmd *, char *, char *, char *, int);
d58598
@@ -463,7 +466,7 @@ int handle_get_args(struct cmd *cmd, UNU
d58598
 	nbuf = obuf;
d58598
 	nbuf_len = obuf_len;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops->get_arg_handler)
d58598
 			continue;
d58598
 		if (!(ah = np->ops->get_arg_handler()))
d58598
@@ -493,7 +496,7 @@ int handle_get_arg(struct cmd *cmd, char
d58598
 	struct arg_handlers *ah;
d58598
 	int rval, status = cmd_not_applicable;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops->get_arg_handler)
d58598
 			continue;
d58598
 		if (!(ah = np->ops->get_arg_handler()))
d58598
@@ -590,11 +593,14 @@ int handle_test_arg(struct cmd *cmd, cha
d58598
 	struct arg_handlers *ah;
d58598
 	int rval, status = cmd_not_applicable;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops->get_arg_handler)
d58598
 			continue;
d58598
 		if (!(ah = np->ops->get_arg_handler()))
d58598
 			continue;
d58598
+		/* 8021QAZ set operations not allowed in read-only mode */
d58598
+		if (np->id == LLDP_MOD_8021QAZ && read_only_8021qaz)
d58598
+			return cmd_no_access;
d58598
 		while (ah->arg) {
d58598
 			if (!strcasecmp(ah->arg, arg) && ah->handle_test) {
d58598
 				rval = ah->handle_test(cmd, ah->arg, argvalue,
d58598
@@ -620,11 +626,14 @@ int handle_set_arg(struct cmd *cmd, char
d58598
 	struct arg_handlers *ah;
d58598
 	int rval, status = cmd_not_applicable;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (!np->ops->get_arg_handler)
d58598
 			continue;
d58598
 		if (!(ah = np->ops->get_arg_handler()))
d58598
 			continue;
d58598
+		/* 8021QAZ set operations not allowed in read-only mode */
d58598
+		if (np->id == LLDP_MOD_8021QAZ && read_only_8021qaz)
d58598
+			return cmd_no_access;
d58598
 		while (ah->arg) {
d58598
 			if (!strcasecmp(ah->arg, arg) && ah->handle_set) {
d58598
 				rval = ah->handle_set(cmd, ah->arg, argvalue,
d58598
diff -upr a/lldp_med.c b/lldp_med.c
d58598
--- a/lldp_med.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_med.c	2020-11-03 09:08:48.061229070 -0500
d58598
@@ -40,8 +40,6 @@
d58598
 #include "lldp_mand_clif.h"
d58598
 #include "lldp_med_cmds.h"
d58598
 
d58598
-extern struct lldp_head lldp_head;
d58598
-
d58598
 struct tlv_info_medcaps {
d58598
 	u8 oui[OUI_SIZE];
d58598
 	u8 subtype;
d58598
@@ -95,7 +93,7 @@ static struct med_data *med_data(const c
d58598
 	struct med_user_data *mud;
d58598
 	struct med_data *md = NULL;
d58598
 
d58598
-	mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED);
d58598
+	mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MED);
d58598
 	if (mud) {
d58598
 		LIST_FOREACH(md, &mud->head, entry) {
d58598
 			if (!strncmp(ifname, md->ifname, IFNAMSIZ) &&
d58598
@@ -905,7 +903,7 @@ void med_ifup(char *ifname, struct lldp_
d58598
 		goto out_err;
d58598
 	}
d58598
 	memset(md, 0, sizeof(struct med_data));
d58598
-	strncpy(md->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(md->ifname, ifname, IFNAMSIZ);
d58598
 	md->agenttype = agent->type;
d58598
 
d58598
 	if (med_bld_tlv(md, agent)) {
d58598
@@ -914,7 +912,7 @@ void med_ifup(char *ifname, struct lldp_
d58598
 		free(md);
d58598
 		goto out_err;
d58598
 	}
d58598
-	mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED);
d58598
+	mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MED);
d58598
 	LIST_INSERT_HEAD(&mud->head, md, entry);
d58598
 	LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
d58598
 	return;
d58598
diff -upr a/lldp_med_cmds.c b/lldp_med_cmds.c
d58598
--- a/lldp_med_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_med_cmds.c	2020-09-23 08:50:52.654813972 -0400
d58598
@@ -303,6 +303,7 @@ static int _set_arg_med_devtype(struct c
d58598
 	case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_III:
d58598
 	case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_II:
d58598
 		tlv_enabletx(cmd->ifname, cmd->type, (OUI_TIA_TR41 << 8) | LLDP_MED_NETWORK_POLICY);
d58598
+		/* FALLTHROUGH */
d58598
 	case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_I:
d58598
 	case LLDP_MED_DEVTYPE_NETWORK_CONNECTIVITY:
d58598
 		tlv_enabletx(cmd->ifname, cmd->type, (OUI_TIA_TR41 << 8) | LLDP_MED_RESERVED);
d58598
diff -upr a/lldp_rtnl.c b/lldp_rtnl.c
d58598
--- a/lldp_rtnl.c	2021-06-09 10:58:59.213200616 -0400
d58598
+++ b/lldp_rtnl.c	2021-04-05 12:02:17.319590520 -0400
d58598
@@ -103,7 +103,8 @@ static void add_rtattr(struct nlmsghdr *
d58598
 
d58598
 	rta->rta_type = type;
d58598
 	rta->rta_len = len;
d58598
-	memcpy(RTA_DATA(rta), data, alen);
d58598
+	if (data)
d58598
+		memcpy(RTA_DATA(rta), data, alen);
d58598
 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
d58598
 }
d58598
 
d58598
diff -upr a/lldp_tlv.c b/lldp_tlv.c
d58598
--- a/lldp_tlv.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldp_tlv.c	2020-09-23 08:50:52.654813972 -0400
d58598
@@ -112,13 +112,13 @@ int pack_tlv_after(struct unpacked_tlv *
d58598
 		return -1;
d58598
 
d58598
 	if (ptlv->size + mtlv->size > length) {
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
 		return -1;
d58598
 	}
d58598
 
d58598
 	memcpy(&mtlv->tlv[mtlv->size], ptlv->tlv, ptlv->size);
d58598
 	mtlv->size += ptlv->size;
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 	return 0;
d58598
 }
d58598
 
d58598
@@ -158,7 +158,7 @@ struct unpacked_tlv *unpack_tlv(struct p
d58598
 	return upkd_tlv;
d58598
 }
d58598
 
d58598
-struct unpacked_tlv *free_unpkd_tlv(struct unpacked_tlv *tlv)
d58598
+void free_unpkd_tlv(struct unpacked_tlv *tlv)
d58598
 {
d58598
 	if (tlv != NULL) {
d58598
 		if (tlv->info != NULL) {
d58598
@@ -166,12 +166,10 @@ struct unpacked_tlv *free_unpkd_tlv(stru
d58598
 			tlv->info = NULL;
d58598
 		}
d58598
 		free(tlv);
d58598
-		tlv = NULL;
d58598
 	}
d58598
-	return NULL;
d58598
 }
d58598
 
d58598
-struct packed_tlv *free_pkd_tlv(struct packed_tlv *tlv)
d58598
+void free_pkd_tlv(struct packed_tlv *tlv)
d58598
 {
d58598
 	if (tlv != NULL) {
d58598
 		if (tlv->tlv != NULL) {
d58598
@@ -179,9 +177,7 @@ struct packed_tlv *free_pkd_tlv(struct p
d58598
 			tlv->tlv = NULL;
d58598
 		}
d58598
 		free(tlv);
d58598
-		tlv = NULL;
d58598
 	}
d58598
-	return NULL;
d58598
 }
d58598
 
d58598
 struct packed_tlv *create_ptlv()
d58598
diff -upr a/lldptool.c b/lldptool.c
d58598
--- a/lldptool.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldptool.c	2020-10-30 09:35:19.614361934 -0400
d58598
@@ -64,6 +64,9 @@
d58598
 #include "lldp_util.h"
d58598
 #include "lldpad_status.h"
d58598
 
d58598
+struct lldp_head lldp_cli_head;
d58598
+struct lldp_head lldp_mod_head;
d58598
+extern void close_history(void);
d58598
 static int show_raw;
d58598
 
d58598
 static const char *cli_version =
d58598
@@ -199,7 +202,7 @@ static void init_modules(void)
d58598
 		if (premod)
d58598
 			LIST_INSERT_AFTER(premod, module, lldp);
d58598
 		else
d58598
-			LIST_INSERT_HEAD(&lldp_head, module, lldp);
d58598
+			LIST_INSERT_HEAD(&lldp_mod_head, module, lldp);
d58598
 		premod = module;
d58598
 	}
d58598
 }
d58598
@@ -208,9 +211,9 @@ void deinit_modules(void)
d58598
 {
d58598
 	struct lldp_module *module;
d58598
 
d58598
-	while (lldp_head.lh_first != NULL) {
d58598
-		module = lldp_head.lh_first;
d58598
-		LIST_REMOVE(lldp_head.lh_first, lldp);
d58598
+	while (lldp_mod_head.lh_first != NULL) {
d58598
+		module = lldp_mod_head.lh_first;
d58598
+		LIST_REMOVE(lldp_mod_head.lh_first, lldp);
d58598
 		module->ops->lldp_mod_unregister(module);
d58598
 	}
d58598
 }
d58598
@@ -222,28 +225,6 @@ static void usage(void)
d58598
 		commands_usage, commands_options, commands_help);
d58598
 }
d58598
 
d58598
-/* assumes input is pointer to two hex digits */
d58598
-/* returns -1 on error */
d58598
-int hex2int(char *b)
d58598
-{
d58598
-	int i;
d58598
-	int n=0;
d58598
-	int m;
d58598
-
d58598
-	for (i=0,m=1; i<2; i++,m--) {
d58598
-		if (isxdigit(*(b+i))) {
d58598
-			if (*(b+i) <= '9')
d58598
-				n |= (*(b+i) & 0x0f) << (4*m);
d58598
-			else
d58598
-				n |= ((*(b+i) & 0x0f) + 9) << (4*m);
d58598
-		}
d58598
-		else {
d58598
-			return -1;
d58598
-		}
d58598
-	}
d58598
-	return n;
d58598
-}
d58598
-
d58598
 void print_raw_message(char *msg, int print)
d58598
 {
d58598
 	if (!print || !(print & SHOW_RAW))
d58598
@@ -368,7 +349,7 @@ cli_cmd_help(UNUSED struct clif *clif, U
d58598
 	printf("%s\n%s\n%s", commands_usage, commands_options, commands_help);
d58598
 
d58598
 	printf("\nTLV identifiers:\n");
d58598
-	LIST_FOREACH(np, &lldp_head, lldp)
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp)
d58598
 		if (np->ops->print_help)
d58598
 			np->ops->print_help();
d58598
 	return 0;
d58598
@@ -428,7 +409,7 @@ u32 lookup_tlvid(char *tlvid_str)
d58598
 	struct lldp_module *np;
d58598
 	u32 tlvid = INVALID_TLVID;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (np->ops->lookup_tlv_name) {
d58598
 			tlvid = np->ops->lookup_tlv_name(tlvid_str);
d58598
 			if (tlvid != INVALID_TLVID)
d58598
@@ -711,6 +692,7 @@ static void cli_interactive()
d58598
 		}
d58598
 		free(cmd);
d58598
 	} while (!cli_quit);
d58598
+	close_history();
d58598
 }
d58598
 
d58598
 static void cli_terminate(UNUSED int sig)
d58598
diff -upr a/lldptool_cmds.c b/lldptool_cmds.c
d58598
--- a/lldptool_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/lldptool_cmds.c	2020-10-23 14:12:58.976289329 -0400
d58598
@@ -27,6 +27,7 @@
d58598
 #include <stdio.h>
d58598
 #include <stdlib.h>
d58598
 #include <ctype.h>
d58598
+#include <sys/types.h>
d58598
 #include "clif.h"
d58598
 #include "dcb_types.h"
d58598
 #include "lldptool.h"
d58598
@@ -464,7 +465,7 @@ static void print_tlvs(struct cmd *cmd,
d58598
 			offset += 8;
d58598
 		
d58598
 		printed = 0;
d58598
-		LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+		LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 			if (np->ops->print_tlv(tlvid, tlv_len, ibuf+offset)) {
d58598
 					printed = 1;
d58598
 					break;
d58598
diff -upr a/lldp_util.c b/lldp_util.c
d58598
--- a/lldp_util.c	2021-06-09 10:58:59.215200642 -0400
d58598
+++ b/lldp_util.c	2020-09-23 08:50:52.654813972 -0400
d58598
@@ -24,6 +24,7 @@
d58598
 
d58598
 *******************************************************************************/
d58598
 
d58598
+#include <ctype.h>
d58598
 #include <stdlib.h>
d58598
 #include <stdio.h>
d58598
 #include <string.h>
d58598
@@ -122,6 +123,28 @@ int hexstr2bin(const char *hex, u8 *buf,
d58598
 	return 0;
d58598
 }
d58598
 
d58598
+/* assumes input is pointer to two hex digits */
d58598
+/* returns -1 on error */
d58598
+int hex2int(char *b)
d58598
+{
d58598
+	int i;
d58598
+	int n=0;
d58598
+	int m;
d58598
+
d58598
+	for (i=0,m=1; i<2; i++,m--) {
d58598
+		if (isxdigit(*(b+i))) {
d58598
+			if (*(b+i) <= '9')
d58598
+				n |= (*(b+i) & 0x0f) << (4*m);
d58598
+			else
d58598
+				n |= ((*(b+i) & 0x0f) + 9) << (4*m);
d58598
+		}
d58598
+		else {
d58598
+			return -1;
d58598
+		}
d58598
+	}
d58598
+	return n;
d58598
+}
d58598
+
d58598
 char *print_mac(char *mac, char *buf)
d58598
 {
d58598
 	sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
d58598
@@ -189,26 +212,6 @@ int is_bond(const char *ifname)
d58598
 }
d58598
 
d58598
 /**
d58598
- *	is_san_mac - check if address is a san mac addr
d58598
- *	@addr: san mac address
d58598
- *
d58598
- *	Returns 0 if addr is NOT san mac, 1 if it is a san mac.
d58598
- *
d58598
- *	BUG: this does not do anything to prove it's a sanmac!!!!
d58598
- *	SAN MAC is no different than LAN MAC, no way to tell!!!
d58598
- */
d58598
-int is_san_mac(u8 *addr)
d58598
-{
d58598
-	int i;
d58598
-
d58598
-	for ( i = 0; i < ETH_ALEN; i++) {
d58598
-		if ( addr[i]!= 0xff )
d58598
-			return 1;
d58598
-	}
d58598
-	return 0;
d58598
-}
d58598
-
d58598
-/**
d58598
  *	get_src_mac_from_bond - select a source MAC to use for slave
d58598
  *	@bond_port: pointer to port structure for a bond interface
d58598
  *	@ifname: interface name of the slave port
d58598
@@ -314,11 +317,24 @@ int	get_src_mac_from_bond(struct port *b
d58598
  */
d58598
 int is_valid_mac(const u8 *mac)
d58598
 {
d58598
-	if (0 == (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]))
d58598
-		return 0;
d58598
-	if (0xff == (mac[0] & mac[1] & mac[2] & mac[3] & mac[4] & mac[5]))
d58598
-		return 0;
d58598
-	return 1;
d58598
+	static const u8 zero_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
d58598
+	static const u8 ff_mac[ETH_ALEN]   = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
d58598
+	static const u8 iana_mcast[ETH_ALEN] = {0x01, 0x00, 0x5E};
d58598
+	static const u8 ipv6_mcast[ETH_ALEN] = {0x33, 0x33};
d58598
+
d58598
+        if(memcmp(mac, zero_mac, ETH_ALEN) == 0 ||
d58598
+	   memcmp(mac, ff_mac, ETH_ALEN)   == 0)
d58598
+                return 0;
d58598
+
d58598
+	/* IANA multicast and ipv6 multicast mac address
d58598
+	 * For reference check document: 
d58598
+	 * https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml
d58598
+	 */
d58598
+        if(memcmp(mac, iana_mcast, 3) == 0 ||
d58598
+           memcmp(mac, ipv6_mcast, 2) == 0)
d58598
+                return 0;
d58598
+	
d58598
+        return 1;
d58598
 }
d58598
 
d58598
 int read_int(const char *path)
d58598
@@ -350,7 +366,7 @@ int get_ifflags(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifr, 0, sizeof(ifr));
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
d58598
 			flags = ifr.ifr_flags;
d58598
 	}
d58598
@@ -386,7 +402,7 @@ int get_ifpflags(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifr, 0, sizeof(ifr));
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIFPFLAGS, &ifr) == 0)
d58598
 			flags = ifr.ifr_flags;
d58598
 	}
d58598
@@ -470,7 +486,7 @@ int is_slave(const char *ifmaster, const
d58598
 
d58598
 	memset(&ifr, 0, sizeof(ifr));
d58598
 	memset(&ifb, 0, sizeof(ifb));
d58598
-	strncpy(ifr.ifr_name, ifmaster, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(ifr.ifr_name, ifmaster, IFNAMSIZ);
d58598
 	ifr.ifr_data = (caddr_t)&ifb;
d58598
 	if (ioctl(fd, SIOCBONDINFOQUERY, &ifr))
d58598
 		goto out_done;
d58598
@@ -500,7 +516,7 @@ int get_ifidx(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifreq, 0, sizeof(ifreq));
d58598
-		strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
d58598
+		STRNCPY_TERMINATED(ifreq.ifr_name, ifname, IFNAMSIZ);
d58598
 		if (ioctl(fd, SIOCGIFINDEX, &ifreq) == 0)
d58598
 			idx = ifreq.ifr_ifindex;
d58598
 	}
d58598
@@ -572,7 +588,7 @@ int is_bridge(const char *ifname)
d58598
 						 (unsigned long) &bi, 0, 0 };
d58598
 
d58598
 			ifr.ifr_data = (char *)args;
d58598
-			strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+			STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 			if (ioctl(fd, SIOCDEVPRIVATE, &ifr) == 0)
d58598
 				rc = 1;
d58598
 		}
d58598
@@ -610,7 +626,7 @@ int is_vlan(const char *ifname)
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifv, 0, sizeof(ifv));
d58598
 		ifv.cmd = GET_VLAN_REALDEV_NAME_CMD;
d58598
-		strncpy(ifv.device1, ifname, sizeof(ifv.device1));
d58598
+		STRNCPY_TERMINATED(ifv.device1, ifname, sizeof(ifv.device1));
d58598
 		if (ioctl(fd, SIOCGIFVLAN, &ifv) == 0)
d58598
 			rc = 1;
d58598
 	}
d58598
@@ -637,7 +653,7 @@ int is_wlan(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&iwreq, 0, sizeof(iwreq));
d58598
-		strncpy(iwreq.ifr_name, ifname, sizeof(iwreq.ifr_name));
d58598
+		STRNCPY_TERMINATED(iwreq.ifr_name, ifname, sizeof(iwreq.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIWNAME, &iwreq) == 0)
d58598
 			rc = 1;
d58598
 	}
d58598
@@ -650,6 +666,8 @@ static struct nla_policy ifla_info_polic
d58598
 {
d58598
   [IFLA_INFO_KIND]       = { .type = NLA_STRING},
d58598
   [IFLA_INFO_DATA]       = { .type = NLA_NESTED },
d58598
+  [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING},
d58598
+  [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
d58598
 };
d58598
 
d58598
 int is_macvtap(const char *ifname)
d58598
@@ -754,7 +772,7 @@ int is_active(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifr, 0, sizeof(ifr));
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
d58598
 			if (ifr.ifr_flags & IFF_UP)
d58598
 				rc = 1;
d58598
@@ -775,7 +793,7 @@ int is_autoneg_supported(const char *ifn
d58598
 		memset(&cmd, 0, sizeof(cmd));
d58598
 		cmd.cmd = ETHTOOL_GSET;
d58598
 		ifr.ifr_data = &cm;;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
d58598
 			if (cmd.supported & SUPPORTED_Autoneg)
d58598
 				rc = 1;
d58598
@@ -796,7 +814,7 @@ int is_autoneg_enabled(const char *ifnam
d58598
 		memset(&cmd, 0, sizeof(cmd));
d58598
 		cmd.cmd = ETHTOOL_GSET;
d58598
 		ifr.ifr_data = &cm;;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
d58598
 			rc = cmd.autoneg;
d58598
 	}
d58598
@@ -833,7 +851,7 @@ int get_maucaps(const char *ifname)
d58598
 		memset(&cmd, 0, sizeof(cmd));
d58598
 		cmd.cmd = ETHTOOL_GSET;
d58598
 		ifr.ifr_data = &cm;;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) {
d58598
 			if (cmd.advertising & ADVERTISED_10baseT_Half)
d58598
 				caps |= MAUCAPADV_b10baseT;
d58598
@@ -872,7 +890,7 @@ int get_mautype(const char *ifname)
d58598
 		memset(&cmd, 0, sizeof(cmd));
d58598
 		cmd.cmd = ETHTOOL_GSET;
d58598
 		ifr.ifr_data = &cm;;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) {
d58598
 			/* TODO: too many dot3MauTypes,
d58598
 			 * should check duplex, speed, and port */
d58598
@@ -899,7 +917,7 @@ int get_mtu(const char *ifname)
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		memset(&ifr, 0, sizeof(ifr));
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIFMTU, &ifr) == 0)
d58598
 			rc = ifr.ifr_mtu;
d58598
 	}
d58598
@@ -921,38 +939,86 @@ int get_mfs(const char *ifname)
d58598
 	return mfs;
d58598
 }
d58598
 
d58598
-int get_mac(const char *ifname, u8 mac[])
d58598
+int get_mac(const char *ifname, u8 mac[], bool perm_mac)
d58598
 {
d58598
-	int fd;
d58598
-	int rc = EINVAL;
d58598
-	struct ifreq ifr;
d58598
+	int ret, s;
d58598
+	struct nlmsghdr *nlh;
d58598
+	struct ifinfomsg *ifinfo;
d58598
+	struct nlattr *tb[IFLA_MAX+1],
d58598
+		*tb2[IFLA_INFO_MAX+1];
d58598
 
d58598
-	memset(mac, 0, 6);
d58598
-	fd = get_ioctl_socket();
d58598
-	if (fd >= 0) {
d58598
-		ifr.ifr_addr.sa_family = AF_INET;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
-		if (!ioctl(fd, SIOCGIFHWADDR, &ifr)) {
d58598
-			memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
d58598
-			rc = 0;
d58598
-		}
d58598
+	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
d58598
+
d58598
+	if (s < 0) {
d58598
+		goto out;
d58598
 	}
d58598
-	return rc;
d58598
-}
d58598
 
d58598
-int get_macstr(const char *ifname, char *addr, size_t size)
d58598
-{
d58598
-	u8 mac[6];
d58598
-	int rc;
d58598
+	nlh = malloc(NLMSG_SIZE);
d58598
 
d58598
-	rc = get_mac(ifname, mac);
d58598
-	if (rc == 0) {
d58598
-		snprintf(addr, size, "%02x:%02x:%02x:%02x:%02x:%02x",
d58598
-			mac[0], mac[1],	mac[2],	mac[3],	mac[4],	mac[5]);
d58598
+	if (!nlh) {
d58598
+		goto out;
d58598
 	}
d58598
-	return rc;
d58598
-}
d58598
 
d58598
+	memset(nlh, 0, NLMSG_SIZE);
d58598
+
d58598
+	nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
d58598
+	nlh->nlmsg_type = RTM_GETLINK;
d58598
+	nlh->nlmsg_flags = NLM_F_REQUEST;
d58598
+
d58598
+	ifinfo = NLMSG_DATA(nlh);
d58598
+	ifinfo->ifi_family = AF_UNSPEC;
d58598
+	ifinfo->ifi_index = get_ifidx(ifname);
d58598
+
d58598
+	ret = send(s, nlh, nlh->nlmsg_len, 0);
d58598
+
d58598
+	if (ret < 0) {
d58598
+		goto out_free;
d58598
+	}
d58598
+
d58598
+	memset(nlh, 0, NLMSG_SIZE);
d58598
+
d58598
+	do {
d58598
+		ret = recv(s, (void *) nlh, NLMSG_SIZE, MSG_DONTWAIT);
d58598
+	} while ((ret < 0) && errno == EINTR);
d58598
+
d58598
+	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg),
d58598
+			(struct nlattr **)&tb, IFLA_MAX, NULL)) {
d58598
+		goto out_free;
d58598
+	}
d58598
+
d58598
+	if (tb[IFLA_ADDRESS])
d58598
+		memcpy(mac, (char*)(RTA_DATA(tb[IFLA_ADDRESS])), 6);
d58598
+
d58598
+	/* Check for the permanent mac address on bonding slaves */
d58598
+	if (perm_mac && tb[IFLA_LINKINFO]) {
d58598
+		char *kind;
d58598
+		struct nlattr *tb3;
d58598
+		int off = 0;
d58598
+
d58598
+		if (nla_parse_nested(tb2, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
d58598
+				     ifla_info_policy)) {
d58598
+			goto out_free;
d58598
+		}
d58598
+		if (!tb2[IFLA_INFO_SLAVE_KIND])
d58598
+			goto out_free;
d58598
+
d58598
+		kind = (char*)(RTA_DATA(tb2[IFLA_INFO_SLAVE_KIND]));
d58598
+		if (strcmp(kind, "bond") && !tb2[IFLA_INFO_SLAVE_DATA])
d58598
+			goto out_free;
d58598
+
d58598
+		nla_for_each_nested(tb3, tb2[IFLA_INFO_SLAVE_DATA], off) {
d58598
+			if (nla_type(tb3) == IFLA_BOND_SLAVE_PERM_HWADDR) {
d58598
+				memcpy(mac, nla_data(tb3), nla_len(tb3));
d58598
+			}
d58598
+		}
d58598
+	}
d58598
+
d58598
+out_free:
d58598
+	free(nlh);
d58598
+out:
d58598
+	close(s);
d58598
+	return 0;
d58598
+}
d58598
 
d58598
 u16 get_caps(const char *ifname)
d58598
 {
d58598
@@ -998,7 +1064,7 @@ int get_saddr(const char *ifname, struct
d58598
 	fd = get_ioctl_socket();
d58598
 	if (fd >= 0) {
d58598
 		ifr.ifr_addr.sa_family = AF_INET;
d58598
-		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
+		STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
d58598
 		if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
d58598
 			memcpy(saddr, &ifr.ifr_addr, sizeof(*saddr));
d58598
 			rc = 0;
d58598
@@ -1039,9 +1105,11 @@ int get_saddr6(const char *ifname, struc
d58598
 
d58598
 	rc = getifaddrs(&ifaddr);
d58598
 	if (rc == 0) {
d58598
+		rc = -1;
d58598
 		for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
d58598
-			if ((ifa->ifa_addr->sa_family == AF_INET6) &&
d58598
-			    (strncmp(ifa->ifa_name, ifname, IFNAMSIZ) == 0)) {
d58598
+			if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ))
d58598
+				continue;
d58598
+			if (ifa->ifa_addr && (ifa->ifa_addr->sa_family == AF_INET6)) {
d58598
 				memcpy(saddr, ifa->ifa_addr, sizeof(*saddr));
d58598
 				rc = 0;
d58598
 				break;
d58598
@@ -1092,7 +1160,7 @@ int get_addr(const char *ifname, int dom
d58598
 	else if (domain == AF_INET6)
d58598
 		return get_ipaddr6(ifname, (struct in6_addr *)buf);
d58598
 	else if (domain == AF_UNSPEC)
d58598
-		return get_mac(ifname, (u8 *)buf);
d58598
+		return get_mac(ifname, (u8 *)buf, false);
d58598
 	else
d58598
 		return -1;
d58598
 }
d58598
@@ -1227,7 +1295,7 @@ int get_arg_val_list(char *ibuf, int ile
d58598
 		}
d58598
 		hexstr2bin(ibuf+*ioff, &arglen, sizeof(arglen));
d58598
 		*ioff += 2 * (int)sizeof(arglen);
d58598
-		if (ilen - *ioff >= arglen) {
d58598
+		if (ilen - *ioff >= 0) {
d58598
 			args[i] = ibuf+*ioff;
d58598
 			*ioff += arglen;
d58598
 			*(arglens+i) = arglen;
d58598
@@ -1237,7 +1305,7 @@ int get_arg_val_list(char *ibuf, int ile
d58598
 					   sizeof(argvalue_len));
d58598
 				argvalue_len = ntohs(argvalue_len);
d58598
 				*ioff += 2*sizeof(argvalue_len);
d58598
-				if (ilen - *ioff >= argvalue_len) {
d58598
+				if (ilen - *ioff >= 0) {
d58598
 					argvals[i] = ibuf+*ioff;
d58598
 					*ioff += argvalue_len;
d58598
 					*(argvallens+i) = argvalue_len;
d58598
diff -upr a/log.c b/log.c
d58598
--- a/log.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/log.c	2020-09-23 08:50:52.655813990 -0400
d58598
@@ -65,4 +65,5 @@ void log_message(int level, const char *
d58598
 		bypass_time = strchr(format, '\n') == 0;
d58598
 	}
d58598
 	va_end(va);
d58598
+	va_end(vb);
d58598
 }
d58598
diff -upr a/Makefile.am b/Makefile.am
d58598
--- a/Makefile.am	2021-06-09 10:58:59.212200603 -0400
d58598
+++ b/Makefile.am	2021-04-05 12:02:17.315590455 -0400
d58598
@@ -1,6 +1,9 @@
d58598
 # target programs to be installed in ${sbindir}
d58598
 sbin_PROGRAMS = lldpad dcbtool lldptool vdptool
d58598
 
d58598
+check_PROGRAMS = lldp_clif_test
d58598
+TESTS = $(check_PROGRAMS)
d58598
+
d58598
 # package nltest and vdptest, but do not install it anywhere
d58598
 if BUILD_DEBUG
d58598
 noinst_PROGRAMS = nltest vdptest qbg22sim
d58598
@@ -16,7 +19,7 @@ ACLOCAL_AMFLAGS = -I m4
d58598
 parse_cli.o: CFLAGS+=-U_FORTIFY_SOURCE -Wno-error
d58598
 
d58598
 ## system requires a shared libconfig
d58598
-AM_CFLAGS = -Wall -Werror -Wextra -Wformat=2 $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS)
d58598
+AM_CFLAGS = $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS)
d58598
 AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) -lrt
d58598
 
d58598
 ## header files to be installed, for programs using the client interface to lldpad 
d58598
@@ -86,9 +89,11 @@ vdptool_LDADD = liblldp_clif.la
d58598
 vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS)
d58598
 
d58598
 dcbtool_SOURCES = dcbtool.c dcbtool_cmds.c parse_cli.l \
d58598
-weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS)
d58598
+	weak_readline.c lldp_rtnl.c lldp_util.c \
d58598
+	$(lldpad_include_HEADERS) $(noinst_HEADERS)
d58598
+
d58598
 dcbtool_LDADD = liblldp_clif.la
d58598
-dcbtool_LDFLAGS = -ldl -llldp_clif
d58598
+dcbtool_LDFLAGS = -ldl -llldp_clif $(LIBNL_LIBS)
d58598
 
d58598
 lldptool_SOURCES = lldptool.c lldptool_cmds.c lldp_rtnl.c \
d58598
 		   lldp_mand_clif.c lldp_basman_clif.c lldp_med_clif.c \
d58598
@@ -140,3 +145,18 @@ bashcompletiondir = $(sysconfdir)/bash_c
d58598
 dist_bashcompletion_DATA = contrib/bash_completion/lldpad contrib/bash_completion/lldptool
d58598
 
d58598
 AM_DISTCHECK_CONFIGURE_FLAGS = --enable-debug
d58598
+
d58598
+lldp_clif_test_SOURCES = test/lldp_clif_test.c lldp_basman_clif.c lldp_util.c \
d58598
+	lldp_rtnl.c
d58598
+lldp_clif_test_LDFLAGS = -lrt $(LIBNL_LIBS)
d58598
+
d58598
+RPMBUILD_TOP = $(abs_top_builddir)/rpm/rpmbuild
d58598
+RPMBUILD_OPT ?= --without check
d58598
+
d58598
+# Build user-space RPMs
d58598
+rpm: dist $(srcdir)/lldpad.spec
d58598
+	${MKDIR_P} ${RPMBUILD_TOP}/SOURCES
d58598
+	cp ${DIST_ARCHIVES} ${RPMBUILD_TOP}/SOURCES
d58598
+	rpmbuild ${RPMBUILD_OPT} \
d58598
+                 -D "_topdir ${RPMBUILD_TOP}" \
d58598
+                 -ba $(srcdir)/lldpad.spec
d58598
diff -upr a/parse_cli.l b/parse_cli.l
d58598
--- a/parse_cli.l	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/parse_cli.l	2020-09-23 08:50:52.655813990 -0400
d58598
@@ -494,7 +494,8 @@ gp	{ if (!cmd) {
d58598
 					yyless(0);
d58598
 					}
d58598
 
d58598
-<getup2tc>[0-7]			{ up2tc_a[up2tc_idx++] = atoi(yytext);
d58598
+<getup2tc>[0-7]			{ up2tc_a[up2tc_idx] = atoi(yytext);
d58598
+				up2tc_idx++;
d58598
 				if (up2tc_idx == 8) {
d58598
 					BEGIN(getpgargs);
d58598
 				}
d58598
diff -upr a/qbg/ecp22.c b/qbg/ecp22.c
d58598
--- a/qbg/ecp22.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/qbg/ecp22.c	2020-10-23 14:12:58.976289329 -0400
d58598
@@ -119,7 +119,8 @@ static void ecp22_append(u8 *buffer, u32
d58598
  */
d58598
 void ecp22_putnode(struct ecp22_freelist *list, struct ecp22_payload_node *elm)
d58598
 {
d58598
-	elm->ptlv = free_pkd_tlv(elm->ptlv);
d58598
+	free_pkd_tlv(elm->ptlv);
d58598
+	elm->ptlv = NULL;
d58598
 	if (list->freecnt > ecp22_maxpayload)
d58598
 		free(elm);
d58598
 	else {
d58598
@@ -154,6 +155,7 @@ static bool ecp22_build_ecpdu(struct ecp
d58598
 	memset(ecp->tx.frame, 0, sizeof ecp->tx.frame);
d58598
 	ecp22_append(ecp->tx.frame, &fb_offset, (void *)&eth, sizeof eth);
d58598
 
d58598
+	memset(&ecph, 0, sizeof(struct ecp22_hdr));
d58598
 	ecp22_hdr_set_version(&ecph, 1);
d58598
 	ecp22_hdr_set_op(&ecph, ECP22_REQUEST);
d58598
 	ecp22_hdr_set_subtype(&ecph, ECP22_VDP);
d58598
@@ -749,7 +751,7 @@ static struct ecp22 *ecp22_create(char *
d58598
 			   ifname);
d58598
 		return NULL;
d58598
 	}
d58598
-	strncpy(ecp->ifname, ifname, sizeof ecp->ifname);
d58598
+	STRNCPY_TERMINATED(ecp->ifname, ifname, sizeof ecp->ifname);
d58598
 	ecp->l2 = l2_packet_init(ecp->ifname, 0, ETH_P_ECP22,
d58598
 				 ecp22_rx_receiveframe, ecp, 1);
d58598
 
d58598
@@ -774,7 +776,7 @@ void ecp22_start(char *ifname)
d58598
 	struct ecp22 *ecp;
d58598
 
d58598
 	LLDPAD_DBG("%s:%s start ecp\n", __func__, ifname);
d58598
-	eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22);
d58598
+	eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22);
d58598
 	if (!eud) {
d58598
 		LLDPAD_DBG("%s:%s no ECP module\n", __func__, ifname);
d58598
 		return;
d58598
@@ -782,6 +784,10 @@ void ecp22_start(char *ifname)
d58598
 	ecp = find_ecpdata(ifname, eud);
d58598
 	if (!ecp)
d58598
 		ecp = ecp22_create(ifname, eud);
d58598
+	if (!ecp) {
d58598
+		LLDPAD_DBG("%s:%s failed creating ECP22 instance\n", __func__, ifname);
d58598
+		return;
d58598
+	}
d58598
 	ecp->max_retries = ECP22_MAX_RETRIES_DEFAULT;
d58598
 	ecp->max_rte = ECP22_ACK_TIMER_DEFAULT;
d58598
 	LIST_INIT(&ecp->inuse.head);
d58598
@@ -803,7 +809,7 @@ static void ecp22_removelist(ecp22_list
d58598
 
d58598
 	while ((np = LIST_FIRST(ptr))) {
d58598
 		LIST_REMOVE(np, node);
d58598
-		np->ptlv = free_pkd_tlv(np->ptlv);
d58598
+		free_pkd_tlv(np->ptlv);
d58598
 		free(np);
d58598
 	}
d58598
 }
d58598
@@ -816,6 +822,7 @@ static void ecp22_remove(struct ecp22 *e
d58598
 	ecp22_removelist(&ecp->isfree.head);
d58598
 	ecp->isfree.freecnt = 0;
d58598
 	LIST_REMOVE(ecp, node);
d58598
+	l2_packet_deinit(ecp->l2);
d58598
 	free(ecp);
d58598
 }
d58598
 
d58598
@@ -832,7 +839,7 @@ void ecp22_stop(char *ifname)
d58598
 	struct ecp22 *ecp;
d58598
 
d58598
 	LLDPAD_DBG("%s:%s stop ecp\n", __func__, ifname);
d58598
-	eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22);
d58598
+	eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22);
d58598
 	ecp = find_ecpdata(ifname, eud);
d58598
 	if (ecp)
d58598
 		ecp22_remove(ecp);
d58598
@@ -847,7 +854,7 @@ static int ecp22_data_from_evb(char *ifn
d58598
 	struct ecp22_user_data *eud;
d58598
 	struct ecp22 *ecp;
d58598
 
d58598
-	eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22);
d58598
+	eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22);
d58598
 	ecp = find_ecpdata(ifname, eud);
d58598
 	if (ecp) {
d58598
 		ecp->max_rte = ptr->max_rte;
d58598
@@ -925,7 +932,7 @@ static int ecp22_req2send(char *ifname,
d58598
 
d58598
 	LLDPAD_DBG("%s:%s subtype:%d\n", __func__, ifname, subtype);
d58598
 
d58598
-	eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22);
d58598
+	eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22);
d58598
 	ecp = find_ecpdata(ifname, eud);
d58598
 	if (!ecp) {
d58598
 		rc = -ENODEV;
d58598
diff -upr a/qbg/ecp.c b/qbg/ecp.c
d58598
--- a/qbg/ecp.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/qbg/ecp.c	2020-09-23 08:50:52.656814007 -0400
d58598
@@ -299,7 +299,7 @@ static bool ecp_build_ECPDU(struct vdp_d
d58598
 
d58598
 		rc = ecp_append(vd->ecp.tx.frame, &fb_offset, ptlv->tlv,
d58598
 				ptlv->size);
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
 		if (rc)
d58598
 			p->seqnr = vd->ecp.lastSequence;
d58598
 		else
d58598
@@ -682,7 +682,7 @@ static void ecp_rx_ReceiveFrame(void *ct
d58598
 	}
d58598
 
d58598
 	if (hdr->h_proto != example_hdr.h_proto) {
d58598
-		LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype",
d58598
+		LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype\n",
d58598
 			    __func__, vd->ecp.ifname, htons(hdr->h_proto));
d58598
 		frame_error++;
d58598
 		return;
d58598
@@ -795,7 +795,7 @@ int ecp_init(char *ifname)
d58598
 			   __func__, ifname);
d58598
 		return -1;
d58598
 	}
d58598
-	strncpy(vd->ecp.ifname, ifname, sizeof vd->ecp.ifname);
d58598
+	STRNCPY_TERMINATED(vd->ecp.ifname, ifname, sizeof vd->ecp.ifname);
d58598
 	ecp_rx_change_state(vd, ECP_RX_IDLE);
d58598
 	ecp_rx_run_sm(vd);
d58598
 	ecp_somethingChangedLocal(vd, true);
d58598
@@ -969,7 +969,7 @@ static void ecp_rx_ProcessFrame(struct v
d58598
 		if ((tlv->type != TYPE_0) && !tlv_stored) {
d58598
 			LLDPAD_DBG("%s:%s TLV (%u) was not stored (%p)\n",
d58598
 				   __func__, vd->ecp.ifname, tlv->type, tlv);
d58598
-			tlv = free_unpkd_tlv(tlv);
d58598
+			free_unpkd_tlv(tlv);
d58598
 			vd->ecp.stats.statsTLVsUnrecognizedTotal++;
d58598
 		}
d58598
 		tlv = NULL;
d58598
diff -upr a/qbg/vdp22.c b/qbg/vdp22.c
d58598
--- a/qbg/vdp22.c	2021-06-09 10:58:59.210200578 -0400
d58598
+++ b/qbg/vdp22.c	2020-10-23 14:12:58.977289347 -0400
d58598
@@ -455,10 +455,10 @@ static void copy_filter(unsigned char fi
d58598
 		fp->grpid = from->gpid;
d58598
 		if (fif == VDP22_FFMT_GROUPVID)
d58598
 			goto vid;
d58598
-		/* Fall through intended */
d58598
+		/* FALLTHROUGH */
d58598
 	case VDP22_FFMT_MACVID:
d58598
 		memcpy(fp->mac, from->mac, sizeof(fp->mac));
d58598
-		/* Fall through intended */
d58598
+		/* FALLTHROUGH */
d58598
 	case VDP22_FFMT_VID:
d58598
 vid:
d58598
 		fp->vlan = vdp22_set_vlanid(from->vlan)
d58598
@@ -694,7 +694,7 @@ static struct vdp22 *vdp22_findif(const
d58598
 	struct vdp22 *vdp = 0;
d58598
 
d58598
 	if (!ud) {
d58598
-		ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22);
d58598
+		ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22);
d58598
 		if (!ud)
d58598
 			LLDPAD_DBG("%s:%s no VDP22 module\n", __func__,
d58598
 				   ifname);
d58598
@@ -794,7 +794,7 @@ void vdp22_stop(char *ifname)
d58598
 	struct vsi22 *vsi;
d58598
 
d58598
 	LLDPAD_DBG("%s:%s stop vdp\n", __func__, ifname);
d58598
-	vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22);
d58598
+	vud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22);
d58598
 	if (!vud) {
d58598
 		LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname);
d58598
 		return;
d58598
@@ -834,7 +834,7 @@ static struct vdp22 *vdp22_create(const
d58598
 			   ifname);
d58598
 		return NULL;
d58598
 	}
d58598
-	strncpy(vdp->ifname, ifname, sizeof vdp->ifname);
d58598
+	STRNCPY_TERMINATED(vdp->ifname, ifname, sizeof vdp->ifname);
d58598
 	vdp->myrole = role;
d58598
 	LIST_INIT(&vdp->vsi22_que);
d58598
 	LIST_INSERT_HEAD(&eud->head, vdp, node);
d58598
@@ -874,7 +874,7 @@ void vdp22_start(const char *ifname, int
d58598
 	struct vsi22 *vsi;
d58598
 
d58598
 	LLDPAD_DBG("%s:%s start vdp\n", __func__, ifname);
d58598
-	vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22);
d58598
+	vud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22);
d58598
 	if (!vud) {
d58598
 		LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname);
d58598
 		return;
d58598
diff -upr a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c
d58598
--- a/qbg/vdp22_cmds.c	2021-06-09 10:58:59.201200461 -0400
d58598
+++ b/qbg/vdp22_cmds.c	2020-10-23 14:12:58.977289347 -0400
d58598
@@ -57,7 +57,7 @@ static struct lldp_module *get_my_module
d58598
 {
d58598
 	struct lldp_module *np = NULL;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp)
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp)
d58598
 		if (thisid == np->id)
d58598
 			break;
d58598
 	return np;
d58598
@@ -296,7 +296,7 @@ int vdp22_sendevent(struct vdpnl_vsi *p)
d58598
 	return 0;
d58598
 }
d58598
 
d58598
-static int vdp22_cmdok(struct cmd *cmd, cmd_status expected)
d58598
+static int vdp22_cmdok(struct cmd *cmd, int expected)
d58598
 {
d58598
 	if (cmd->cmd != expected)
d58598
 		return cmd_invalid;
d58598
@@ -473,6 +473,7 @@ static bool vdp22_partial_vsi_equal(stru
d58598
 			if (memcmp(p1->mgrid, p2->mgrid,
d58598
 				   sizeof(p2->mgrid)))
d58598
 				return false;
d58598
+			/* FALLTHROUGH */
d58598
 		case VSI_TYPEID_ARG:
d58598
 			if (p1->type_id != p2->type_id)
d58598
 				return false;
d58598
@@ -576,7 +577,7 @@ static int get_arg_vsi(struct cmd *cmd,
d58598
 	memset(&vsi, 0, sizeof(vsi));
d58598
 	memset(vsi_str, 0, sizeof(vsi_str));
d58598
 	vsi.request = cmd->tlvid;
d58598
-	strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname) - 1);
d58598
+	strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname));
d58598
 	good_cmd = cmd_failed;
d58598
 	if ((cmd->ops & op_config) && (cmd->ops & op_arg)) {
d58598
 		memset(&mac, 0, sizeof(mac));
d58598
diff -upr a/qbg/vdp22sm.c b/qbg/vdp22sm.c
d58598
--- a/qbg/vdp22sm.c	2021-06-09 10:58:59.210200578 -0400
d58598
+++ b/qbg/vdp22sm.c	2020-09-23 08:50:52.657814025 -0400
d58598
@@ -1521,7 +1521,7 @@ static void vdp22br_process(struct vsi22
d58598
 	case VDP22_RESP_DEASSOC:
d58598
 		if (error > VDP22_STATUS_MASK)
d58598
 			p->status = VDP22_HARDBIT;
d58598
-		/* Fall through intended */
d58598
+		/* FALLTHROUGH */
d58598
 	case VDP22_RESP_SUCCESS:
d58598
 rest:
d58598
 		p->status |= VDP22_ACKBIT | make_status(error);
d58598
@@ -1768,7 +1768,7 @@ static void vdp22br_run(struct vsi22 *p)
d58598
 			break;
d58598
 		case VDP22_BR_END:
d58598
 			vdp22br_end(p);
d58598
-			break;
d58598
+			return;
d58598
 		}
d58598
 	} while (vdp22br_move_state(p) == true);
d58598
 }
d58598
diff -upr a/qbg/vdp.c b/qbg/vdp.c
d58598
--- a/qbg/vdp.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/qbg/vdp.c	2020-10-23 14:12:58.977289347 -0400
d58598
@@ -188,7 +188,7 @@ struct vdp_data *vdp_data(char *ifname)
d58598
 	struct vdp_user_data *ud;
d58598
 	struct vdp_data *vd = NULL;
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP02);
d58598
 	if (ud) {
d58598
 		LIST_FOREACH(vd, &ud->head, entry) {
d58598
 			if (!strncmp(ifname, vd->ifname, IFNAMSIZ))
d58598
@@ -879,7 +879,7 @@ static bool vdp_vsi_set_bridge_state(str
d58598
 {
d58598
 	switch(profile->state) {
d58598
 	case VSI_UNASSOCIATED:
d58598
-		if ((profile->mode == VDP_MODE_DEASSOCIATE)) /* || (INACTIVE)) */ {
d58598
+		if (profile->mode == VDP_MODE_DEASSOCIATE) {
d58598
 			vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING);
d58598
 			return true;
d58598
 		} else if (profile->mode == VDP_MODE_ASSOCIATE) {
d58598
@@ -1198,9 +1198,9 @@ int vdp_indicate(struct vdp_data *vd, st
d58598
 			/* put it in the list  */
d58598
 			profile->state = VSI_UNASSOCIATED;
d58598
 			LIST_INSERT_HEAD(&vd->profile_head, profile, profile);
d58598
-		}
d58598
 
d58598
-		vdp_vsi_sm_bridge(profile);
d58598
+			vdp_vsi_sm_bridge(profile);
d58598
+		}
d58598
 	}
d58598
 
d58598
 	return 0;
d58598
@@ -1357,7 +1357,7 @@ struct packed_tlv *vdp_gettlv(struct vdp
d58598
 	return ptlv;
d58598
 
d58598
 out_free:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	free_pkd_tlv(ptlv);
d58598
 out_err:
d58598
 	LLDPAD_ERR("%s: %s failed\n", __func__, vd->ifname);
d58598
 	return NULL;
d58598
@@ -1607,7 +1607,7 @@ void vdp_ifup(char *ifname, struct lldp_
d58598
 			 __func__, ifname, sizeof(*vd));
d58598
 		goto out_err;
d58598
 	}
d58598
-	strncpy(vd->ifname, ifname, IFNAMSIZ);
d58598
+	STRNCPY_TERMINATED(vd->ifname, ifname, IFNAMSIZ);
d58598
 
d58598
 	vd->role = VDP_ROLE_STATION;
d58598
 	vd->enabletx = enabletx;
d58598
@@ -1624,7 +1624,7 @@ void vdp_ifup(char *ifname, struct lldp_
d58598
 
d58598
 	LIST_INIT(&vd->profile_head);
d58598
 
d58598
-	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02);
d58598
+	ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP02);
d58598
 	LIST_INSERT_HEAD(&ud->head, vd, entry);
d58598
 
d58598
 out_start_again:
d58598
@@ -1882,7 +1882,7 @@ int vdp_trigger(struct vsi_profile *prof
d58598
 	if (!macp->req_pid)
d58598
 		return 0;
d58598
 	sleep(1);		/* Delay message notification */
d58598
-	if (!profile->port || !profile->port->ifname) {
d58598
+	if (!profile->port || !profile->port->ifname[0]) {
d58598
 		LLDPAD_ERR("%s: no ifname found for profile %p:\n", __func__,
d58598
 			   profile);
d58598
 		goto error_exit;
d58598
diff -upr a/qbg/vdp_cmds.c b/qbg/vdp_cmds.c
d58598
--- a/qbg/vdp_cmds.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/qbg/vdp_cmds.c	2020-09-23 08:50:52.658814043 -0400
d58598
@@ -85,7 +85,7 @@ static char *print_mode(char *s, size_t
d58598
 	return s;
d58598
 }
d58598
 
d58598
-static int vdp_cmdok(struct cmd *cmd, cmd_status expected)
d58598
+static int vdp_cmdok(struct cmd *cmd, int expected)
d58598
 {
d58598
 	if (cmd->cmd != expected)
d58598
 		return cmd_invalid;
d58598
diff -upr a/qbg/vdpnl.c b/qbg/vdpnl.c
d58598
--- a/qbg/vdpnl.c	2021-06-09 10:58:59.201200461 -0400
d58598
+++ b/qbg/vdpnl.c	2020-09-23 08:50:52.658814043 -0400
d58598
@@ -233,7 +233,7 @@ static int vdpnl_set(struct nlmsghdr *nl
d58598
 
d58598
 	vsi->ifindex = ifinfo->ifi_index;
d58598
 	if (tb[IFLA_IFNAME])
d58598
-		strncpy(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]),
d58598
+		STRNCPY_TERMINATED(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]),
d58598
 			sizeof vsi->ifname);
d58598
 	else {
d58598
 		if (!if_indextoname(ifinfo->ifi_index, vsi->ifname)) {
d58598
@@ -304,9 +304,9 @@ static size_t vdp_nllen(void)
d58598
 	size_t needed;
d58598
 
d58598
 	needed = nla_total_size(sizeof(struct nlattr)) /* IFLA_VF_PORT */
d58598
-		+ nla_total_size(4);	/* IFLA_PORT_VF */
d58598
-		+ nla_total_size(PORT_UUID_MAX); /* IFLA_PORT_INSTANCE_UUID */
d58598
-		+ nla_total_size(2);	/* IFLA_PORT_RESPONSE */
d58598
+		+ nla_total_size(4) /* IFLA_PORT_VF */
d58598
+		+ nla_total_size(PORT_UUID_MAX) /* IFLA_PORT_INSTANCE_UUID */
d58598
+		+ nla_total_size(2); /* IFLA_PORT_RESPONSE */
d58598
 	return needed;
d58598
 }
d58598
 
d58598
diff -upr a/qbg_utils.c b/qbg_utils.c
d58598
--- a/qbg_utils.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/qbg_utils.c	2020-11-03 09:08:48.062229088 -0500
d58598
@@ -36,7 +36,6 @@
d58598
 #include "qbg_utils.h"
d58598
 
d58598
 extern int loglvl;			/* Global lldpad log level */
d58598
-extern struct lldp_head lldp_head;
d58598
 
d58598
 /*
d58598
  * hexdump_frame - print raw evb/ecp/vdp frame
d58598
@@ -73,7 +72,7 @@ void hexdump_frame(const char *ifname, c
d58598
  */
d58598
 int modules_notify(int id, int sender_id, char *ifname, void *data)
d58598
 {
d58598
-	struct lldp_module *mp = find_module_by_id(&lldp_head, id);
d58598
+	struct lldp_module *mp = find_module_by_id(&lldp_mod_head, id);
d58598
 	int rc = 0;
d58598
 
d58598
 	if (mp && mp->ops->lldp_mod_notify)
d58598
diff -upr a/README b/README
d58598
--- a/README	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/README	2020-09-23 08:50:52.646813830 -0400
d58598
@@ -186,7 +186,9 @@ lldpad Application Install
d58598
    lldpad will create the lldpad.conf file if it does not exist.
d58598
 
d58598
    For development purposes, 'lldpad' can be run directly from the build 
d58598
-   directory.
d58598
+   directory.  To run the unit tests associated with openlldpd, execute:
d58598
+
d58598
+     ./bootstrap.sh; ./configure; make check
d58598
 
d58598
 Options
d58598
 -------
d58598
diff -upr a/tlv_dcbx.c b/tlv_dcbx.c
d58598
--- a/tlv_dcbx.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/tlv_dcbx.c	2020-09-23 08:50:52.659814061 -0400
d58598
@@ -154,7 +154,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->pg1)) {
d58598
 		ptlv = pack_tlv(dcbx->pg1);
d58598
@@ -162,7 +163,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->pfc1)) {
d58598
 		ptlv = pack_tlv(dcbx->pfc1);
d58598
@@ -170,7 +172,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->app1)) {
d58598
 		ptlv = pack_tlv(dcbx->app1);
d58598
@@ -178,7 +181,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 
d58598
 	if (tlv_ok(dcbx->llink)) {
d58598
@@ -187,7 +191,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 
d58598
 	if (offset != tlv->length)
d58598
@@ -196,7 +201,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc
d58598
 	return tlv;
d58598
 
d58598
 error:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	if (ptlv)
d58598
+		free_pkd_tlv(ptlv);
d58598
 	if (tlv) {
d58598
 		if (tlv->info)
d58598
 			free(tlv->info);
d58598
@@ -254,7 +260,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->pg2)) {
d58598
 		ptlv = pack_tlv(dcbx->pg2);
d58598
@@ -262,7 +269,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->pfc2)) {
d58598
 		ptlv = pack_tlv(dcbx->pfc2);
d58598
@@ -270,7 +278,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 	if (tlv_ok(dcbx->app2)) {
d58598
 		ptlv = pack_tlv(dcbx->app2);
d58598
@@ -278,7 +287,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc
d58598
 			goto error;
d58598
 		memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size);
d58598
 		offset += ptlv->size;
d58598
-		ptlv = free_pkd_tlv(ptlv);
d58598
+		free_pkd_tlv(ptlv);
d58598
+		ptlv = NULL;
d58598
 	}
d58598
 
d58598
 	if (offset != tlv->length)
d58598
@@ -287,7 +297,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc
d58598
 	return tlv;
d58598
 
d58598
 error:
d58598
-	ptlv = free_pkd_tlv(ptlv);
d58598
+	if (ptlv)
d58598
+		free_pkd_tlv(ptlv);
d58598
 	if (tlv) {
d58598
 		if (tlv->info)
d58598
 			free(tlv->info);
d58598
diff -upr a/vdptool.c b/vdptool.c
d58598
--- a/vdptool.c	2021-06-09 10:58:59.202200474 -0400
d58598
+++ b/vdptool.c	2020-10-23 14:12:58.978289365 -0400
d58598
@@ -36,6 +36,7 @@
d58598
  * set and query VSI profile settings.
d58598
  */
d58598
 
d58598
+#define _GNU_SOURCE
d58598
 #include <stdlib.h>
d58598
 #include <stdio.h>
d58598
 #include <unistd.h>
d58598
@@ -60,6 +61,8 @@
d58598
 #define OUI_ENCODE_HNDLR(name) name##_oui_encode_hndlr
d58598
 #define OUI_PRNT_DECODE_HNDLR(name) name##_oui_print_decode_hndlr
d58598
 
d58598
+struct lldp_head lldp_mod_head;
d58598
+
d58598
 #define EXTERN_OUI_FN(name) \
d58598
 	extern bool name##_oui_encode_hndlr(char *, char *, size_t); \
d58598
 	extern void name##_oui_print_decode_hndlr(char *)
d58598
@@ -140,7 +143,7 @@ static char *print_status(cmd_status sta
d58598
 		str = "TLV does not support agent type";
d58598
 		break;
d58598
 	default:
d58598
-		str = print_vdp_status(status);
d58598
+		str = print_vdp_status((enum vdp22_cmd_status)status);
d58598
 		break;
d58598
 	}
d58598
 	return str;
d58598
@@ -178,7 +181,7 @@ static char *get_oui_name(char *argvals)
d58598
 
d58598
 static void fill_oui_hdr(vdptool_oui_data_t *oui_data, char *oui_name)
d58598
 {
d58598
-	strncpy(oui_data->oui_name, oui_name, sizeof(oui_data->oui_name));
d58598
+	STRNCPY_TERMINATED(oui_data->oui_name, oui_name, sizeof(oui_data->oui_name));
d58598
 	snprintf(oui_data->data, sizeof(oui_data->data), "%02x%s",
d58598
 		 (unsigned int)strlen(oui_data->oui_name), oui_data->oui_name);
d58598
 }
d58598
@@ -587,7 +590,7 @@ static void print_all_vsis(char *ibuf, b
d58598
 	size_t ilen = strlen(ibuf);
d58598
 	u16 vsi_len;
d58598
 	int offset = 0, vsi_cnt = 0;
d58598
-	char tmp_ibuf[strlen(ibuf)];
d58598
+	char tmp_ibuf[strlen(ibuf) + 1];
d58598
 
d58598
 	while (ilen > 0) {
d58598
 		vsi_len = hex2u16(ibuf + offset);
d58598
@@ -795,13 +798,13 @@ static void init_modules(void)
d58598
 	struct lldp_module *premod = NULL;
d58598
 	int i = 0;
d58598
 
d58598
-	LIST_INIT(&lldp_head);
d58598
+	LIST_INIT(&lldp_mod_head);
d58598
 	for (i = 0; register_tlv_table[i]; i++) {
d58598
 		module = register_tlv_table[i]();
d58598
 		if (premod)
d58598
 			LIST_INSERT_AFTER(premod, module, lldp);
d58598
 		else
d58598
-			LIST_INSERT_HEAD(&lldp_head, module, lldp);
d58598
+			LIST_INSERT_HEAD(&lldp_mod_head, module, lldp);
d58598
 		premod = module;
d58598
 	}
d58598
 }
d58598
@@ -810,9 +813,9 @@ void deinit_modules(void)
d58598
 {
d58598
 	struct lldp_module *module;
d58598
 
d58598
-	while (lldp_head.lh_first != NULL) {
d58598
-		module = lldp_head.lh_first;
d58598
-		LIST_REMOVE(lldp_head.lh_first, lldp);
d58598
+	while (lldp_mod_head.lh_first != NULL) {
d58598
+		module = lldp_mod_head.lh_first;
d58598
+		LIST_REMOVE(lldp_mod_head.lh_first, lldp);
d58598
 		module->ops->lldp_mod_unregister(module);
d58598
 	}
d58598
 }
d58598
@@ -952,7 +955,7 @@ cli_cmd_help(UNUSED struct clif *clif, U
d58598
 	printf("%s\n%s\n%s", commands_usage, commands_options, commands_help);
d58598
 
d58598
 	printf("\nTLV identifiers:\n");
d58598
-	LIST_FOREACH(np, &lldp_head, lldp)
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp)
d58598
 		if (np->ops->print_help)
d58598
 			np->ops->print_help();
d58598
 	return 0;
d58598
@@ -1005,7 +1008,7 @@ u32 lookup_tlvid(char *tlvid_str)
d58598
 	struct lldp_module *np;
d58598
 	u32 tlvid = INVALID_TLVID;
d58598
 
d58598
-	LIST_FOREACH(np, &lldp_head, lldp) {
d58598
+	LIST_FOREACH(np, &lldp_mod_head, lldp) {
d58598
 		if (np->ops->lookup_tlv_name) {
d58598
 			tlvid = np->ops->lookup_tlv_name(tlvid_str);
d58598
 			if (tlvid != INVALID_TLVID)
d58598
diff -upr a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c
d58598
--- a/vdptool_cisco_oui.c	2021-06-09 10:58:59.203200487 -0400
d58598
+++ b/vdptool_cisco_oui.c	2020-09-23 08:50:52.660814079 -0400
d58598
@@ -28,7 +28,7 @@
d58598
 #include "lldp_util.h"
d58598
 #include "vdp_cisco.h"
d58598
 
d58598
-bool cisco_oui_encode_hndlr(char *dst, char *src, int len)
d58598
+bool cisco_oui_encode_hndlr(char *dst, char *src, size_t len)
d58598
 {
d58598
 	char *src_temp = strdup(src);
d58598
 	char *key, *data;
d58598
diff -upr a/weak_readline.c b/weak_readline.c
d58598
--- a/weak_readline.c	2015-01-20 13:42:56.000000000 -0500
d58598
+++ b/weak_readline.c	2020-09-23 08:50:52.660814079 -0400
d58598
@@ -30,6 +30,9 @@
d58598
 #include <dlfcn.h>
d58598
 
d58598
 static int inited;
d58598
+static void *hist_handle;
d58598
+static void *rl_handle;
d58598
+
d58598
 
d58598
 static char *(*readline_p)(const char *);
d58598
 static void (*using_history_p)(void);
d58598
@@ -38,9 +41,6 @@ static void (*add_history_p)(const char
d58598
 
d58598
 static void weak_readline_init(void)
d58598
 {
d58598
-	void *hist_handle;
d58598
-	void *rl_handle;
d58598
-
d58598
 	inited = 1;
d58598
 	hist_handle = dlopen("libhistory.so", RTLD_LAZY | RTLD_GLOBAL);
d58598
 	if (!hist_handle)
d58598
@@ -77,6 +77,16 @@ void using_history(void)
d58598
 		using_history_p();
d58598
 }
d58598
 
d58598
+void close_history(void)
d58598
+{
d58598
+	if (inited) {
d58598
+		dlclose(rl_handle);
d58598
+		rl_handle = NULL;
d58598
+		dlclose(hist_handle);
d58598
+		hist_handle = NULL;
d58598
+	}
d58598
+}
d58598
+
d58598
 void stifle_history(int max)
d58598
 {
d58598
 	if (!inited)