diff --git a/SOURCES/0001-ndptool-add-T-target-support.patch b/SOURCES/0001-ndptool-add-T-target-support.patch
new file mode 100644
index 0000000..eecb1fc
--- /dev/null
+++ b/SOURCES/0001-ndptool-add-T-target-support.patch
@@ -0,0 +1,292 @@
+From acccd780df517b0e5925de4497688b6238bee10c Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Mon, 6 Aug 2018 22:02:09 +0800
+Subject: [PATCH 01/04] ndptool: add -T target support
+
+Currently ndptool can send a Neighbour Solicitation, but does not target
+an IP address, so the NS packet doesn't really make sense.
+
+Extend ndptool to target a destination for Neighbour Solicitation.
+
+v2:
+1) remove function ipv6_addr_is_multicast()
+2) inline some help functions.
+3) update code style.
+4) rename parameter -d/--dest to -T/--target
+
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ include/ndp.h   |   2 +
+ libndp/libndp.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
+ man/ndptool.8   |   4 ++
+ utils/ndptool.c |  21 +++++++--
+ 4 files changed, 145 insertions(+), 3 deletions(-)
+
+diff --git a/include/ndp.h b/include/ndp.h
+index 0dc1468..698bba7 100644
+--- a/include/ndp.h
++++ b/include/ndp.h
+@@ -79,6 +79,8 @@ enum ndp_msg_type ndp_msg_type(struct ndp_msg *msg);
+ struct in6_addr *ndp_msg_addrto(struct ndp_msg *msg);
+ uint32_t ndp_msg_ifindex(struct ndp_msg *msg);
+ void ndp_msg_ifindex_set(struct ndp_msg *msg, uint32_t ifindex);
++void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target);
++void ndp_msg_opt_set(struct ndp_msg *msg);
+ int ndp_msg_send(struct ndp *ndp, struct ndp_msg *msg);
+ int ndp_msg_send_with_flags(struct ndp *ndp, struct ndp_msg *msg, uint8_t flags);
+ 
+diff --git a/libndp/libndp.c b/libndp/libndp.c
+index baacb76..bec55d4 100644
+--- a/libndp/libndp.c
++++ b/libndp/libndp.c
+@@ -32,10 +32,14 @@
+ #include <net/ethernet.h>
+ #include <assert.h>
+ #include <ndp.h>
++#include <net/if.h>
++#include <sys/ioctl.h>
+ 
+ #include "ndp_private.h"
+ #include "list.h"
+ 
++#define pr_err(args...) fprintf(stderr, ##args)
++
+ /**
+  * SECTION: logging
+  * @short_description: libndp logging facility
+@@ -308,6 +312,23 @@ static void ndp_msg_addrto_adjust_all_routers(struct in6_addr *addr)
+ 	addr->s6_addr32[3] = htonl(0x2);
+ }
+ 
++/*
++ * compute link-local solicited-node multicast address
++ */
++static void ndp_msg_addrto_adjust_solicit_multi(struct in6_addr *addr,
++						struct in6_addr *target)
++{
++	struct in6_addr any = IN6ADDR_ANY_INIT;
++
++	/* Don't set addr to target if target is default IN6ADDR_ANY_INIT */
++	if (!memcmp(target, &any, sizeof(any)))
++		return;
++	addr->s6_addr32[0] = htonl(0xFF020000);
++	addr->s6_addr32[1] = 0;
++	addr->s6_addr32[2] = htonl(0x1);
++	addr->s6_addr32[3] = htonl(0xFF000000) | target->s6_addr32[3];
++}
++
+ static bool ndp_msg_addrto_validate_link_local(struct in6_addr *addr)
+ {
+ 	return IN6_IS_ADDR_LINKLOCAL (addr);
+@@ -679,6 +700,106 @@ void ndp_msg_ifindex_set(struct ndp_msg *msg, uint32_t ifindex)
+ 	msg->ifindex = ifindex;
+ }
+ 
++/**
++ * ndp_msg_target_set:
++ * @msg: message structure
++ * @target: ns,na target
++ *
++ * Set target address for NS and NA.
++ **/
++NDP_EXPORT
++void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
++{
++	enum ndp_msg_type msg_type = ndp_msg_type(msg);
++	switch (msg_type) {
++		case NDP_MSG_NS:
++			((struct ndp_msgna*)&msg->nd_msg)->na->nd_na_target = *target;
++			/*
++			 * Neighbor Solicitations are multicast when the node
++			 * needs to resolve an address and unicast when the
++			 * node seeks to verify the reachability of a
++			 * neighbor.
++			 *
++			 * In this case we don't know if we have a cache of
++			 * target, so we use multicast to resolve the target
++			 * address.
++			 * */
++			ndp_msg_addrto_adjust_solicit_multi(&msg->addrto, target);
++			break;
++		case NDP_MSG_NA:
++			((struct ndp_msgns*)&msg->nd_msg)->ns->nd_ns_target = *target;
++			break;
++		default:
++			break;
++	}
++}
++
++static int ndp_get_iface_mac(int ifindex, char *ptr)
++{
++	int sockfd;
++	struct ifreq ifr;
++
++	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
++	if (sockfd == -1) {
++		pr_err("%s: Failed to create socket", __func__);
++		return -errno;
++	}
++
++	if (if_indextoname(ifindex, (char *)&ifr.ifr_name) == NULL) {
++		pr_err("%s: Failed to get iface name with index %d", __func__, ifindex);
++		return -errno;
++	}
++
++	if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
++		pr_err("%s: Failed to get iface mac with index %d\n", __func__, ifindex);
++		return -errno;
++	}
++
++	memcpy(ptr, &ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data));
++
++	return 0;
++}
++
++static void ndp_msg_opt_set_linkaddr(struct ndp_msg *msg, int ndp_opt)
++{
++	char *opts_start = ndp_msg_payload_opts(msg);
++	struct nd_opt_hdr *s_laddr_opt = (struct nd_opt_hdr *) opts_start;
++	char *opt_data = (char *) s_laddr_opt + sizeof(struct nd_opt_hdr);
++	int err;
++
++	err = ndp_get_iface_mac(ndp_msg_ifindex(msg), opt_data);
++	if (err)
++		return;
++
++	opt_data += 6;
++	s_laddr_opt->nd_opt_type = ndp_opt;
++	s_laddr_opt->nd_opt_len = (opt_data - opts_start) >> 3;
++	msg->len += opt_data - opts_start;
++}
++
++/**
++ * ndp_msg_opt_set:
++ * @msg: message structure
++ *
++ * Set neighbor discovery option info.
++ **/
++NDP_EXPORT
++void ndp_msg_opt_set(struct ndp_msg *msg)
++{
++	enum ndp_msg_type msg_type = ndp_msg_type(msg);
++
++	switch (msg_type) {
++		case NDP_MSG_NS:
++			ndp_msg_opt_set_linkaddr(msg, ND_OPT_SOURCE_LINKADDR);
++			break;
++		case NDP_MSG_NA:
++			ndp_msg_opt_set_linkaddr(msg, ND_OPT_TARGET_LINKADDR);
++			break;
++		default:
++			break;
++	}
++}
++
+ /**
+  * ndp_msg_send:
+  * @ndp: libndp library context
+diff --git a/man/ndptool.8 b/man/ndptool.8
+index ef765dc..dd6ddee 100644
+--- a/man/ndptool.8
++++ b/man/ndptool.8
+@@ -41,6 +41,10 @@ Neighbor Advertisement.
+ .B "\-i ifname, \-\-ifname ifname"
+ Specified interface name.
+ 
++.TP
++.B "\-T target, \-\-target target"
++Specified target address for NS/NA message.
++
+ .TP
+ .B "\-U, \-\-unsolicited"
+ Send Unsolicited NA.
+diff --git a/utils/ndptool.c b/utils/ndptool.c
+index 96479fa..ba24d75 100644
+--- a/utils/ndptool.c
++++ b/utils/ndptool.c
+@@ -135,6 +135,7 @@ static void print_help(const char *argv0) {
+             "\t-v --verbose             Increase output verbosity\n"
+             "\t-t --msg-type=TYPE       Specify message type\n"
+ 	    "\t                         (\"rs\", \"ra\", \"ns\", \"na\")\n"
++            "\t-T --target=TARGET       Target address for NS or NA\n"
+             "\t-i --ifname=IFNAME       Specify interface name\n"
+             "\t-U --unsolicited         Send Unsolicited NA\n"
+ 	    "Available commands:\n"
+@@ -333,7 +334,7 @@ static int run_cmd_monitor(struct ndp *ndp, enum ndp_msg_type msg_type,
+ }
+ 
+ static int run_cmd_send(struct ndp *ndp, enum ndp_msg_type msg_type,
+-			uint32_t ifindex)
++			uint32_t ifindex, struct in6_addr *target)
+ {
+ 	struct ndp_msg *msg;
+ 	int err;
+@@ -344,6 +345,8 @@ static int run_cmd_send(struct ndp *ndp, enum ndp_msg_type msg_type,
+ 		return err;
+ 	}
+ 	ndp_msg_ifindex_set(msg, ifindex);
++	ndp_msg_target_set(msg, target);
++	ndp_msg_opt_set(msg);
+ 
+ 	err = ndp_msg_send_with_flags(ndp, msg, flags);
+ 	if (err) {
+@@ -384,6 +387,7 @@ int main(int argc, char **argv)
+ 		{ "verbose",	no_argument,		NULL, 'v' },
+ 		{ "msg-type",	required_argument,	NULL, 't' },
+ 		{ "ifname",	required_argument,	NULL, 'i' },
++		{ "target",	required_argument,	NULL, 'T' },
+ 		{ "unsolicited",no_argument,		NULL, 'U' },
+ 		{ NULL, 0, NULL, 0 }
+ 	};
+@@ -392,12 +396,14 @@ int main(int argc, char **argv)
+ 	char *msgtypestr = NULL;
+ 	enum ndp_msg_type msg_type;
+ 	char *ifname = NULL;
++	char *addr = NULL;
++	struct in6_addr target = IN6ADDR_ANY_INIT;
+ 	uint32_t ifindex;
+ 	char *cmd_name;
+ 	int err;
+ 	int res = EXIT_FAILURE;
+ 
+-	while ((opt = getopt_long(argc, argv, "hvt:i:U",
++	while ((opt = getopt_long(argc, argv, "hvt:T:i:U",
+ 				  long_options, NULL)) >= 0) {
+ 
+ 		switch(opt) {
+@@ -415,6 +421,10 @@ int main(int argc, char **argv)
+ 			free(ifname);
+ 			ifname = strdup(optarg);
+ 			break;
++		case 'd':
++			free(addr);
++			addr = strdup(optarg);
++			break;
+ 		case 'U':
+ 			flags |= ND_OPT_NA_UNSOL;
+ 			break;
+@@ -448,6 +458,11 @@ int main(int argc, char **argv)
+ 		}
+ 	}
+ 
++	if (addr && inet_pton(AF_INET6, addr, &target) <= 0) {
++		pr_err("Invalid target address \"%s\"\n", addr);
++		goto errout;
++	}
++
+ 	err = get_msg_type(&msg_type, msgtypestr);
+ 	if (err) {
+ 		pr_err("Invalid message type \"%s\" selected\n", msgtypestr);
+@@ -478,7 +493,7 @@ int main(int argc, char **argv)
+ 			print_help(argv0);
+ 			goto errout;
+ 		}
+-		err = run_cmd_send(ndp, msg_type, ifindex);
++		err = run_cmd_send(ndp, msg_type, ifindex, &target);
+ 	} else {
+ 		pr_err("Unknown command \"%s\"\n", cmd_name);
+ 		goto ndp_close;
+-- 
+2.19.2
+
diff --git a/SOURCES/0002-ndptool-fix-target-parameter-typo.patch b/SOURCES/0002-ndptool-fix-target-parameter-typo.patch
new file mode 100644
index 0000000..cd5771d
--- /dev/null
+++ b/SOURCES/0002-ndptool-fix-target-parameter-typo.patch
@@ -0,0 +1,31 @@
+From e67999b18c59d37d59b557316dfe53ed5d52e923 Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Wed, 12 Dec 2018 11:38:30 +0800
+Subject: [PATCH 02/04] ndptool: fix target parameter typo
+
+In my last commit acccd780df517 ("ndptool: add -T target support"), after
+renaming parameter -d to -T. I forgot to change the name in switch opt.
+
+Fixes: acccd780df517 ("ndptool: add -T target support")
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ utils/ndptool.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/utils/ndptool.c b/utils/ndptool.c
+index ba24d75..afa516f 100644
+--- a/utils/ndptool.c
++++ b/utils/ndptool.c
+@@ -421,7 +421,7 @@ int main(int argc, char **argv)
+ 			free(ifname);
+ 			ifname = strdup(optarg);
+ 			break;
+-		case 'd':
++		case 'T':
+ 			free(addr);
+ 			addr = strdup(optarg);
+ 			break;
+-- 
+2.19.2
+
diff --git a/SOURCES/0003-libndp-close-sockfd-after-using-to-avoid-handle-leak.patch b/SOURCES/0003-libndp-close-sockfd-after-using-to-avoid-handle-leak.patch
new file mode 100644
index 0000000..2c1d0cb
--- /dev/null
+++ b/SOURCES/0003-libndp-close-sockfd-after-using-to-avoid-handle-leak.patch
@@ -0,0 +1,53 @@
+From 81df977dc0c2a04d5fa0c18dee130490d84a92f5 Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Thu, 20 Dec 2018 11:48:16 +0800
+Subject: [PATCH 03/04] libndp: close sockfd after using to avoid handle leak
+
+Fixes: acccd780df517 ("ndptool: add -T target support")
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ libndp/libndp.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/libndp/libndp.c b/libndp/libndp.c
+index bec55d4..f327d45 100644
+--- a/libndp/libndp.c
++++ b/libndp/libndp.c
+@@ -736,7 +736,7 @@ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
+ 
+ static int ndp_get_iface_mac(int ifindex, char *ptr)
+ {
+-	int sockfd;
++	int sockfd, err = 0;
+ 	struct ifreq ifr;
+ 
+ 	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+@@ -747,17 +747,21 @@ static int ndp_get_iface_mac(int ifindex, char *ptr)
+ 
+ 	if (if_indextoname(ifindex, (char *)&ifr.ifr_name) == NULL) {
+ 		pr_err("%s: Failed to get iface name with index %d", __func__, ifindex);
+-		return -errno;
++		err = -errno;
++		goto close_sock;
+ 	}
+ 
+ 	if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
+ 		pr_err("%s: Failed to get iface mac with index %d\n", __func__, ifindex);
+-		return -errno;
++		err = -errno;
++		goto close_sock;
+ 	}
+ 
+ 	memcpy(ptr, &ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data));
+ 
+-	return 0;
++close_sock:
++	close(sockfd);
++	return err;
+ }
+ 
+ static void ndp_msg_opt_set_linkaddr(struct ndp_msg *msg, int ndp_opt)
+-- 
+2.19.2
+
diff --git a/SOURCES/0004-libndp-fix-nd_msg-typo-when-setting-target-address.patch b/SOURCES/0004-libndp-fix-nd_msg-typo-when-setting-target-address.patch
new file mode 100644
index 0000000..16e9500
--- /dev/null
+++ b/SOURCES/0004-libndp-fix-nd_msg-typo-when-setting-target-address.patch
@@ -0,0 +1,39 @@
+From 23490cbf50a9ad62d480a0916c6d0ca61d221afb Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Mon, 2 Sep 2019 19:39:36 +0800
+Subject: [PATCH 04/04] libndp: fix nd_msg typo when setting target address
+
+When setting the target address of nd_msg, I set the ns/na type reversed.
+
+Fixes: acccd780df517 ("ndptool: add -T target support")
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ libndp/libndp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libndp/libndp.c b/libndp/libndp.c
+index f327d45..8b7de6b 100644
+--- a/libndp/libndp.c
++++ b/libndp/libndp.c
+@@ -713,7 +713,7 @@ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
+ 	enum ndp_msg_type msg_type = ndp_msg_type(msg);
+ 	switch (msg_type) {
+ 		case NDP_MSG_NS:
+-			((struct ndp_msgna*)&msg->nd_msg)->na->nd_na_target = *target;
++			((struct ndp_msgns*)&msg->nd_msg)->ns->nd_ns_target = *target;
+ 			/*
+ 			 * Neighbor Solicitations are multicast when the node
+ 			 * needs to resolve an address and unicast when the
+@@ -727,7 +727,7 @@ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
+ 			ndp_msg_addrto_adjust_solicit_multi(&msg->addrto, target);
+ 			break;
+ 		case NDP_MSG_NA:
+-			((struct ndp_msgns*)&msg->nd_msg)->ns->nd_ns_target = *target;
++			((struct ndp_msgna*)&msg->nd_msg)->na->nd_na_target = *target;
+ 			break;
+ 		default:
+ 			break;
+-- 
+2.19.2
+
diff --git a/SOURCES/0005-ndptool-add-D-dest-support.patch b/SOURCES/0005-ndptool-add-D-dest-support.patch
new file mode 100644
index 0000000..bda1968
--- /dev/null
+++ b/SOURCES/0005-ndptool-add-D-dest-support.patch
@@ -0,0 +1,248 @@
+From e9a35fba03ec3670586fba7debd2e0cb3cd4341e Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Mon, 2 Sep 2019 19:39:12 +0800
+Subject: [PATCH 05/06] ndptool: add -D dest support
+
+This patch add -D dest option, with this option a user could set the dest
+address in IPv6 header for solicited NS/NA message
+
+For function ndp_msg_addrto_adjust_solicit_multi(), I moved the check
+in ndp_msg_target_set() instead of in the function itself.
+
+I also use reverse christmas tree variable order in the main() function
+of ndptool.c.
+
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ include/ndp.h   |  1 +
+ libndp/libndp.c | 42 ++++++++++++++++++++++++++++++++----------
+ man/ndptool.8   |  6 +++++-
+ utils/ndptool.c | 49 +++++++++++++++++++++++++++++++++++--------------
+ 4 files changed, 73 insertions(+), 25 deletions(-)
+
+diff --git a/include/ndp.h b/include/ndp.h
+index 698bba7..7bf8794 100644
+--- a/include/ndp.h
++++ b/include/ndp.h
+@@ -80,6 +80,7 @@ struct in6_addr *ndp_msg_addrto(struct ndp_msg *msg);
+ uint32_t ndp_msg_ifindex(struct ndp_msg *msg);
+ void ndp_msg_ifindex_set(struct ndp_msg *msg, uint32_t ifindex);
+ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target);
++void ndp_msg_dest_set(struct ndp_msg *msg, struct in6_addr *dest);
+ void ndp_msg_opt_set(struct ndp_msg *msg);
+ int ndp_msg_send(struct ndp *ndp, struct ndp_msg *msg);
+ int ndp_msg_send_with_flags(struct ndp *ndp, struct ndp_msg *msg, uint8_t flags);
+diff --git a/libndp/libndp.c b/libndp/libndp.c
+index 8b7de6b..283de77 100644
+--- a/libndp/libndp.c
++++ b/libndp/libndp.c
+@@ -318,11 +318,6 @@ static void ndp_msg_addrto_adjust_all_routers(struct in6_addr *addr)
+ static void ndp_msg_addrto_adjust_solicit_multi(struct in6_addr *addr,
+ 						struct in6_addr *target)
+ {
+-	struct in6_addr any = IN6ADDR_ANY_INIT;
+-
+-	/* Don't set addr to target if target is default IN6ADDR_ANY_INIT */
+-	if (!memcmp(target, &any, sizeof(any)))
+-		return;
+ 	addr->s6_addr32[0] = htonl(0xFF020000);
+ 	addr->s6_addr32[1] = 0;
+ 	addr->s6_addr32[2] = htonl(0x1);
+@@ -700,17 +695,41 @@ void ndp_msg_ifindex_set(struct ndp_msg *msg, uint32_t ifindex)
+ 	msg->ifindex = ifindex;
+ }
+ 
++/**
++ * ndp_msg_dest_set:
++ * @msg: message structure
++ * @dest: ns,na dest
++ *
++ * Set dest address in IPv6 header for NS and NA.
++ **/
++NDP_EXPORT
++void ndp_msg_dest_set(struct ndp_msg *msg, struct in6_addr *dest)
++{
++	enum ndp_msg_type msg_type = ndp_msg_type(msg);
++	switch (msg_type) {
++		case NDP_MSG_NS:
++			/* fall through */
++		case NDP_MSG_NA:
++			msg->addrto = *dest;
++			/* fall through */
++		default:
++			break;
++	}
++}
++
+ /**
+  * ndp_msg_target_set:
+  * @msg: message structure
+  * @target: ns,na target
+  *
+- * Set target address for NS and NA.
++ * Set target address in ICMPv6 header for NS and NA.
+  **/
+ NDP_EXPORT
+ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
+ {
++	struct in6_addr any = IN6ADDR_ANY_INIT;
+ 	enum ndp_msg_type msg_type = ndp_msg_type(msg);
++
+ 	switch (msg_type) {
+ 		case NDP_MSG_NS:
+ 			((struct ndp_msgns*)&msg->nd_msg)->ns->nd_ns_target = *target;
+@@ -720,11 +739,14 @@ void ndp_msg_target_set(struct ndp_msg *msg, struct in6_addr *target)
+ 			 * node seeks to verify the reachability of a
+ 			 * neighbor.
+ 			 *
+-			 * In this case we don't know if we have a cache of
+-			 * target, so we use multicast to resolve the target
+-			 * address.
++			 * In this case we need to update the dest address in
++			 * IPv6 header when
++			 * a) IPv6 dest address is not set
++			 * b) ICMPv6 target address is supplied
+ 			 * */
+-			ndp_msg_addrto_adjust_solicit_multi(&msg->addrto, target);
++			if (!memcmp(&msg->addrto, &any, sizeof(any)) &&
++			    memcmp(target, &any, sizeof(any)))
++				ndp_msg_addrto_adjust_solicit_multi(&msg->addrto, target);
+ 			break;
+ 		case NDP_MSG_NA:
+ 			((struct ndp_msgna*)&msg->nd_msg)->na->nd_na_target = *target;
+diff --git a/man/ndptool.8 b/man/ndptool.8
+index dd6ddee..fb0dd63 100644
+--- a/man/ndptool.8
++++ b/man/ndptool.8
+@@ -41,9 +41,13 @@ Neighbor Advertisement.
+ .B "\-i ifname, \-\-ifname ifname"
+ Specified interface name.
+ 
++.TP
++.B "\-D dest, \-\-dest dest"
++Specified dest address in IPv6 header for NS/NA message.
++
+ .TP
+ .B "\-T target, \-\-target target"
+-Specified target address for NS/NA message.
++Specified target address in ICMPv6 header for NS/NA message.
+ 
+ .TP
+ .B "\-U, \-\-unsolicited"
+diff --git a/utils/ndptool.c b/utils/ndptool.c
+index afa516f..1131462 100644
+--- a/utils/ndptool.c
++++ b/utils/ndptool.c
+@@ -135,7 +135,8 @@ static void print_help(const char *argv0) {
+             "\t-v --verbose             Increase output verbosity\n"
+             "\t-t --msg-type=TYPE       Specify message type\n"
+ 	    "\t                         (\"rs\", \"ra\", \"ns\", \"na\")\n"
+-            "\t-T --target=TARGET       Target address for NS or NA\n"
++            "\t-D --dest=DEST           Dest address in IPv6 header for NS or NA\n"
++            "\t-T --target=TARGET       Target address in ICMPv6 header for NS or NA\n"
+             "\t-i --ifname=IFNAME       Specify interface name\n"
+             "\t-U --unsolicited         Send Unsolicited NA\n"
+ 	    "Available commands:\n"
+@@ -334,7 +335,8 @@ static int run_cmd_monitor(struct ndp *ndp, enum ndp_msg_type msg_type,
+ }
+ 
+ static int run_cmd_send(struct ndp *ndp, enum ndp_msg_type msg_type,
+-			uint32_t ifindex, struct in6_addr *target)
++			uint32_t ifindex, struct in6_addr *dest,
++			struct in6_addr *target)
+ {
+ 	struct ndp_msg *msg;
+ 	int err;
+@@ -345,6 +347,7 @@ static int run_cmd_send(struct ndp *ndp, enum ndp_msg_type msg_type,
+ 		return err;
+ 	}
+ 	ndp_msg_ifindex_set(msg, ifindex);
++	ndp_msg_dest_set(msg, dest);
+ 	ndp_msg_target_set(msg, target);
+ 	ndp_msg_opt_set(msg);
+ 
+@@ -387,23 +390,27 @@ int main(int argc, char **argv)
+ 		{ "verbose",	no_argument,		NULL, 'v' },
+ 		{ "msg-type",	required_argument,	NULL, 't' },
+ 		{ "ifname",	required_argument,	NULL, 'i' },
++		{ "dest",	required_argument,	NULL, 'D' },
+ 		{ "target",	required_argument,	NULL, 'T' },
+ 		{ "unsolicited",no_argument,		NULL, 'U' },
+ 		{ NULL, 0, NULL, 0 }
+ 	};
+-	int opt;
+-	struct ndp *ndp;
+-	char *msgtypestr = NULL;
++
++	struct in6_addr target = IN6ADDR_ANY_INIT;
++	struct in6_addr dest = IN6ADDR_ANY_INIT;
+ 	enum ndp_msg_type msg_type;
++	char *msgtypestr = NULL;
++	int res = EXIT_FAILURE;
+ 	char *ifname = NULL;
+-	char *addr = NULL;
+-	struct in6_addr target = IN6ADDR_ANY_INIT;
++	char *daddr = NULL;
++	char *taddr = NULL;
+ 	uint32_t ifindex;
++	struct ndp *ndp;
+ 	char *cmd_name;
++	int opt;
+ 	int err;
+-	int res = EXIT_FAILURE;
+ 
+-	while ((opt = getopt_long(argc, argv, "hvt:T:i:U",
++	while ((opt = getopt_long(argc, argv, "hvt:D:T:i:U",
+ 				  long_options, NULL)) >= 0) {
+ 
+ 		switch(opt) {
+@@ -421,9 +428,13 @@ int main(int argc, char **argv)
+ 			free(ifname);
+ 			ifname = strdup(optarg);
+ 			break;
++		case 'D':
++			free(daddr);
++			daddr = strdup(optarg);
++			break;
+ 		case 'T':
+-			free(addr);
+-			addr = strdup(optarg);
++			free(taddr);
++			taddr = strdup(optarg);
+ 			break;
+ 		case 'U':
+ 			flags |= ND_OPT_NA_UNSOL;
+@@ -458,8 +469,18 @@ int main(int argc, char **argv)
+ 		}
+ 	}
+ 
+-	if (addr && inet_pton(AF_INET6, addr, &target) <= 0) {
+-		pr_err("Invalid target address \"%s\"\n", addr);
++	if (daddr && (flags & ND_OPT_NA_UNSOL)) {
++		pr_err("Conflicts for both setting dest address and unsolicited flag\n");
++		goto errout;
++	}
++
++	if (daddr && inet_pton(AF_INET6, daddr, &dest) <= 0) {
++		pr_err("Invalid dest address \"%s\"\n", daddr);
++		goto errout;
++	}
++
++	if (taddr && inet_pton(AF_INET6, taddr, &target) <= 0) {
++		pr_err("Invalid target address \"%s\"\n", taddr);
+ 		goto errout;
+ 	}
+ 
+@@ -493,7 +514,7 @@ int main(int argc, char **argv)
+ 			print_help(argv0);
+ 			goto errout;
+ 		}
+-		err = run_cmd_send(ndp, msg_type, ifindex, &target);
++		err = run_cmd_send(ndp, msg_type, ifindex, &dest, &target);
+ 	} else {
+ 		pr_err("Unknown command \"%s\"\n", cmd_name);
+ 		goto ndp_close;
+-- 
+2.19.2
+
diff --git a/SOURCES/0006-ndptool-fix-potential-memory-leak-caused-by-strdup.patch b/SOURCES/0006-ndptool-fix-potential-memory-leak-caused-by-strdup.patch
new file mode 100644
index 0000000..b7cb54c
--- /dev/null
+++ b/SOURCES/0006-ndptool-fix-potential-memory-leak-caused-by-strdup.patch
@@ -0,0 +1,56 @@
+From 27403f898372e99b0ad916bebe2bc29e95bee1f0 Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <haliu@redhat.com>
+Date: Tue, 24 Sep 2019 14:17:56 +0800
+Subject: [PATCH 06/06] ndptool: fix potential memory leak caused by strdup
+
+We use strdup to copy the parameters. As strdup will call malloc when
+obtain the memory, we need to free them before exit, or there will be
+memory leak. This is found by covscan.
+
+Signed-off-by: Hangbin Liu <haliu@redhat.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+---
+ utils/ndptool.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/utils/ndptool.c b/utils/ndptool.c
+index 1131462..4eca83d 100644
+--- a/utils/ndptool.c
++++ b/utils/ndptool.c
+@@ -416,7 +416,8 @@ int main(int argc, char **argv)
+ 		switch(opt) {
+ 		case 'h':
+ 			print_help(argv0);
+-			return EXIT_SUCCESS;
++			res = EXIT_SUCCESS;
++			goto errout;
+ 		case 'v':
+ 			g_verbosity++;
+ 			break;
+@@ -442,11 +443,11 @@ int main(int argc, char **argv)
+ 		case '?':
+ 			pr_err("unknown option.\n");
+ 			print_help(argv0);
+-			return EXIT_FAILURE;
++			goto errout;
+ 		default:
+ 			pr_err("unknown option \"%c\".\n", opt);
+ 			print_help(argv0);
+-			return EXIT_FAILURE;
++			goto errout;
+ 		}
+ 	}
+ 
+@@ -530,5 +531,9 @@ int main(int argc, char **argv)
+ ndp_close:
+ 	ndp_close(ndp);
+ errout:
++	free(msgtypestr);
++	free(ifname);
++	free(daddr);
++	free(taddr);
+ 	return res;
+ }
+-- 
+2.19.2
+
diff --git a/SPECS/libndp.spec b/SPECS/libndp.spec
index 3eb173d..dfd36a4 100644
--- a/SPECS/libndp.spec
+++ b/SPECS/libndp.spec
@@ -1,12 +1,19 @@
 Name: libndp
 Version: 1.7
-Release: 1%{?dist}
+Release: 3%{?dist}
 Summary: Library for Neighbor Discovery Protocol
 Group: System Environment/Libraries
 License: LGPLv2+
 URL: http://www.libndp.org/
 Source: http://www.libndp.org/files/libndp-%{version}.tar.gz
 
+Patch1: 0001-ndptool-add-T-target-support.patch
+Patch2: 0002-ndptool-fix-target-parameter-typo.patch
+Patch3: 0003-libndp-close-sockfd-after-using-to-avoid-handle-leak.patch
+Patch4: 0004-libndp-fix-nd_msg-typo-when-setting-target-address.patch
+Patch5: 0005-ndptool-add-D-dest-support.patch
+Patch6: 0006-ndptool-fix-potential-memory-leak-caused-by-strdup.patch
+
 %description
 This package contains a library which provides a wrapper
 for IPv6 Neighbor Discovery Protocol.  It also provides a tool
@@ -23,6 +30,12 @@ necessary for developing programs using libndp.
 
 %prep
 %setup -q
+%patch1 -p1 -b .ndptool_add_T_target_support
+%patch2 -p1 -b .ndptool_fix_target_parameter_typo
+%patch3 -p1 -b .libndp_close_sockfd_after_using
+%patch4 -p1 -b .libndp_fix_nd_msg_typo
+%patch5 -p1 -b .ndptool_add_D_dest_support
+%patch6 -p1 -b .ndptool_fix_potential_memory_leak
 
 %build
 %configure --disable-static
@@ -48,6 +61,16 @@ find $RPM_BUILD_ROOT -name \*.la -delete
 %{_libdir}/pkgconfig/*.pc
 
 %changelog
+* Fri Nov 01 2019 Hangbin Liu <haliu@redhat.com> - 1.7-3
+- ndptool: add -D dest support (rhbz 1697595)
+- ndptool: fix potential memory leak caused by strdup (rhbz 1697595)
+
+* Fri Nov 01 2019 Hangbin Liu <haliu@redhat.com> - 1.7-2
+- ndptool: add -T target support (rhbz 1666194)
+- ndptool: fix target parameter typo (rhbz 1666194)
+- libndp: close sockfd after using to avoid handle leak (rhbz 1666194)
+- libndp: fix nd_msg typo when setting target address (rhbz 1666194)
+
 * Thu Jul 18 2019 Hangbin Liu <haliu@redhat.com> - 1.7-1
 - Update to 1.7
 - libndp: apply filter to raw socket to only accept ND messages