Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libndp for openSUSE:Factory checked in at 2022-01-20 00:11:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libndp (Old) and /work/SRC/openSUSE:Factory/.libndp.new.1892 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libndp" Thu Jan 20 00:11:53 2022 rev:8 rq:946808 version:1.8 Changes: -------- --- /work/SRC/openSUSE:Factory/libndp/libndp.changes 2018-11-06 14:08:35.163122849 +0100 +++ /work/SRC/openSUSE:Factory/.libndp.new.1892/libndp.changes 2022-01-20 00:12:07.814569263 +0100 @@ -1,0 +2,12 @@ +Tue Jan 4 22:49:20 UTC 2022 - Dirk M??ller <dmuel...@suse.com> + +- update to 1.8: + * libndp,ndptool: use poll() instead of select() + * ndptool: avoid static buffer for string in ndptool + * libndp: avoid static buffer for debug string in ndp_sock_recv() + * libndp: use thread local variables for static return arguments + * ndptool: fix printing dnssl lifetime in ndptool + * ndptool: fix potential memory leak caused by strdup + * libndp: close sockfd after using to avoid handle leak + +------------------------------------------------------------------- Old: ---- libndp-1.7.tar.gz New: ---- libndp-1.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libndp.spec ++++++ --- /var/tmp/diff_new_pack.aQQXDg/_old 2022-01-20 00:12:08.298569653 +0100 +++ /var/tmp/diff_new_pack.aQQXDg/_new 2022-01-20 00:12:08.302569657 +0100 @@ -1,7 +1,7 @@ # # spec file for package libndp # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,13 +17,13 @@ Name: libndp -Version: 1.7 +Version: 1.8 Release: 0 Summary: Library for Neighbor Discovery Protocol License: LGPL-2.1-or-later Group: Productivity/Networking/Other -URL: http://www.libndp.org/ -Source: http://www.libndp.org/files/libndp-%{version}.tar.gz +URL: http://libndp.org/ +Source: http://libndp.org/files/libndp-%{version}.tar.gz BuildRequires: pkgconfig %description @@ -54,7 +54,7 @@ %build %configure \ --disable-static -make %{?_smp_mflags} V=1 +%make_build %install make install DESTDIR=%{buildroot} INSTALL="install -p" ++++++ libndp-1.7.tar.gz -> libndp-1.8.tar.gz ++++++ ++++ 6671 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/build-aux/ar-lib new/libndp-1.8/build-aux/ar-lib --- old/libndp-1.7/build-aux/ar-lib 2016-05-17 12:50:00.000000000 +0200 +++ new/libndp-1.8/build-aux/ar-lib 2019-12-28 13:58:49.000000000 +0100 @@ -4,7 +4,7 @@ me=ar-lib scriptversion=2012-03-01.08; # UTC -# Copyright (C) 2010-2014 Free Software Foundation, Inc. +# Copyright (C) 2010-2018 Free Software Foundation, Inc. # Written by Peter Rosin <p...@lysator.liu.se>. # # This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/build-aux/compile new/libndp-1.8/build-aux/compile --- old/libndp-1.7/build-aux/compile 2016-05-17 12:50:00.000000000 +0200 +++ new/libndp-1.8/build-aux/compile 2019-12-28 13:58:49.000000000 +0100 @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # Written by Tom Tromey <tro...@cygnus.com>. # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -255,7 +255,8 @@ echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/build-aux/missing new/libndp-1.8/build-aux/missing --- old/libndp-1.7/build-aux/missing 2016-05-17 12:50:00.000000000 +0200 +++ new/libndp-1.8/build-aux/missing 2019-12-28 13:58:49.000000000 +0100 @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2013-10-28.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <pin...@iro.umontreal.ca>, 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -101,9 +101,9 @@ exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -207,9 +207,9 @@ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/configure.ac new/libndp-1.8/configure.ac --- old/libndp-1.7/configure.ac 2018-06-08 11:34:21.000000000 +0200 +++ new/libndp-1.8/configure.ac 2021-05-20 11:38:17.000000000 +0200 @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([libndp], [1.7], [j...@resnulli.us]) +AC_INIT([libndp], [1.8], [j...@resnulli.us]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) @@ -22,9 +22,9 @@ # 6. If any interfaces have been removed or changed since the last public # release, then set age to 0. -AC_SUBST(LIBNDP_CURRENT, 1) -AC_SUBST(LIBNDP_REVISION, 1) -AC_SUBST(LIBNDP_AGE, 1) +AC_SUBST(LIBNDP_CURRENT, 2) +AC_SUBST(LIBNDP_REVISION, 0) +AC_SUBST(LIBNDP_AGE, 2) CFLAGS="$CFLAGS -Wall" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/include/ndp.h new/libndp-1.8/include/ndp.h --- old/libndp-1.7/include/ndp.h 2016-05-17 12:54:01.000000000 +0200 +++ new/libndp-1.8/include/ndp.h 2019-09-16 08:55:58.000000000 +0200 @@ -79,6 +79,9 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/libndp/libndp.c new/libndp-1.8/libndp/libndp.c --- old/libndp-1.7/libndp/libndp.c 2016-08-29 09:06:07.000000000 +0200 +++ new/libndp-1.8/libndp/libndp.c 2021-03-05 08:08:18.000000000 +0100 @@ -25,17 +25,21 @@ #include <errno.h> #include <ctype.h> #include <sys/socket.h> -#include <sys/select.h> +#include <poll.h> #include <netinet/in.h> #include <netinet/icmp6.h> #include <arpa/inet.h> #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 @@ -217,11 +221,9 @@ return 0; } -static const char *str_in6_addr(struct in6_addr *addr) +static const char *str_in6_addr(struct in6_addr *addr, char buf[static INET6_ADDRSTRLEN]) { - static char buf[INET6_ADDRSTRLEN]; - - return inet_ntop(AF_INET6, addr, buf, sizeof(buf)); + return inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN); } @@ -308,6 +310,18 @@ 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) +{ + 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); @@ -680,6 +694,137 @@ } /** + * 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 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; + /* + * 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 need to update the dest address in + * IPv6 header when + * a) IPv6 dest address is not set + * b) ICMPv6 target address is supplied + * */ + 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; + break; + default: + break; + } +} + +static int ndp_get_iface_mac(int ifindex, char *ptr) +{ + int sockfd, err = 0; + 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); + 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); + err = -errno; + goto close_sock; + } + + memcpy(ptr, &ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data)); + +close_sock: + close(sockfd); + return err; +} + +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 * @msg: message structure @@ -1468,7 +1613,7 @@ NDP_EXPORT struct in6_addr *ndp_msg_opt_route_prefix(struct ndp_msg *msg, int offset) { - static struct in6_addr prefix; + static NDP_THREAD struct in6_addr prefix; struct __nd_opt_route_info *ri = ndp_msg_payload_opts_offset(msg, offset); @@ -1574,7 +1719,7 @@ struct in6_addr *ndp_msg_opt_rdnss_addr(struct ndp_msg *msg, int offset, int addr_index) { - static struct in6_addr addr; + static NDP_THREAD struct in6_addr addr; struct __nd_opt_rdnss *rdnss = ndp_msg_payload_opts_offset(msg, offset); size_t len = rdnss->nd_opt_rdnss_len << 3; /* convert to bytes */ @@ -1624,7 +1769,7 @@ int domain_index) { int i; - static char buf[256]; + static NDP_THREAD char buf[256]; struct __nd_opt_dnssl *dnssl = ndp_msg_payload_opts_offset(msg, offset); size_t len = dnssl->nd_opt_dnssl_len << 3; /* convert to bytes */ @@ -1673,6 +1818,7 @@ enum ndp_msg_type msg_type; size_t len; int err; + char buf[INET6_ADDRSTRLEN]; msg = ndp_msg_alloc(); if (!msg) @@ -1686,7 +1832,7 @@ goto free_msg; } dbg(ndp, "rcvd from: %s, ifindex: %u, hoplimit: %d", - str_in6_addr(&msg->addrto), msg->ifindex, msg->hoplimit); + str_in6_addr(&msg->addrto, buf), msg->ifindex, msg->hoplimit); if (msg->hoplimit != 255) { warn(ndp, "ignoring packet with bad hop limit (%d)", msg->hoplimit); @@ -1961,22 +2107,20 @@ NDP_EXPORT int ndp_callall_eventfd_handler(struct ndp *ndp) { - fd_set rfds; - int fdmax; - struct timeval tv; - int fd = ndp_get_eventfd(ndp); + struct pollfd pfd; int ret; int err; - memset(&tv, 0, sizeof(tv)); - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - fdmax = fd + 1; + pfd = (struct pollfd) { + .fd = ndp_get_eventfd(ndp), + .events = POLLIN, + }; + while (true) { - ret = select(fdmax, &rfds, NULL, NULL, &tv); + ret = poll(&pfd, 1, 0); if (ret == -1) return -errno; - if (!FD_ISSET(fd, &rfds)) + if (!(pfd.revents & POLLIN)) return 0; err = ndp_call_eventfd_handler(ndp); if (err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/libndp/ndp_private.h new/libndp-1.8/libndp/ndp_private.h --- old/libndp-1.7/libndp/ndp_private.h 2016-05-17 12:54:01.000000000 +0200 +++ new/libndp-1.8/libndp/ndp_private.h 2021-01-27 09:10:20.000000000 +0100 @@ -27,6 +27,7 @@ #include "list.h" #define NDP_EXPORT __attribute__ ((visibility("default"))) +#define NDP_THREAD __thread /** * SECTION: ndp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/man/ndptool.8 new/libndp-1.8/man/ndptool.8 --- old/libndp-1.7/man/ndptool.8 2016-05-17 12:54:01.000000000 +0200 +++ new/libndp-1.8/man/ndptool.8 2019-09-16 08:55:58.000000000 +0200 @@ -42,6 +42,14 @@ 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 in ICMPv6 header for NS/NA message. + +.TP .B "\-U, \-\-unsolicited" Send Unsolicited NA. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/utils/Makefile.am new/libndp-1.8/utils/Makefile.am --- old/libndp-1.7/utils/Makefile.am 2016-05-17 12:54:01.000000000 +0200 +++ new/libndp-1.8/utils/Makefile.am 2021-03-05 08:08:18.000000000 +0100 @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 -AM_CFLAGS = -I${top_srcdir}/include +AM_CFLAGS = -I${top_srcdir}/include -D_GNU_SOURCE ndptool_LDADD = $(top_builddir)/libndp/libndp.la diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libndp-1.7/utils/ndptool.c new/libndp-1.8/utils/ndptool.c --- old/libndp-1.7/utils/ndptool.c 2016-06-15 07:52:09.000000000 +0200 +++ new/libndp-1.8/utils/ndptool.c 2021-03-05 08:08:18.000000000 +0100 @@ -28,7 +28,7 @@ #include <arpa/inet.h> #include <errno.h> #include <ndp.h> -#include <sys/select.h> +#include <poll.h> enum verbosity_level { VERB1, @@ -59,13 +59,10 @@ static int run_main_loop(struct ndp *ndp) { - fd_set rfds; - fd_set rfds_tmp; - int fdmax; + struct pollfd pfd; int ret; struct sigaction siginfo; sigset_t mask; - int ndp_fd; int err = 0; sigemptyset(&siginfo.sa_mask); @@ -100,23 +97,22 @@ sigemptyset(&mask); - FD_ZERO(&rfds); - ndp_fd = ndp_get_eventfd(ndp); - FD_SET(ndp_fd, &rfds); - fdmax = ndp_fd + 1; + pfd = (struct pollfd) { + .fd = ndp_get_eventfd(ndp), + .events = POLLIN, + }; for (;;) { - rfds_tmp = rfds; - ret = pselect(fdmax, &rfds_tmp, NULL, NULL, NULL, &mask); + ret = ppoll(&pfd, 1, NULL, &mask); if (ret == -1) { if (errno == EINTR) { goto out; } - pr_err("Select failed\n"); + pr_err("Poll failed\n"); err = -errno; goto out; } - if (FD_ISSET(ndp_fd, &rfds_tmp)) { + if (pfd.revents & POLLIN) { err = ndp_call_eventfd_handler(ndp); if (err) { pr_err("ndp eventfd handler call failed\n"); @@ -135,6 +131,8 @@ "\t-v --verbose Increase output verbosity\n" "\t-t --msg-type=TYPE Specify message type\n" "\t (\"rs\", \"ra\", \"ns\", \"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" @@ -143,11 +141,9 @@ argv0); } -static const char *str_in6_addr(struct in6_addr *addr) +static const char *str_in6_addr(struct in6_addr *addr, char buf[static INET6_ADDRSTRLEN]) { - static char buf[INET6_ADDRSTRLEN]; - - return inet_ntop(AF_INET6, addr, buf, sizeof(buf)); + return inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN); } static void pr_out_hwaddr(unsigned char *hwaddr, size_t len) @@ -187,6 +183,7 @@ static int msgrcv_handler_func(struct ndp *ndp, struct ndp_msg *msg, void *priv) { + char buf[INET6_ADDRSTRLEN]; char ifname[IF_NAMESIZE]; enum ndp_msg_type msg_type = ndp_msg_type(msg); int offset; @@ -194,7 +191,7 @@ if_indextoname(ndp_msg_ifindex(msg), ifname); pr_out("NDP payload len %zu, from addr: %s, iface: %s\n", ndp_msg_payload_len(msg), - str_in6_addr(ndp_msg_addrto(msg)), ifname); + str_in6_addr(ndp_msg_addrto(msg), buf), ifname); if (msg_type == NDP_MSG_RS) { pr_out(" Type: RS\n"); } else if (msg_type == NDP_MSG_RA) { @@ -243,7 +240,7 @@ valid_time = ndp_msg_opt_prefix_valid_time(msg, offset); preferred_time = ndp_msg_opt_prefix_preferred_time(msg, offset); pr_out(" Prefix: %s/%u", - str_in6_addr(ndp_msg_opt_prefix(msg, offset)), + str_in6_addr(ndp_msg_opt_prefix(msg, offset), buf), ndp_msg_opt_prefix_len(msg, offset)); pr_out(", valid_time: "); if (valid_time == (uint32_t) -1) @@ -267,7 +264,7 @@ pr_out(" MTU: %u\n", ndp_msg_opt_mtu(msg, offset)); ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_ROUTE) { pr_out(" Route: %s/%u", - str_in6_addr(ndp_msg_opt_route_prefix(msg, offset)), + str_in6_addr(ndp_msg_opt_route_prefix(msg, offset), buf), ndp_msg_opt_route_prefix_len(msg, offset)); pr_out(", lifetime: "); pr_out_lft(ndp_msg_opt_route_lifetime(msg, offset)); @@ -276,14 +273,14 @@ pr_out("\n"); } ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_RDNSS) { - static struct in6_addr *addr; + struct in6_addr *addr; int addr_index; pr_out(" Recursive DNS Servers: "); ndp_msg_opt_rdnss_for_each_addr(addr, addr_index, msg, offset) { if (addr_index != 0) pr_out(", "); - pr_out("%s", str_in6_addr(addr)); + pr_out("%s", str_in6_addr(addr, buf)); } pr_out(", lifetime: "); pr_out_lft(ndp_msg_opt_rdnss_lifetime(msg, offset)); @@ -300,7 +297,7 @@ pr_out("%s", domain); } pr_out(", lifetime: "); - pr_out_lft(ndp_msg_opt_rdnss_lifetime(msg, offset)); + pr_out_lft(ndp_msg_opt_dnssl_lifetime(msg, offset)); pr_out("\n"); } } else if (msg_type == NDP_MSG_NS) { @@ -333,7 +330,8 @@ } static int run_cmd_send(struct ndp *ndp, enum ndp_msg_type msg_type, - uint32_t ifindex) + uint32_t ifindex, struct in6_addr *dest, + struct in6_addr *target) { struct ndp_msg *msg; int err; @@ -344,6 +342,9 @@ 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); err = ndp_msg_send_with_flags(ndp, msg, flags); if (err) { @@ -384,26 +385,34 @@ { "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 *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:i:U", + while ((opt = getopt_long(argc, argv, "hvt:D:T:i:U", long_options, NULL)) >= 0) { switch(opt) { case 'h': print_help(argv0); - return EXIT_SUCCESS; + res = EXIT_SUCCESS; + goto errout; case 'v': g_verbosity++; break; @@ -415,17 +424,25 @@ free(ifname); ifname = strdup(optarg); break; + case 'D': + free(daddr); + daddr = strdup(optarg); + break; + case 'T': + free(taddr); + taddr = strdup(optarg); + break; case 'U': flags |= ND_OPT_NA_UNSOL; break; 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; } } @@ -448,6 +465,21 @@ } } + 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; + } + err = get_msg_type(&msg_type, msgtypestr); if (err) { pr_err("Invalid message type \"%s\" selected\n", msgtypestr); @@ -478,7 +510,7 @@ print_help(argv0); goto errout; } - err = run_cmd_send(ndp, msg_type, ifindex); + err = run_cmd_send(ndp, msg_type, ifindex, &dest, &target); } else { pr_err("Unknown command \"%s\"\n", cmd_name); goto ndp_close; @@ -494,5 +526,9 @@ ndp_close: ndp_close(ndp); errout: + free(msgtypestr); + free(ifname); + free(daddr); + free(taddr); return res; }