Module Name: src Committed By: martin Date: Fri Jul 7 13:57:27 UTC 2017
Modified Files: src/sbin/route [netbsd-8]: route.8 route.c rtutil.c src/sys/net [netbsd-8]: if_llatbl.c if_llatbl.h route.c route.h rtsock.c src/sys/netinet [netbsd-8]: if_arp.c in.c src/sys/netinet6 [netbsd-8]: in6.c nd6.c nd6.h src/tests/net [netbsd-8]: net_common.sh src/tests/net/arp [netbsd-8]: t_arp.sh src/tests/net/ndp [netbsd-8]: t_ndp.sh t_ra.sh src/tests/net/net [netbsd-8]: t_ipv6address.sh src/tests/net/route [netbsd-8]: t_flags.sh t_flags6.sh t_route.sh src/usr.sbin/arp [netbsd-8]: arp.c src/usr.sbin/ndp [netbsd-8]: ndp.c Log Message: Pull up following revision(s) (requested by ozaki-r in ticket #107): usr.sbin/arp/arp.c: revision 1.56 sys/net/rtsock.c: revision 1.218 sys/net/if_llatbl.c: revision 1.20 usr.sbin/arp/arp.c: revision 1.57 sys/net/rtsock.c: revision 1.219 sys/net/if_llatbl.c: revision 1.21 usr.sbin/arp/arp.c: revision 1.58 tests/net/net_common.sh: revision 1.19 sys/netinet6/nd6.h: revision 1.84 sys/netinet6/nd6.h: revision 1.85 tests/net/arp/t_arp.sh: revision 1.23 sys/netinet6/in6.c: revision 1.246 tests/net/arp/t_arp.sh: revision 1.24 sys/netinet6/in6.c: revision 1.247 tests/net/arp/t_arp.sh: revision 1.25 sys/netinet6/in6.c: revision 1.248 tests/net/arp/t_arp.sh: revision 1.26 usr.sbin/ndp/ndp.c: revision 1.49 tests/net/arp/t_arp.sh: revision 1.27 tests/net/ndp/t_ndp.sh: revision 1.20 tests/net/arp/t_arp.sh: revision 1.28 tests/net/ndp/t_ndp.sh: revision 1.21 tests/net/arp/t_arp.sh: revision 1.29 tests/net/ndp/t_ndp.sh: revision 1.22 tests/net/ndp/t_ndp.sh: revision 1.23 tests/net/route/t_flags6.sh: revision 1.13 tests/net/ndp/t_ndp.sh: revision 1.24 tests/net/route/t_flags6.sh: revision 1.14 tests/net/ndp/t_ndp.sh: revision 1.25 tests/net/route/t_flags6.sh: revision 1.15 tests/net/ndp/t_ndp.sh: revision 1.26 sbin/route/rtutil.c: revision 1.9 tests/net/ndp/t_ndp.sh: revision 1.27 tests/net/ndp/t_ndp.sh: revision 1.28 tests/net/net/t_ipv6address.sh: revision 1.14 tests/net/ndp/t_ra.sh: revision 1.28 tests/net/ndp/t_ndp.sh: revision 1.29 sys/net/route.h: revision 1.113 tests/net/ndp/t_ra.sh: revision 1.29 sys/net/rtsock.c: revision 1.220 sys/net/rtsock.c: revision 1.221 sys/net/rtsock.c: revision 1.222 sys/net/rtsock.c: revision 1.223 tests/net/route/t_route.sh: revision 1.13 sys/net/rtsock.c: revision 1.224 sys/net/route.c: revision 1.196 sys/net/if_llatbl.c: revision 1.19 sys/net/route.c: revision 1.197 sbin/route/route.c: revision 1.156 tests/net/route/t_flags.sh: revision 1.16 tests/net/route/t_flags.sh: revision 1.17 usr.sbin/ndp/ndp.c: revision 1.50 tests/net/route/t_flags.sh: revision 1.18 sys/netinet/in.c: revision 1.204 tests/net/route/t_flags.sh: revision 1.19 sys/netinet/in.c: revision 1.205 tests/net/arp/t_arp.sh: revision 1.30 tests/net/arp/t_arp.sh: revision 1.31 sys/net/if_llatbl.h: revision 1.11 tests/net/arp/t_arp.sh: revision 1.32 sys/net/if_llatbl.h: revision 1.12 tests/net/arp/t_arp.sh: revision 1.33 sys/netinet6/nd6.c: revision 1.233 sys/netinet6/nd6.c: revision 1.234 sys/netinet/if_arp.c: revision 1.251 sys/netinet6/nd6.c: revision 1.235 sys/netinet/if_arp.c: revision 1.252 sbin/route/route.8: revision 1.57 sys/net/rtsock.c: revision 1.214 sys/net/rtsock.c: revision 1.215 sys/net/rtsock.c: revision 1.216 sys/net/rtsock.c: revision 1.217 whitespace police Simplify We can assume that rt_ifp is always non-NULL. Sending a routing message (RTM_ADD) on adding an llentry A message used to be sent on adding a cloned route. Restore the behavior for backward compatibility. Requested by ryo@ Drop RTF_CONNECTED from a result of RTM_GET for ARP/NDP entries ARP/NDP entries aren't connected routes. Reported by ryo@ Support -c <count> option for route monitor route command exits if it receives <count> routing messages where <count> is a value specified by -c. The option is useful to get only particular message(s) in a test script. Test routing messages emitted on operations of ARP/NDP entries Do netstat -a for an appropriate protocol Add missing declarations for cleanup Set net.inet.arp.keep only if it's required Don't create a permanent L2 cache entry on adding an address to an interface It was created to copy FreeBSD, however actually the cache isn't necessary. Remove it to simplify the code and reduce the cost to maintain it (e.g., keep a consistency with a corresponding local route). Fix typo Fix in_lltable_match_prefix The function has not been used but will be used soon. Remove unused function (nd6_rem_ifa_lle) Allow in6_lltable_free_entry to be called without holding the afdata lock of ifp as well as in_lltable_free_entry This behavior is a bit odd and should be fixed in the future... Purge ARP/NDP entries on an interface when the interface is down Fix PR kern/51179 Purge all related L2 caches on removing a route The change addresses situations similar to PR 51179. Purge L2 caches on changing an interface of a route The change addresses situations similar to PR 51179. Test implicit removals of ARP/NDP entries One test case reproudces PR 51179. Fix build of kernels without both INET and INET6 Tweak lltable_sysctl_dumparp - Rename lltable_sysctl_dumparp to lltable_sysctl_dump because it's not only for ARP - Enable it not only for INET but also for INET6 Fix usage of routing messages on arp -d and ndp -d It didn't work as we expected; we should set RTA_GATEWAY not RTA_IFP on RTM_GET to return an if_index and the kernel should use it on RTM_DELETE. Improve backward compatibility of (fake) routing messages on adding an ARP/NDP entry A message originally included only DST and GATEWAY. Restore it. Fix ifdef; care about a case w/ INET6 and w/o INET Drop RTF_UP from a routing message of a deleted ARP/NDP entry Check existence of ARP/NDP entries Checking ARP/NDP entries is valid rather than checking routes. Fix wrong comment Drop RTF_LLINFO flag (now it's RTF_LLDATA) from local routes They don't have llinfo anymore. And also the change fixes unexpected behavior of ARP proxy. Restore ARP/NDP entries to route show and netstat -r Requested by dyoung@ some time ago Enable to remove multiple ARP/NDP entries for one destination The kernel can have multiple ARP/NDP entries which have an indentical destination on different interfaces. This is normal and can be reproduce easily by ping -I or ping6 -S. We should be able to remove such entries. arp -d <ip> and ndp -d <ip> are changed to fetch all ARP/NDP entries and remove matched entries. So we can remove multiple entries described above. This fetch all and selective removal behavior is the same as arp <ip> and ndp <ip>; they also do fetch all entries and show only matched entries. Related to PR 51179 Check if ARP/NDP entries are purged when a related route is deleted To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.56.8.1 src/sbin/route/route.8 cvs rdiff -u -r1.155 -r1.155.4.1 src/sbin/route/route.c cvs rdiff -u -r1.8 -r1.8.8.1 src/sbin/route/rtutil.c cvs rdiff -u -r1.18 -r1.18.6.1 src/sys/net/if_llatbl.c cvs rdiff -u -r1.10 -r1.10.8.1 src/sys/net/if_llatbl.h cvs rdiff -u -r1.194.6.1 -r1.194.6.2 src/sys/net/route.c cvs rdiff -u -r1.112 -r1.112.4.1 src/sys/net/route.h cvs rdiff -u -r1.213 -r1.213.2.1 src/sys/net/rtsock.c cvs rdiff -u -r1.250.2.1 -r1.250.2.2 src/sys/netinet/if_arp.c cvs rdiff -u -r1.203 -r1.203.2.1 src/sys/netinet/in.c cvs rdiff -u -r1.245 -r1.245.2.1 src/sys/netinet6/in6.c cvs rdiff -u -r1.232 -r1.232.2.1 src/sys/netinet6/nd6.c cvs rdiff -u -r1.83 -r1.83.6.1 src/sys/netinet6/nd6.h cvs rdiff -u -r1.18 -r1.18.2.1 src/tests/net/net_common.sh cvs rdiff -u -r1.22 -r1.22.6.1 src/tests/net/arp/t_arp.sh cvs rdiff -u -r1.19 -r1.19.2.1 src/tests/net/ndp/t_ndp.sh cvs rdiff -u -r1.27 -r1.27.2.1 src/tests/net/ndp/t_ra.sh cvs rdiff -u -r1.13 -r1.13.2.1 src/tests/net/net/t_ipv6address.sh cvs rdiff -u -r1.15 -r1.15.6.1 src/tests/net/route/t_flags.sh cvs rdiff -u -r1.12 -r1.12.6.1 src/tests/net/route/t_flags6.sh cvs rdiff -u -r1.12 -r1.12.4.1 src/tests/net/route/t_route.sh cvs rdiff -u -r1.55 -r1.55.8.1 src/usr.sbin/arp/arp.c cvs rdiff -u -r1.48 -r1.48.6.1 src/usr.sbin/ndp/ndp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/route/route.8 diff -u src/sbin/route/route.8:1.56 src/sbin/route/route.8:1.56.8.1 --- src/sbin/route/route.8:1.56 Mon Apr 4 07:37:07 2016 +++ src/sbin/route/route.8 Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -.\" $NetBSD: route.8,v 1.56 2016/04/04 07:37:07 ozaki-r Exp $ +.\" $NetBSD: route.8,v 1.56.8.1 2017/07/07 13:57:26 martin Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" @(#)route.8 8.4 (Berkeley) 6/1/94 .\" -.Dd March 30, 2016 +.Dd June 16, 2017 .Dt ROUTE 8 .Os .Sh NAME @@ -139,8 +139,17 @@ The monitor command has the syntax .Nm .Op Fl n .Cm monitor +.Op Fl c Ar count .Ed .Pp +If +.Ar count +is specified, +.Nm +exits after receiving +.Ar count +routing messages. +.Pp The flush command has the syntax .Pp .Bd -filled -offset indent -compact Index: src/sbin/route/route.c diff -u src/sbin/route/route.c:1.155 src/sbin/route/route.c:1.155.4.1 --- src/sbin/route/route.c:1.155 Fri Mar 17 16:13:44 2017 +++ src/sbin/route/route.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: route.c,v 1.155 2017/03/17 16:13:44 roy Exp $ */ +/* $NetBSD: route.c,v 1.155.4.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (c) 1983, 1989, 1991, 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 19 #if 0 static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: route.c,v 1.155 2017/03/17 16:13:44 roy Exp $"); +__RCSID("$NetBSD: route.c,v 1.155.4.1 2017/07/07 13:57:26 martin Exp $"); #endif #endif /* not lint */ @@ -108,7 +108,7 @@ static char *netmask_string(const struct static int prefixlen(const char *, struct sou *); #ifndef SMALL static void interfaces(void); -__dead static void monitor(void); +static void monitor(int, char * const *); static int print_getmsg(struct rt_msghdr *, int, struct sou *); static const char *linkstate(struct if_msghdr *); static sup readtag(sup, const char *); @@ -236,7 +236,7 @@ main(int argc, char * const *argv) #ifndef SMALL case K_MONITOR: - monitor(); + monitor(argc, argv); return 0; #endif /* SMALL */ @@ -1105,20 +1105,37 @@ interfaces(void) } static void -monitor(void) +monitor(int argc, char * const *argv) { - int n; + int i, n; union { char msg[2048]; struct rt_msghdr hdr; } u; + int count = 0; + + /* usage: route monitor [-c <count>] */ + + /* eat "monitor" */ + argc -= 1; + argv += 1; + + /* parse [-c <count>] */ + if (argc > 0) { + if (argc != 2) + usage(argv[0]); + if (strcmp(argv[0], "-c") != 0) + usage(argv[0]); + + count = atoi(argv[1]); + } verbose = 1; if (debugonly) { interfaces(); exit(0); } - for(;;) { + for(i = 0; count == 0 || i < count; i++) { time_t now; n = prog_read(sock, &u, sizeof(u)); now = time(NULL); Index: src/sbin/route/rtutil.c diff -u src/sbin/route/rtutil.c:1.8 src/sbin/route/rtutil.c:1.8.8.1 --- src/sbin/route/rtutil.c:1.8 Mon Apr 4 07:37:07 2016 +++ src/sbin/route/rtutil.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtutil.c,v 1.8 2016/04/04 07:37:07 ozaki-r Exp $ */ +/* $NetBSD: rtutil.c,v 1.8.8.1 2017/07/07 13:57:26 martin Exp $ */ /* $OpenBSD: show.c,v 1.1 2006/05/27 19:16:37 claudio Exp $ */ /* @@ -59,6 +59,11 @@ #include "prog_ops.h" #include "rtutil.h" +/* + * Keep to handle ARP/NDP entries (fake routes) + * for backward compatibility. + */ +#define RTF_LLINFO 0x400 #define PLEN (LONG_BIT / 4 + 2) #define PFKEYV2_CHUNK sizeof(u_int64_t) @@ -84,7 +89,7 @@ static const struct bits bits[] = { /* { RTF_CLONING, 'C' }, */ { RTF_CONNECTED, 'C' }, /* { RTF_XRESOLVE, 'X' }, */ - /* { RTF_LLINFO, 'L' }, */ + { RTF_LLINFO, 'L' }, { RTF_STATIC, 'S' }, { RTF_PROTO1, '1' }, { RTF_PROTO2, '2' }, @@ -263,6 +268,9 @@ p_rtentry(struct rt_msghdr *rtm, int fla char ifbuf[IF_NAMESIZE]; #endif + if ((flags & RT_LFLAG) && (rtm->rtm_flags & RTF_LLINFO)) + return; + if (old_af != sa->sa_family) { old_af = sa->sa_family; p_family(sa->sa_family); Index: src/sys/net/if_llatbl.c diff -u src/sys/net/if_llatbl.c:1.18 src/sys/net/if_llatbl.c:1.18.6.1 --- src/sys/net/if_llatbl.c:1.18 Fri Mar 3 06:27:20 2017 +++ src/sys/net/if_llatbl.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_llatbl.c,v 1.18 2017/03/03 06:27:20 msaitoh Exp $ */ +/* $NetBSD: if_llatbl.c,v 1.18.6.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. * Copyright (c) 2004-2008 Qing Li. All rights reserved. @@ -80,6 +80,8 @@ int lltable_dump_entry(struct lltable *llt, struct llentry *lle, struct rt_walkarg *w, struct sockaddr *sa) { +#define RTF_LLINFO 0x400 +#define RTF_CLONED 0x2000 struct ifnet *ifp = llt->llt_ifp; int error; void *a; @@ -107,9 +109,14 @@ lltable_dump_entry(struct lltable *llt, struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; /* Need to copy by myself */ + rtm->rtm_index = ifp->if_index; + rtm->rtm_rmx.rmx_mtu = 0; rtm->rtm_rmx.rmx_expire = (lle->la_flags & LLE_STATIC) ? 0 : lle->la_expire; + rtm->rtm_flags = RTF_UP; rtm->rtm_flags |= RTF_HOST; /* For ndp */ + /* For backward compatibility */ + rtm->rtm_flags |= RTF_LLINFO | RTF_CLONED; rtm->rtm_flags |= (lle->la_flags & LLE_STATIC) ? RTF_STATIC : 0; if (lle->la_flags & LLE_PUB) rtm->rtm_flags |= RTF_ANNOUNCE; @@ -121,6 +128,8 @@ lltable_dump_entry(struct lltable *llt, } return error; +#undef RTF_LLINFO +#undef RTF_CLONED } /* @@ -149,7 +158,7 @@ lltable_dump_af(struct lltable *llt, str * Dump arp state for a specific address family. */ int -lltable_sysctl_dumparp(int af, struct rt_walkarg *w) +lltable_sysctl_dump(int af, struct rt_walkarg *w) { struct lltable *llt; int error = 0; @@ -486,8 +495,8 @@ lltable_drain(int af) } void -lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask, - u_int flags) +lltable_prefix_free(const int af, const struct sockaddr *prefix, + const struct sockaddr *mask, const u_int flags) { struct lltable *llt; Index: src/sys/net/if_llatbl.h diff -u src/sys/net/if_llatbl.h:1.10 src/sys/net/if_llatbl.h:1.10.8.1 --- src/sys/net/if_llatbl.h:1.10 Wed Dec 21 08:47:02 2016 +++ src/sys/net/if_llatbl.h Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_llatbl.h,v 1.10 2016/12/21 08:47:02 ozaki-r Exp $ */ +/* $NetBSD: if_llatbl.h,v 1.10.8.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. * Copyright (c) 2004-2008 Qing Li. All rights reserved. @@ -254,11 +254,11 @@ void lltableinit(void); struct lltable *lltable_allocate_htbl(uint32_t hsize); void lltable_free(struct lltable *); void lltable_link(struct lltable *llt); -void lltable_prefix_free(int, struct sockaddr *, - struct sockaddr *, u_int); +void lltable_prefix_free(const int, const struct sockaddr *, + const struct sockaddr *, const u_int); void lltable_drain(int); void lltable_purge_entries(struct lltable *); -int lltable_sysctl_dumparp(int, struct rt_walkarg *); +int lltable_sysctl_dump(int, struct rt_walkarg *); int lltable_dump_entry(struct lltable *, struct llentry *, struct rt_walkarg *, struct sockaddr *); Index: src/sys/net/route.c diff -u src/sys/net/route.c:1.194.6.1 src/sys/net/route.c:1.194.6.2 --- src/sys/net/route.c:1.194.6.1 Sun Jun 25 06:31:58 2017 +++ src/sys/net/route.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: route.c,v 1.194.6.1 2017/06/25 06:31:58 snj Exp $ */ +/* $NetBSD: route.c,v 1.194.6.2 2017/07/07 13:57:26 martin Exp $ */ /*- * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. @@ -97,7 +97,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.194.6.1 2017/06/25 06:31:58 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.194.6.2 2017/07/07 13:57:26 martin Exp $"); #include <sys/param.h> #ifdef RTFLUSH_DEBUG @@ -123,6 +123,9 @@ __KERNEL_RCSID(0, "$NetBSD: route.c,v 1. #include <net/if.h> #include <net/if_dl.h> #include <net/route.h> +#if defined(INET) || defined(INET6) +#include <net/if_llatbl.h> +#endif #include <netinet/in.h> #include <netinet/in_var.h> @@ -1249,6 +1252,10 @@ rtrequest1(int req, struct rt_addrinfo * need_unlock = false; rt_timer_remove_all(rt); rtcache_clear_rtentry(dst->sa_family, rt); +#if defined(INET) || defined(INET6) + if (netmask != NULL) + lltable_prefix_free(dst->sa_family, dst, netmask, 0); +#endif if (ret_nrt == NULL) { /* Adjust the refcount */ rt_ref(rt); @@ -1587,8 +1594,6 @@ rt_ifa_addlocal(struct ifaddr *ifa) memset(&info, 0, sizeof(info)); info.rti_flags = RTF_HOST | RTF_LOCAL; - if (!(ifa->ifa_ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))) - info.rti_flags |= RTF_LLDATA; info.rti_info[RTAX_DST] = ifa->ifa_addr; info.rti_info[RTAX_GATEWAY] = (const struct sockaddr *)ifa->ifa_ifp->if_sadl; Index: src/sys/net/route.h diff -u src/sys/net/route.h:1.112 src/sys/net/route.h:1.112.4.1 --- src/sys/net/route.h:1.112 Tue Apr 11 13:55:54 2017 +++ src/sys/net/route.h Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: route.h,v 1.112 2017/04/11 13:55:54 roy Exp $ */ +/* $NetBSD: route.h,v 1.112.4.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -500,6 +500,10 @@ int rt_msg3(int, struct rt_addrinfo *, v void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); void route_enqueue(struct mbuf *, int); +struct llentry; +void rt_clonedmsg(const struct sockaddr *, const struct ifnet *, + const struct rtentry *); + /* rtbl */ int rt_addaddr(rtbl_t *, struct rtentry *, const struct sockaddr *); void rt_assert_inactive(const struct rtentry *); Index: src/sys/net/rtsock.c diff -u src/sys/net/rtsock.c:1.213 src/sys/net/rtsock.c:1.213.2.1 --- src/sys/net/rtsock.c:1.213 Thu Jun 1 02:45:14 2017 +++ src/sys/net/rtsock.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtsock.c,v 1.213 2017/06/01 02:45:14 chs Exp $ */ +/* $NetBSD: rtsock.c,v 1.213.2.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213 2017/06/01 02:45:14 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213.2.1 2017/07/07 13:57:26 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -474,7 +474,7 @@ COMPATNAME(route_purgeif)(struct socket return EOPNOTSUPP; } -#ifdef INET +#if defined(INET) || defined(INET6) static int route_get_sdl_index(struct rt_addrinfo *info, int *sdl_index) { @@ -493,7 +493,7 @@ route_get_sdl_index(struct rt_addrinfo * return 0; } -#endif /* INET */ +#endif static void route_get_sdl(const struct ifnet *ifp, const struct sockaddr *dst, @@ -536,12 +536,11 @@ route_output_report(struct rtentry *rt, struct rt_xmsghdr *rtm, struct rt_xmsghdr **new_rtm) { int len; - struct ifnet *ifp; - if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0) - ; - else if ((ifp = rt->rt_ifp) != NULL) { + if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { const struct ifaddr *rtifa; + const struct ifnet *ifp = rt->rt_ifp; + info->rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; /* rtifa used to be simply rt->rt_ifa. * If rt->rt_ifa != NULL, then @@ -569,9 +568,6 @@ route_output_report(struct rtentry *rt, else info->rti_info[RTAX_BRD] = NULL; rtm->rtm_index = ifp->if_index; - } else { - info->rti_info[RTAX_IFP] = NULL; - info->rti_info[RTAX_IFA] = NULL; } (void)rt_msg2(rtm->rtm_type, info, NULL, NULL, &len); if (len > rtm->rtm_msglen) { @@ -645,7 +641,7 @@ route_output_change(struct rtentry *rt, struct ifnet *ifp = NULL, *new_ifp; struct ifaddr *ifa = NULL, *new_ifa; struct psref psref_ifa, psref_new_ifa, psref_ifp; - bool newgw; + bool newgw, ifp_changed = false; /* * New gateway could require new ifaddr, ifp; @@ -695,13 +691,16 @@ route_output_change(struct rtentry *rt, oifa->ifa_rtrequest(RTM_DELETE, rt, info); rt_replace_ifa(rt, ifa); rt->rt_ifp = new_ifp; + ifp_changed = true; } if (new_ifa == NULL) ifa_release(ifa, &psref_ifa); } ifa_release(new_ifa, &psref_new_ifa); - if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) + if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) { rt->rt_ifp = new_ifp; + ifp_changed = true; + } rt_setmetrics(rtm->rtm_inits, rtm, rt); if (rt->rt_flags != info->rti_flags) { rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF) | @@ -709,6 +708,13 @@ route_output_change(struct rtentry *rt, } if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info); +#if defined(INET) || defined(INET6) + if (ifp_changed && rt_mask(rt) != NULL) + lltable_prefix_free(rt_getkey(rt)->sa_family, rt_getkey(rt), + rt_mask(rt), 0); +#else + (void)ifp_changed; /* XXX gcc */ +#endif out: if_put(ifp, &psref_ifp); @@ -793,8 +799,8 @@ COMPATNAME(route_output)(struct mbuf *m, if (info.rti_info[RTAX_GATEWAY] == NULL) { senderr(EINVAL); } -#ifdef INET - /* support for new ARP code with keeping backcompat */ +#if defined(INET) || defined(INET6) + /* support for new ARP/NDP code with keeping backcompat */ if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { const struct sockaddr_dl *sdlp = satocsdl(info.rti_info[RTAX_GATEWAY]); @@ -836,7 +842,7 @@ COMPATNAME(route_output)(struct mbuf *m, break; } fallback: -#endif /* INET */ +#endif /* defined(INET) || defined(INET6) */ error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); if (error == 0) { rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt); @@ -845,16 +851,19 @@ COMPATNAME(route_output)(struct mbuf *m, break; case RTM_DELETE: -#ifdef INET - /* support for new ARP code */ +#if defined(INET) || defined(INET6) + /* support for new ARP/NDP code */ if (info.rti_info[RTAX_GATEWAY] && (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) && (rtm->rtm_flags & RTF_LLDATA) != 0) { + const struct sockaddr_dl *sdlp = + satocsdl(info.rti_info[RTAX_GATEWAY]); error = lla_rt_output(rtm->rtm_type, rtm->rtm_flags, - rtm->rtm_rmx.rmx_expire, &info, 0); + rtm->rtm_rmx.rmx_expire, &info, sdlp->sdl_index); + rtm->rtm_flags &= ~RTF_UP; break; } -#endif /* INET */ +#endif error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); if (error != 0) break; @@ -920,6 +929,7 @@ COMPATNAME(route_output)(struct mbuf *m, rtm = new_rtm; } rtm->rtm_flags |= RTF_LLDATA; + rtm->rtm_flags &= ~RTF_CONNECTED; rtm->rtm_flags |= (ll_flags & LLE_STATIC) ? RTF_STATIC : 0; break; } @@ -1632,6 +1642,42 @@ COMPATNAME(rt_ieee80211msg)(struct ifnet COMPATNAME(route_enqueue)(m, 0); } +#ifndef COMPAT_RTSOCK +/* + * Send a routing message as mimicing that a cloned route is added. + */ +void +rt_clonedmsg(const struct sockaddr *dst, const struct ifnet *ifp, + const struct rtentry *rt) +{ + struct rt_addrinfo info; + /* Mimic flags exactly */ +#define RTF_LLINFO 0x400 +#define RTF_CLONED 0x2000 + int flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_LLINFO | RTF_CLONED; + union { + struct sockaddr sa; + struct sockaddr_storage ss; + struct sockaddr_dl sdl; + } u; + uint8_t namelen = strlen(ifp->if_xname); + uint8_t addrlen = ifp->if_addrlen; + + if (rt == NULL) + return; /* XXX */ + + memset(&info, 0, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, ifp->if_type, + NULL, namelen, NULL, addrlen); + info.rti_info[RTAX_GATEWAY] = &u.sa; + + rt_missmsg(RTM_ADD, &info, flags, 0); +#undef RTF_LLINFO +#undef RTF_CLONED +} +#endif /* COMPAT_RTSOCK */ + /* * This is used in dumping the kernel table via sysctl(). */ @@ -1871,7 +1917,7 @@ again: case NET_RT_DUMP: case NET_RT_FLAGS: -#ifdef INET +#if defined(INET) || defined(INET6) /* * take care of llinfo entries, the caller must * specify an AF @@ -1879,17 +1925,29 @@ again: if (w.w_op == NET_RT_FLAGS && (w.w_arg == 0 || w.w_arg & RTF_LLDATA)) { if (af != 0) - error = lltable_sysctl_dumparp(af, &w); + error = lltable_sysctl_dump(af, &w); else error = EINVAL; break; } -#endif /* INET */ +#endif - for (i = 1; i <= AF_MAX; i++) - if ((af == 0 || af == i) && - (error = rt_walktree(i, sysctl_dumpentry, &w))) - break; + for (i = 1; i <= AF_MAX; i++) { + if (af == 0 || af == i) { + error = rt_walktree(i, sysctl_dumpentry, &w); + if (error != 0) + break; +#if defined(INET) || defined(INET6) + /* + * Return ARP/NDP entries too for + * backward compatibility. + */ + error = lltable_sysctl_dump(i, &w); + if (error != 0) + break; +#endif + } + } break; #ifdef COMPAT_14 Index: src/sys/netinet/if_arp.c diff -u src/sys/netinet/if_arp.c:1.250.2.1 src/sys/netinet/if_arp.c:1.250.2.2 --- src/sys/netinet/if_arp.c:1.250.2.1 Sat Jul 1 08:56:06 2017 +++ src/sys/netinet/if_arp.c Fri Jul 7 13:57:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.250.2.1 2017/07/01 08:56:06 snj Exp $ */ +/* $NetBSD: if_arp.c,v 1.250.2.2 2017/07/07 13:57:27 martin Exp $ */ /*- * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.1 2017/07/01 08:56:06 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.2 2017/07/07 13:57:27 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -760,8 +760,13 @@ notfound: IF_AFDATA_WUNLOCK(ifp); if (la == NULL) ARP_STATINC(ARP_STAT_ALLOCFAIL); - else + else { + struct sockaddr_in sin; + arp_init_llentry(ifp, la); + sockaddr_in_init(&sin, &la->r_l3addr.addr4, 0); + rt_clonedmsg(sintosa(&sin), ifp, rt); + } } else if (LLE_TRY_UPGRADE(la) == 0) { create_lookup = "lookup"; LLE_RUNLOCK(la); @@ -1468,41 +1473,13 @@ arpioctl(u_long cmd, void *data) void arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) { - struct in_addr *ip; struct in_ifaddr *ia = (struct in_ifaddr *)ifa; - /* - * Warn the user if another station has this IP address, - * but only if the interface IP address is not zero. - */ - ip = &IA_SIN(ifa)->sin_addr; - if (!in_nullhost(*ip) && - (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) == 0) { - struct llentry *lle; - - /* - * interface address is considered static entry - * because the output of the arp utility shows - * that L2 entry as permanent - */ - IF_AFDATA_WLOCK(ifp); - lle = lla_create(LLTABLE(ifp), (LLE_IFADDR | LLE_STATIC), - (struct sockaddr *)IA_SIN(ifa)); - IF_AFDATA_WUNLOCK(ifp); - if (lle == NULL) - log(LOG_INFO, "%s: cannot create arp entry for" - " interface address\n", __func__); - else { - arp_init_llentry(ifp, lle); - LLE_RUNLOCK(lle); - } - } - ifa->ifa_rtrequest = arp_rtrequest; ifa->ifa_flags |= RTF_CONNECTED; /* ARP will handle DAD for this address. */ - if (in_nullhost(*ip)) { + if (in_nullhost(IA_SIN(ifa)->sin_addr)) { if (ia->ia_dad_stop != NULL) /* safety */ ia->ia_dad_stop(ifa); ia->ia_dad_start = NULL; Index: src/sys/netinet/in.c diff -u src/sys/netinet/in.c:1.203 src/sys/netinet/in.c:1.203.2.1 --- src/sys/netinet/in.c:1.203 Thu Jun 1 02:45:14 2017 +++ src/sys/netinet/in.c Fri Jul 7 13:57:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in.c,v 1.203 2017/06/01 02:45:14 chs Exp $ */ +/* $NetBSD: in.c,v 1.203.2.1 2017/07/07 13:57:27 martin Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.203 2017/06/01 02:45:14 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.203.2.1 2017/07/07 13:57:27 martin Exp $"); #include "arp.h" @@ -1505,6 +1505,7 @@ in_if_down(struct ifnet *ifp) { in_if_link_down(ifp); + lltable_purge_entries(LLTABLE(ifp)); } void @@ -1896,12 +1897,15 @@ in_lltable_match_prefix(const struct soc { const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix; const struct sockaddr_in *msk = (const struct sockaddr_in *)mask; + struct in_addr lle_addr; + + lle_addr.s_addr = ntohl(lle->r_l3addr.addr4.s_addr); /* * (flags & LLE_STATIC) means deleting all entries * including static ARP entries. */ - if (IN_ARE_MASKED_ADDR_EQUAL(lle->r_l3addr.addr4, pfx, msk) && + if (IN_ARE_MASKED_ADDR_EQUAL(lle_addr, pfx, msk) && ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) return (1); Index: src/sys/netinet6/in6.c diff -u src/sys/netinet6/in6.c:1.245 src/sys/netinet6/in6.c:1.245.2.1 --- src/sys/netinet6/in6.c:1.245 Fri Apr 28 05:56:33 2017 +++ src/sys/netinet6/in6.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in6.c,v 1.245 2017/04/28 05:56:33 ozaki-r Exp $ */ +/* $NetBSD: in6.c,v 1.245.2.1 2017/07/07 13:57:26 martin Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245 2017/04/28 05:56:33 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.1 2017/07/07 13:57:26 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1298,10 +1298,11 @@ in6_update_ifa1(struct ifnet *ifp, struc goto cleanup; } - /* Add local address to lltable, if necessary (ex. on p2p link). */ - error = nd6_add_ifa_lle(ia); - if (error != 0) - goto cleanup; + if (nd6_need_cache(ifp)) { + /* XXX maybe unnecessary */ + ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; + ia->ia_ifa.ifa_flags |= RTF_CONNECTED; + } /* * Perform DAD, if needed. @@ -2273,6 +2274,7 @@ in6_if_down(struct ifnet *ifp) { in6_if_link_down(ifp); + lltable_purge_entries(LLTABLE6(ifp)); } void @@ -2415,15 +2417,16 @@ static void in6_lltable_free_entry(struct lltable *llt, struct llentry *lle) { struct ifnet *ifp = llt->llt_ifp; + bool locked = false; - IF_AFDATA_WLOCK_ASSERT(ifp); LLE_WLOCK_ASSERT(lle); /* Unlink entry from table */ if ((lle->la_flags & LLE_LINKED) != 0) { - + IF_AFDATA_WLOCK_ASSERT(ifp); lltable_unlink_entry(llt, lle); KASSERT((lle->la_flags & LLE_LINKED) == 0); + locked = true; } /* * We need to release the lock here to lle_timer proceeds; @@ -2433,7 +2436,8 @@ in6_lltable_free_entry(struct lltable *l */ LLE_ADDREF(lle); LLE_WUNLOCK(lle); - IF_AFDATA_WUNLOCK(ifp); + if (locked) + IF_AFDATA_WUNLOCK(ifp); #ifdef NET_MPSAFE callout_halt(&lle->lle_timer, NULL); @@ -2449,7 +2453,8 @@ in6_lltable_free_entry(struct lltable *l lltable_drop_entry_queue(lle); LLE_FREE_LOCKED(lle); - IF_AFDATA_WLOCK(ifp); + if (locked) + IF_AFDATA_WLOCK(ifp); } static int Index: src/sys/netinet6/nd6.c diff -u src/sys/netinet6/nd6.c:1.232 src/sys/netinet6/nd6.c:1.232.2.1 --- src/sys/netinet6/nd6.c:1.232 Thu Jun 1 02:45:14 2017 +++ src/sys/netinet6/nd6.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: nd6.c,v 1.232 2017/06/01 02:45:14 chs Exp $ */ +/* $NetBSD: nd6.c,v 1.232.2.1 2017/07/07 13:57:26 martin Exp $ */ /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232 2017/06/01 02:45:14 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232.2.1 2017/07/07 13:57:26 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -2298,6 +2298,7 @@ nd6_resolve(struct ifnet *ifp, const str /* Slow path */ ln = nd6_lookup(&dst->sin6_addr, ifp, true); if (ln == NULL && nd6_is_addr_neighbor(dst, ifp)) { + struct sockaddr_in6 sin6; /* * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), * the condition below is not very efficient. But we believe @@ -2313,6 +2314,10 @@ nd6_resolve(struct ifnet *ifp, const str m_freem(m); return ENOBUFS; } + + sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0); + rt_clonedmsg(sin6tosa(&sin6), ifp, rt); + created = true; } @@ -2418,61 +2423,6 @@ nd6_need_cache(struct ifnet *ifp) } } -/* - * Add pernament ND6 link-layer record for given - * interface address. - * - * Very similar to IPv4 arp_ifinit(), but: - * 1) IPv6 DAD is performed in different place - * 2) It is called by IPv6 protocol stack in contrast to - * arp_ifinit() which is typically called in SIOCSIFADDR - * driver ioctl handler. - * - */ -int -nd6_add_ifa_lle(struct in6_ifaddr *ia) -{ - struct ifnet *ifp; - struct llentry *ln; - - ifp = ia->ia_ifa.ifa_ifp; - if (nd6_need_cache(ifp) == 0) - return 0; - ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; - ia->ia_ifa.ifa_flags |= RTF_CONNECTED; - - IF_AFDATA_WLOCK(ifp); - ln = lla_create(LLTABLE6(ifp), LLE_IFADDR | LLE_EXCLUSIVE, - sin6tosa(&ia->ia_addr)); - IF_AFDATA_WUNLOCK(ifp); - if (ln == NULL) - return ENOBUFS; - - ln->la_expire = 0; /* for IPv6 this means permanent */ - ln->ln_state = ND6_LLINFO_REACHABLE; - - LLE_WUNLOCK(ln); - return 0; -} - -/* - * Removes ALL lle records for interface address prefix. - * XXXME: That's probably not we really want to do, we need - * to remove address record only and keep other records - * until we determine if given prefix is really going - * to be removed. - */ -void -nd6_rem_ifa_lle(struct in6_ifaddr *ia) -{ - struct sockaddr_in6 mask, addr; - - memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr)); - memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); - lltable_prefix_free(AF_INET6, sin6tosa(&addr), sin6tosa(&mask), - LLE_STATIC); -} - static void clear_llinfo_pqueue(struct llentry *ln) { Index: src/sys/netinet6/nd6.h diff -u src/sys/netinet6/nd6.h:1.83 src/sys/netinet6/nd6.h:1.83.6.1 --- src/sys/netinet6/nd6.h:1.83 Wed Feb 22 03:02:55 2017 +++ src/sys/netinet6/nd6.h Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: nd6.h,v 1.83 2017/02/22 03:02:55 ozaki-r Exp $ */ +/* $NetBSD: nd6.h,v 1.83.6.1 2017/07/07 13:57:26 martin Exp $ */ /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ /* @@ -447,8 +447,6 @@ void nd6_cache_lladdr(struct ifnet *, st int nd6_sysctl(int, void *, size_t *, void *, size_t); int nd6_need_cache(struct ifnet *); void nd6_llinfo_release_pkts(struct llentry *, struct ifnet *); -int nd6_add_ifa_lle(struct in6_ifaddr *); -void nd6_rem_ifa_lle(struct in6_ifaddr *); /* nd6_nbr.c */ void nd6_na_input(struct mbuf *, int, int); Index: src/tests/net/net_common.sh diff -u src/tests/net/net_common.sh:1.18 src/tests/net/net_common.sh:1.18.2.1 --- src/tests/net/net_common.sh:1.18 Fri Jun 2 01:18:51 2017 +++ src/tests/net/net_common.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: net_common.sh,v 1.18 2017/06/02 01:18:51 ozaki-r Exp $ +# $NetBSD: net_common.sh,v 1.18.2.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2016 Internet Initiative Japan Inc. # All rights reserved. @@ -157,7 +157,11 @@ start_nc_server() pid=$! echo $pid > $NC_PID - $DEBUG && rump.netstat -a -f inet + if [ $proto = ipv4 ]; then + $DEBUG && rump.netstat -a -f inet + else + $DEBUG && rump.netstat -a -f inet6 + fi export RUMP_SERVER=$backup Index: src/tests/net/arp/t_arp.sh diff -u src/tests/net/arp/t_arp.sh:1.22 src/tests/net/arp/t_arp.sh:1.22.6.1 --- src/tests/net/arp/t_arp.sh:1.22 Fri Nov 25 08:51:16 2016 +++ src/tests/net/arp/t_arp.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_arp.sh,v 1.22 2016/11/25 08:51:16 ozaki-r Exp $ +# $NetBSD: t_arp.sh,v 1.22.6.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2015 The NetBSD Foundation, Inc. # All rights reserved. @@ -28,6 +28,8 @@ SOCKSRC=unix://commsock1 SOCKDST=unix://commsock2 IP4SRC=10.0.1.1 +IP4SRC2=10.0.1.5 +IP4NET=10.0.1.0 IP4DST=10.0.1.2 IP4DST_PROXYARP1=10.0.1.3 IP4DST_PROXYARP2=10.0.1.4 @@ -111,16 +113,20 @@ setup_dst_server() $DEBUG && rump.ifconfig shmif0 $DEBUG && rump.arp -n -a + $DEBUG && rump.netstat -nr -f inet } setup_src_server() { - local keep=$1 + local keep=${1:-0} export RUMP_SERVER=$SOCKSRC # Adjust ARP parameters - atf_check -s exit:0 -o ignore rump.sysctl -w net.inet.arp.keep=$keep + if [ $keep != 0 ]; then + atf_check -s exit:0 -o ignore \ + rump.sysctl -w net.inet.arp.keep=$keep + fi # Setup an interface rump_server_add_iface $SOCKSRC shmif0 bus1 @@ -131,8 +137,9 @@ setup_src_server() # Sanity check $DEBUG && rump.ifconfig shmif0 $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o ignore rump.arp -n $IP4SRC - atf_check -s not-exit:0 -e ignore rump.arp -n $IP4DST + $DEBUG && rump.netstat -nr -f inet + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4SRC + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST } test_cache_expiration() @@ -153,16 +160,18 @@ test_cache_expiration() atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 $IP4DST $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o ignore rump.arp -n $IP4SRC + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4SRC # Should be cached atf_check -s exit:0 -o ignore rump.arp -n $IP4DST + $DEBUG && rump.netstat -nr -f inet + atf_check -s exit:0 -o match:"$IP4DST" rump.netstat -nr -f inet atf_check -s exit:0 sleep $(($arp_keep + $bonus)) $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o ignore rump.arp -n $IP4SRC + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4SRC # Should be expired - atf_check -s not-exit:0 -e ignore rump.arp -n $IP4DST + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST } arp_cache_expiration_5s_body() @@ -179,6 +188,23 @@ arp_cache_expiration_10s_body() rump_server_destroy_ifaces } +check_arp_static_entry() +{ + local ip=$1 + local mac=$2 + local type=$3 + local flags= + + atf_check -s exit:0 -o match:"$mac" rump.arp -n $ip + if [ $type = 'permanent' ]; then + atf_check -s exit:0 -o match:'permanent' rump.arp -n $ip + check_route $ip "$mac" UHLS shmif0 + else + atf_check -s exit:0 -o not-match:'permanent' rump.arp -n $ip + check_route $ip "$mac" UHL shmif0 + fi +} + arp_command_body() { local arp_keep=5 @@ -192,18 +218,17 @@ arp_command_body() export RUMP_SERVER=$SOCKSRC - # We can delete the entry for the interface's IP address - atf_check -s exit:0 -o ignore rump.arp -d $IP4SRC - # Add and delete a static entry $DEBUG && rump.arp -n -a atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:10 $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o match:'b2:a0:20:00:00:10' rump.arp -n 10.0.1.10 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.10 + $DEBUG && rump.netstat -nr -f inet + check_arp_static_entry 10.0.1.10 'b2:a0:20:00:00:10' permanent atf_check -s exit:0 -o ignore rump.arp -d 10.0.1.10 $DEBUG && rump.arp -n -a + $DEBUG && rump.netstat -nr -f inet atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.10 + check_route_no_entry 10.0.1.10 # Add multiple entries via a file cat - > ./list <<-EOF @@ -214,18 +239,15 @@ arp_command_body() 10.0.1.15 b2:a0:20:00:00:15 EOF $DEBUG && rump.arp -n -a + $DEBUG && rump.netstat -nr -f inet atf_check -s exit:0 -o ignore rump.arp -f ./list $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o match:'b2:a0:20:00:00:11' rump.arp -n 10.0.1.11 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.11 - atf_check -s exit:0 -o match:'b2:a0:20:00:00:12' rump.arp -n 10.0.1.12 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.12 - atf_check -s exit:0 -o match:'b2:a0:20:00:00:13' rump.arp -n 10.0.1.13 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.13 - atf_check -s exit:0 -o match:'b2:a0:20:00:00:14' rump.arp -n 10.0.1.14 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.14 - atf_check -s exit:0 -o match:'b2:a0:20:00:00:15' rump.arp -n 10.0.1.15 - atf_check -s exit:0 -o match:'permanent' rump.arp -n 10.0.1.15 + $DEBUG && rump.netstat -nr -f inet + check_arp_static_entry 10.0.1.11 'b2:a0:20:00:00:11' permanent + check_arp_static_entry 10.0.1.12 'b2:a0:20:00:00:12' permanent + check_arp_static_entry 10.0.1.13 'b2:a0:20:00:00:13' permanent + check_arp_static_entry 10.0.1.14 'b2:a0:20:00:00:14' permanent + check_arp_static_entry 10.0.1.15 'b2:a0:20:00:00:15' permanent # Test arp -a atf_check -s exit:0 -o match:'10.0.1.11' rump.arp -n -a @@ -236,6 +258,7 @@ arp_command_body() # Flush all entries $DEBUG && rump.arp -n -a + $DEBUG && rump.netstat -nr -f inet atf_check -s exit:0 -o ignore rump.arp -d -a atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.11 atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.12 @@ -243,17 +266,23 @@ arp_command_body() atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.14 atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.15 atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.1 + check_route_no_entry 10.0.1.11 + check_route_no_entry 10.0.1.12 + check_route_no_entry 10.0.1.13 + check_route_no_entry 10.0.1.14 + check_route_no_entry 10.0.1.15 # Test temp option $DEBUG && rump.arp -n -a atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:10 temp $DEBUG && rump.arp -n -a - atf_check -s exit:0 -o match:'b2:a0:20:00:00:10' rump.arp -n 10.0.1.10 - atf_check -s exit:0 -o not-match:'permanent' rump.arp -n 10.0.1.10 + $DEBUG && rump.netstat -nr -f inet + check_arp_static_entry 10.0.1.10 'b2:a0:20:00:00:10' temp # Hm? the cache doesn't expire... atf_check -s exit:0 sleep $(($arp_keep + $bonus)) $DEBUG && rump.arp -n -a + $DEBUG && rump.netstat -nr -f inet #atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.10 rump_server_destroy_ifaces @@ -309,21 +338,23 @@ arp_garp_body() arp_cache_overwriting_body() { - local arp_keep=5 local bonus=2 rump_server_start $SOCKSRC rump_server_start $SOCKDST setup_dst_server - setup_src_server $arp_keep + setup_src_server export RUMP_SERVER=$SOCKSRC # Cannot overwrite a permanent cache - atf_check -s not-exit:0 -e match:'File exists' \ - rump.arp -s $IP4SRC b2:a0:20:00:00:ff + atf_check -s exit:0 rump.arp -s $IP4DST b2:a0:20:00:00:ff $DEBUG && rump.arp -n -a + atf_check -s not-exit:0 -e match:'File exists' \ + rump.arp -s $IP4DST b2:a0:20:00:00:fe + # cleanup + atf_check -s exit:0 rump.arp -d $IP4DST atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 $IP4DST $DEBUG && rump.arp -n -a @@ -366,7 +397,6 @@ make_pkt_str_garp() test_proxy_arp() { - local arp_keep=5 local opts= title= flags= local type=$1 @@ -374,7 +404,7 @@ test_proxy_arp() rump_server_start $SOCKDST tap setup_dst_server - setup_src_server $arp_keep + setup_src_server export RUMP_SERVER=$SOCKDST atf_check -s exit:0 -o ignore rump.sysctl -w net.inet.ip.forwarding=1 @@ -382,11 +412,11 @@ test_proxy_arp() if [ "$type" = "pub" ]; then opts="pub" - title="permanent published" else opts="pub proxy" - title='permanent published \(proxy only\)' fi + # Always proxy only since migrating to lltable/llentry + title='permanent published \(proxy only\)' # # Test#1: First setup an endpoint then create proxy arp entry @@ -412,26 +442,14 @@ test_proxy_arp() # Try to ping export RUMP_SERVER=$SOCKSRC - if [ "$type" = "pub" ]; then - # XXX fails - atf_check -s not-exit:0 -o ignore -e ignore \ - rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP1 - else - atf_check -s exit:0 -o ignore \ - rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP1 - fi + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP1 extract_new_packets bus1 > ./out $DEBUG && cat ./out pkt1=$(make_pkt_str_arprep $IP4DST_PROXYARP1 $macaddr_dst) pkt2=$(make_pkt_str_garp $IP4DST_PROXYARP1 $macaddr_dst) - if [ "$type" = "pub" ]; then - atf_check -s not-exit:0 -x \ - "cat ./out |grep -q -e '$pkt1' -e '$pkt2'" - else - atf_check -s exit:0 -x "cat ./out |grep -q -e '$pkt1' -e '$pkt2'" - fi + atf_check -s exit:0 -x "cat ./out |grep -q -e '$pkt1' -e '$pkt2'" # # Test#2: Create proxy arp entry then set up an endpoint @@ -480,14 +498,13 @@ arp_proxy_arp_pubproxy_body() arp_link_activation_body() { - local arp_keep=5 local bonus=2 rump_server_start $SOCKSRC rump_server_start $SOCKDST setup_dst_server - setup_src_server $arp_keep + setup_src_server # flush old packets extract_new_packets bus1 > ./out @@ -520,14 +537,13 @@ arp_link_activation_body() arp_static_body() { - local arp_keep=5 local macaddr_src= rump_server_start $SOCKSRC rump_server_start $SOCKDST setup_dst_server - setup_src_server $arp_keep + setup_src_server macaddr_src=$(get_macaddr $SOCKSRC shmif0) @@ -598,6 +614,268 @@ arp_static_cleanup() cleanup } +atf_test_case arp_rtm cleanup +arp_rtm_head() +{ + + atf_set "descr" "Tests for routing messages on operations of ARP entries" + atf_set "require.progs" "rump_server" +} + +arp_rtm_body() +{ + local macaddr_src= macaddr_dst= + local file=./tmp + local pid= str= + + rump_server_start $SOCKSRC + rump_server_start $SOCKDST + + setup_dst_server + setup_src_server + + macaddr_src=$(get_macaddr $SOCKSRC shmif0) + macaddr_dst=$(get_macaddr $SOCKDST shmif0) + + export RUMP_SERVER=$SOCKSRC + + # Test ping and a resulting routing message (RTM_ADD) + rump.route -n monitor -c 1 > $file & + pid=$? + sleep 1 + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST + wait $pid + $DEBUG && cat $file + + str="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>" + atf_check -s exit:0 -o match:"$str" cat $file + str="<DST,GATEWAY>" + atf_check -s exit:0 -o match:"$str" cat $file + str="$IP4DST link#2" + atf_check -s exit:0 -o match:"$str" cat $file + + # Test arp -d and resulting routing messages (RTM_DELETE) + rump.route -n monitor -c 2 > $file & + pid=$? + sleep 1 + atf_check -s exit:0 -o ignore rump.arp -d $IP4DST + wait $pid + $DEBUG && cat $file + + str="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + str="<DST,GATEWAY>" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + str="$IP4DST $macaddr_dst" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + + rump_server_destroy_ifaces +} + +arp_rtm_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case arp_purge_on_route_change cleanup +arp_purge_on_route_change_head() +{ + + atf_set "descr" "Tests if ARP entries are removed on route change" + atf_set "require.progs" "rump_server" +} + +arp_purge_on_route_change_body() +{ + + rump_server_start $SOCKSRC + rump_server_start $SOCKDST + + setup_dst_server + setup_src_server + + rump_server_add_iface $SOCKSRC shmif1 bus1 + export RUMP_SERVER=$SOCKSRC + atf_check -s exit:0 rump.ifconfig shmif1 inet $IP4SRC2/24 + atf_check -s exit:0 rump.ifconfig -w 10 + + $DEBUG && rump.netstat -nr -f inet + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST + $DEBUG && rump.arp -na + atf_check -s exit:0 -o ignore \ + rump.route change -net $IP4NET -ifp shmif1 + $DEBUG && rump.netstat -nr -f inet + $DEBUG && rump.arp -na + # The entry was already removed on route change + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + rump_server_destroy_ifaces +} + +arp_purge_on_route_change_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case arp_purge_on_route_delete cleanup +arp_purge_on_route_delete_head() +{ + + atf_set "descr" "Tests if ARP entries are removed on route delete" + atf_set "require.progs" "rump_server" +} + +arp_purge_on_route_delete_body() +{ + + rump_server_start $SOCKSRC + rump_server_start $SOCKDST + + setup_dst_server + setup_src_server + + $DEBUG && rump.netstat -nr -f inet + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST + $DEBUG && rump.arp -na + + atf_check -s exit:0 -o ignore rump.route delete -net $IP4NET + $DEBUG && rump.netstat -nr -f inet + $DEBUG && rump.arp -na + + # The entry was already removed on route delete + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + rump_server_destroy_ifaces +} + +arp_purge_on_route_delete_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case arp_purge_on_ifdown cleanup +arp_purge_on_ifdown_head() +{ + + atf_set "descr" "Tests if ARP entries are removed on interface down" + atf_set "require.progs" "rump_server" +} + +arp_purge_on_ifdown_body() +{ + + rump_server_start $SOCKSRC + rump_server_start $SOCKDST + + setup_dst_server + setup_src_server + + $DEBUG && rump.netstat -nr -f inet + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST + atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST + + # Shutdown the interface + atf_check -s exit:0 rump.ifconfig shmif0 down + $DEBUG && rump.netstat -nr -f inet + $DEBUG && rump.arp -na + + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + rump_server_destroy_ifaces +} + +arp_purge_on_ifdown_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case arp_stray_entries cleanup +arp_stray_entries_head() +{ + + atf_set "descr" "Tests if ARP entries are removed on route change" + atf_set "require.progs" "rump_server" +} + +arp_stray_entries_body() +{ + + rump_server_start $SOCKSRC + rump_server_start $SOCKDST + + setup_dst_server + setup_src_server + + rump_server_add_iface $SOCKSRC shmif1 bus1 + + export RUMP_SERVER=$SOCKSRC + atf_check -s exit:0 rump.ifconfig shmif1 inet $IP4SRC2/24 + atf_check -s exit:0 rump.ifconfig -w 10 + + $DEBUG && rump.netstat -nr -f inet + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST + $DEBUG && rump.arp -na + atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST + atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST + + # Clean up + atf_check -s exit:0 -o ignore rump.arp -da + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + # ping from a different source address + atf_check -s exit:0 -o ignore \ + rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST + $DEBUG && rump.arp -na + atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST + # ARP reply goes back via shmif1, so a cache is created on shmif1 + atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST + + # Clean up by arp -da + atf_check -s exit:0 -o ignore rump.arp -da + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + # ping from a different source address again + atf_check -s exit:0 -o ignore \ + rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST + atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST + # ARP reply doen't come + atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST + + # Cleanup caches on the destination + export RUMP_SERVER=$SOCKDST + atf_check -s exit:0 -o ignore rump.arp -da + export RUMP_SERVER=$SOCKSRC + + # ping from a different source address again + atf_check -s exit:0 -o ignore \ + rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST + atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST + # ARP reply goes back via shmif1 + atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST + + # Clean up by arp -d <ip> + atf_check -s exit:0 -o ignore rump.arp -d $IP4DST + # Both entries should be deleted + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST + + rump_server_destroy_ifaces +} + +arp_stray_entries_cleanup() +{ + + $DEBUG && dump + cleanup +} + atf_init_test_cases() { atf_add_test_case arp_cache_expiration_5s @@ -609,4 +887,9 @@ atf_init_test_cases() atf_add_test_case arp_proxy_arp_pubproxy atf_add_test_case arp_link_activation atf_add_test_case arp_static + atf_add_test_case arp_rtm + atf_add_test_case arp_purge_on_route_change + atf_add_test_case arp_purge_on_route_delete + atf_add_test_case arp_purge_on_ifdown + atf_add_test_case arp_stray_entries } Index: src/tests/net/ndp/t_ndp.sh diff -u src/tests/net/ndp/t_ndp.sh:1.19 src/tests/net/ndp/t_ndp.sh:1.19.2.1 --- src/tests/net/ndp/t_ndp.sh:1.19 Fri May 26 01:14:38 2017 +++ src/tests/net/ndp/t_ndp.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_ndp.sh,v 1.19 2017/05/26 01:14:38 ozaki-r Exp $ +# $NetBSD: t_ndp.sh,v 1.19.2.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2015 The NetBSD Foundation, Inc. # All rights reserved. @@ -28,7 +28,9 @@ SOCKSRC=unix://commsock1 SOCKDST=unix://commsock2 IP6SRC=fc00::1 +IP6SRC2=fc00::3 IP6DST=fc00::2 +IP6NET=fc00::0 DEBUG=${DEBUG:-false} TIMEOUT=1 @@ -99,8 +101,8 @@ setup_src_server() # Sanity check $DEBUG && rump.ifconfig shmif0 $DEBUG && rump.ndp -n -a - atf_check -s exit:0 -o ignore rump.ndp -n $IP6SRC - atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST } get_timeout() @@ -126,7 +128,7 @@ ndp_cache_expiration_body() atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST $DEBUG && rump.ndp -n -a - atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC # Should be cached atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST @@ -135,7 +137,7 @@ ndp_cache_expiration_body() atf_check -s exit:0 sleep $(($timeout + 1)) $DEBUG && rump.ndp -n -a - atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC # Expired but remains until GC sweaps it (1 day) atf_check -s exit:0 -o match:"$ONEDAYISH" rump.ndp -n $IP6DST @@ -160,17 +162,16 @@ ndp_commands_body() export RUMP_SERVER=$SOCKSRC - # We can delete the entry for the interface's IP address - atf_check -s exit:0 -o match:"$IP6SRC" rump.ndp -d $IP6SRC - # Add and delete a static entry $DEBUG && rump.ndp -n -a atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 $DEBUG && rump.ndp -n -a atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10 + check_route fc00::10 'b2:a0:20:00:00:10' UHLS shmif0 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10 $DEBUG && rump.ndp -n -a atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10 + check_route_no_entry fc00::10 # Add multiple entries via a file (XXX not implemented) #cat - > ./list <<-EOF @@ -191,6 +192,9 @@ ndp_commands_body() atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12 + check_route_flags $IP6DST UHL + check_route_flags fc00::11 UHLS + check_route_flags fc00::12 UHLS # Test ndp -a atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a @@ -204,15 +208,20 @@ ndp_commands_body() atf_check -s exit:0 -o ignore rump.ndp -c atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST + #check_route_no_entry $IP6SRC + check_route_no_entry $IP6DST # Only the static caches are not deleted atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12 + check_route_flags fc00::11 UHLS + check_route_flags fc00::12 UHLS $DEBUG && rump.ndp -n -a atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp $DEBUG && rump.ndp -n -a atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10 + check_route fc00::10 'b2:a0:20:00:00:10' UHL shmif0 rump_server_destroy_ifaces } @@ -229,8 +238,9 @@ ndp_cache_overwriting_body() export RUMP_SERVER=$SOCKSRC # Cannot overwrite a permanent cache - atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:ff + atf_check -s exit:0 rump.ndp -s $IP6SRC b2:a0:20:00:00:ff $DEBUG && rump.ndp -n -a + atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:fe atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST $DEBUG && rump.ndp -n -a @@ -396,6 +406,275 @@ ndp_link_activation_cleanup() cleanup } +atf_test_case ndp_rtm cleanup +ndp_rtm_head() +{ + + atf_set "descr" "Tests for routing messages on operations of NDP entries" + atf_set "require.progs" "rump_server" +} + +ndp_rtm_body() +{ + local macaddr_src= macaddr_dst= + local file=./tmp + local pid= str= + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + macaddr_src=$(get_macaddr $SOCKSRC shmif0) + macaddr_dst=$(get_macaddr $SOCKDST shmif0) + + export RUMP_SERVER=$SOCKSRC + + # Test ping and a resulting routing message (RTM_ADD) + rump.route -n monitor -c 1 > $file & + pid=$? + sleep 1 + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST + wait $pid + $DEBUG && cat $file + + str="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>" + atf_check -s exit:0 -o match:"$str" cat $file + str="<DST,GATEWAY>" + atf_check -s exit:0 -o match:"$str" cat $file + str="$IP6DST link#2" + atf_check -s exit:0 -o match:"$str" cat $file + + # Test ndp -d and resulting routing messages (RTM_DELETE) + rump.route -n monitor -c 2 > $file & + pid=$? + sleep 1 + atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST + wait $pid + $DEBUG && cat $file + + str="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + str="<DST,GATEWAY>" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + str="$IP6DST $macaddr_dst" + atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file + + rump_server_destroy_ifaces +} + +ndp_rtm_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case ndp_purge_on_route_change cleanup +ndp_purge_on_route_change_head() +{ + + atf_set "descr" "Tests if NDP entries are removed on route change" + atf_set "require.progs" "rump_server" +} + +ndp_purge_on_route_change_body() +{ + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + rump_server_add_iface $SOCKSRC shmif1 bus1 + export RUMP_SERVER=$SOCKSRC + atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2 + atf_check -s exit:0 rump.ifconfig -w 10 + + $DEBUG && rump.netstat -nr -f inet6 + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + + atf_check -s exit:0 -o ignore \ + rump.route change -inet6 -net $IP6NET/64 -ifp shmif1 + $DEBUG && rump.netstat -nr -f inet6 + $DEBUG && rump.ndp -na + # The entry was already removed on route change + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6DST + + rump_server_destroy_ifaces +} + +ndp_purge_on_route_change_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case ndp_purge_on_route_delete cleanup +ndp_purge_on_route_delete_head() +{ + + atf_set "descr" "Tests if NDP entries are removed on route delete" + atf_set "require.progs" "rump_server" +} + +ndp_purge_on_route_delete_body() +{ + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + $DEBUG && rump.netstat -nr -f inet6 + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + + atf_check -s exit:0 -o ignore rump.route delete -inet6 -net $IP6NET/64 + $DEBUG && rump.netstat -nr -f inet6 + $DEBUG && rump.ndp -na + + # The entry was already removed on route delete + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6DST + + rump_server_destroy_ifaces +} + +ndp_purge_on_route_delete_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case ndp_purge_on_ifdown cleanup +ndp_purge_on_ifdown_head() +{ + + atf_set "descr" "Tests if NDP entries are removed on interface down" + atf_set "require.progs" "rump_server" +} + +ndp_purge_on_ifdown_body() +{ + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + $DEBUG && rump.netstat -nr -f inet6 + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + + # Shutdown the interface + atf_check -s exit:0 rump.ifconfig shmif0 down + $DEBUG && rump.netstat -nr -f inet6 + $DEBUG && rump.ndp -na + + # The entry was already removed on ifconfig down + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6DST + + rump_server_destroy_ifaces +} + +ndp_purge_on_ifdown_cleanup() +{ + + $DEBUG && dump + cleanup +} + +atf_test_case ndp_stray_entries cleanup +ndp_stray_entries_head() +{ + + atf_set "descr" "Tests if NDP entries are removed on route change" + atf_set "require.progs" "rump_server" +} + +ndp_stray_entries_body() +{ + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + rump_server_add_iface $SOCKSRC shmif1 bus1 + + export RUMP_SERVER=$SOCKSRC + atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2/64 + atf_check -s exit:0 rump.ifconfig -w 10 + + $DEBUG && rump.netstat -nr -f inet6 + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST + $DEBUG && rump.ndp -na + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST + + # Clean up + atf_check -s exit:0 -o ignore rump.ndp -c + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST + + # ping from a different source address + atf_check -s exit:0 -o ignore \ + rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST + $DEBUG && rump.ndp -na + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + # ARP reply goes back via shmif1, so a cache is created on shmif1 + atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST + + # Clean up by ndp -c + atf_check -s exit:0 -o ignore rump.ndp -c + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST + + # ping from a different source address again + atf_check -s exit:0 -o ignore \ + rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + # ARP reply doen't come + atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST + + # Cleanup caches on the destination + export RUMP_SERVER=$SOCKDST + $DEBUG && rump.ndp -na + atf_check -s exit:0 -o ignore rump.ndp -c + $DEBUG && rump.ndp -na + export RUMP_SERVER=$SOCKSRC + + # ping from a different source address again + atf_check -s exit:0 -o ignore \ + rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST + atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST + # ARP reply goes back via shmif1 + atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST + + # Clean up by ndp -d <ip> + atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST + # Both entries should be deleted + atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST + + rump_server_destroy_ifaces +} + +ndp_stray_entries_cleanup() +{ + + $DEBUG && dump + cleanup +} + atf_init_test_cases() { atf_add_test_case ndp_cache_expiration @@ -403,4 +682,9 @@ atf_init_test_cases() atf_add_test_case ndp_cache_overwriting atf_add_test_case ndp_neighborgcthresh atf_add_test_case ndp_link_activation + atf_add_test_case ndp_rtm + atf_add_test_case ndp_purge_on_route_change + atf_add_test_case ndp_purge_on_route_delete + atf_add_test_case ndp_purge_on_ifdown + atf_add_test_case ndp_stray_entries } Index: src/tests/net/ndp/t_ra.sh diff -u src/tests/net/ndp/t_ra.sh:1.27 src/tests/net/ndp/t_ra.sh:1.27.2.1 --- src/tests/net/ndp/t_ra.sh:1.27 Fri May 26 01:14:38 2017 +++ src/tests/net/ndp/t_ra.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_ra.sh,v 1.27 2017/05/26 01:14:38 ozaki-r Exp $ +# $NetBSD: t_ra.sh,v 1.27.2.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2015 Internet Initiative Japan Inc. # All rights reserved. @@ -149,7 +149,7 @@ check_entries() atf_check -s exit:0 \ -o match:"$ll_srv%shmif0 +$mac_srv +shmif0 +$ONEDAYISH S R" \ rump.ndp -n -a - atf_check -s exit:0 -o match:$addr_prefix rump.ndp -n -a + atf_check -s exit:0 -o not-match:$addr_prefix rump.ndp -n -a atf_check -s exit:0 \ -o match:"$addr_prefix.+<(TENTATIVE,)?AUTOCONF>" \ rump.ifconfig shmif0 inet6 @@ -277,7 +277,7 @@ ra_flush_prefix_entries_body() atf_check -s exit:0 -o empty rump.ndp -p atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 atf_check -s exit:0 -o match:"$ONEDAYISH S R" rump.ndp -n -a - atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a + atf_check -s exit:0 -o not-match:'fc00:1:' rump.ndp -n -a atf_check -s exit:0 -o not-match:'fc00:1:' rump.ifconfig shmif0 inet6 unset RUMP_SERVER @@ -334,8 +334,7 @@ ra_flush_defrouter_entries_body() atf_check -s exit:0 -o empty rump.ndp -r atf_check -s exit:0 -o match:'No advertising router' rump.ndp -p atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 - atf_check -s exit:0 -o match:"$ONEDAYISH S R" rump.ndp -n -a - atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a + atf_check -s exit:0 -o not-match:'fc00:1:' rump.ndp -n -a atf_check -s exit:0 -o match:'fc00:1:' rump.ifconfig shmif0 inet6 unset RUMP_SERVER @@ -762,8 +761,7 @@ ra_defrouter_expiration_body() atf_check -s exit:0 -o not-match:'if=shmif0' rump.ndp -r atf_check -s exit:0 -o match:'No advertising router' rump.ndp -p atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 - atf_check -s exit:0 -o match:"$ONEDAYISH S R" rump.ndp -n -a - atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a + atf_check -s exit:0 -o not-match:'fc00:1:' rump.ndp -n -a atf_check -s exit:0 -o match:'fc00:1:' rump.ifconfig shmif0 inet6 unset RUMP_SERVER @@ -828,7 +826,7 @@ ra_prefix_expiration_body() atf_check -s exit:0 -o empty rump.ndp -p atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 atf_check -s exit:0 -o match:"$ONEDAYISH S R" rump.ndp -n -a - atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a + atf_check -s exit:0 -o not-match:'fc00:1:' rump.ndp -n -a atf_check -s exit:0 -o not-match:'fc00:1:' rump.ifconfig shmif0 inet6 unset RUMP_SERVER Index: src/tests/net/net/t_ipv6address.sh diff -u src/tests/net/net/t_ipv6address.sh:1.13 src/tests/net/net/t_ipv6address.sh:1.13.2.1 --- src/tests/net/net/t_ipv6address.sh:1.13 Fri May 26 01:14:38 2017 +++ src/tests/net/net/t_ipv6address.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_ipv6address.sh,v 1.13 2017/05/26 01:14:38 ozaki-r Exp $ +# $NetBSD: t_ipv6address.sh,v 1.13.2.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2015 Internet Initiative Japan Inc. # All rights reserved. @@ -364,7 +364,7 @@ linklocal_ops_body() rump.route get -inet6 ${src_if0_lladdr} # ndp - atf_check -s exit:0 -o match:"${src_if0_lladdr}" \ + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ rump.ndp -n ${src_if0_lladdr}%shmif0 # ndp without an interface name (zone index) Index: src/tests/net/route/t_flags.sh diff -u src/tests/net/route/t_flags.sh:1.15 src/tests/net/route/t_flags.sh:1.15.6.1 --- src/tests/net/route/t_flags.sh:1.15 Wed Dec 21 02:46:08 2016 +++ src/tests/net/route/t_flags.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_flags.sh,v 1.15 2016/12/21 02:46:08 ozaki-r Exp $ +# $NetBSD: t_flags.sh,v 1.15.6.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2015 The NetBSD Foundation, Inc. # All rights reserved. @@ -100,7 +100,7 @@ test_connected() export RUMP_SERVER=$SOCK_LOCAL - # Up, Host, LLINFO, local + # Up, Host, local check_route_flags 10.0.0.2 UHl # Up, Cloning @@ -148,6 +148,8 @@ test_blackhole() # Delete an existing route first atf_check -s exit:0 -o ignore rump.route delete -net 10.0.0.0/24 + # Should be removed too + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n 10.0.0.1 # Gateway must be lo0 atf_check -s exit:0 -o ignore \ @@ -163,6 +165,7 @@ test_blackhole() # Shouldn't be created check_route_no_entry 10.0.0.1 + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n 10.0.0.1 } test_reject() @@ -185,6 +188,7 @@ test_reject() # Shouldn't be created check_route_no_entry 10.0.0.1 + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n 10.0.0.1 # Gateway is lo0 (RTF_GATEWAY) @@ -204,6 +208,7 @@ test_reject() # Shouldn't be created check_route_no_entry 10.0.0.1 + atf_check -s not-exit:0 -e match:'no entry' rump.arp -n 10.0.0.1 # Gateway is lo0 (RTF_HOST) @@ -297,6 +302,20 @@ test_announce() # TODO test its behavior } +test_llinfo() +{ + local peer_macaddr= + + peer_macaddr=$(get_macaddr $SOCK_PEER shmif0) + + export RUMP_SERVER=$SOCK_LOCAL + + atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 10.0.0.1 + + # Up, Host, LLINFO + check_route 10.0.0.1 $peer_macaddr UHL shmif0 +} + add_test() { local name=$1 @@ -331,4 +350,5 @@ atf_init_test_cases() add_test reject "Tests route flags: reject route" add_test icmp_redirect "Tests route flags: icmp redirect" add_test announce "Tests route flags: announce flag" + add_test llinfo "Tests route flags: ARP caches" } Index: src/tests/net/route/t_flags6.sh diff -u src/tests/net/route/t_flags6.sh:1.12 src/tests/net/route/t_flags6.sh:1.12.6.1 --- src/tests/net/route/t_flags6.sh:1.12 Wed Dec 21 02:46:08 2016 +++ src/tests/net/route/t_flags6.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_flags6.sh,v 1.12 2016/12/21 02:46:08 ozaki-r Exp $ +# $NetBSD: t_flags6.sh,v 1.12.6.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2016 Internet Initiative Japan Inc. # All rights reserved. @@ -134,6 +134,9 @@ test_blackhole6() # Delete an existing route first atf_check -s exit:0 -o ignore \ rump.route delete -inet6 -net fc00::/64 + # Should be removed too + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6_PEER # Gateway must be lo0 atf_check -s exit:0 -o ignore \ @@ -149,6 +152,8 @@ test_blackhole6() # Shouldn't be created check_route_no_entry $IP6_PEER + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6_PEER } test_reject6() @@ -173,6 +178,8 @@ test_reject6() # Shouldn't be created check_route_no_entry $IP6_PEER + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6_PEER # Gateway is lo0 (RTF_GATEWAY) @@ -193,6 +200,8 @@ test_reject6() # Shouldn't be created check_route_no_entry $IP6_PEER + atf_check -s not-exit:0 -o ignore -e match:'no entry' \ + rump.ndp -n $IP6_PEER # Gateway is lo0 (RTF_HOST) @@ -232,6 +241,20 @@ test_announce6() # TODO test its behavior } +test_llinfo6() +{ + local peer_macaddr= + + peer_macaddr=$(get_macaddr $SOCK_PEER shmif0) + + export RUMP_SERVER=$SOCK_LOCAL + + atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6_PEER + + # Up, Host, LLINFO + check_route $IP6_PEER $peer_macaddr UHL shmif0 +} + add_test() { local name=$1 @@ -265,4 +288,5 @@ atf_init_test_cases() add_test blackhole6 "Tests route flags: blackhole route" add_test reject6 "Tests route flags: reject route" add_test announce6 "Tests route flags: announce flag" + add_test llinfo6 "Tests route flags: announce llinfo" } Index: src/tests/net/route/t_route.sh diff -u src/tests/net/route/t_route.sh:1.12 src/tests/net/route/t_route.sh:1.12.4.1 --- src/tests/net/route/t_route.sh:1.12 Fri Mar 24 03:47:25 2017 +++ src/tests/net/route/t_route.sh Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_route.sh,v 1.12 2017/03/24 03:47:25 ozaki-r Exp $ +# $NetBSD: t_route.sh,v 1.12.4.1 2017/07/07 13:57:26 martin Exp $ # # Copyright (c) 2016 Internet Initiative Japan Inc. # All rights reserved. @@ -234,7 +234,7 @@ test_route_get() destination: 10.0.1.2 local addr: 10.0.1.2 interface: lo0 - flags: <UP,HOST,DONE,LLINFO,LOCAL> + flags: <UP,HOST,DONE,LOCAL> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire EOF rump.route -n get $IP4SRC > ./output @@ -309,7 +309,7 @@ test_route_get6() destination: fc00:0:0:1::2 local addr: fc00:0:0:1::2 interface: lo0 - flags: <UP,HOST,DONE,LLINFO,LOCAL> + flags: <UP,HOST,DONE,LOCAL> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire EOF rump.route -n get -inet6 $IP6SRC > ./output Index: src/usr.sbin/arp/arp.c diff -u src/usr.sbin/arp/arp.c:1.55 src/usr.sbin/arp/arp.c:1.55.8.1 --- src/usr.sbin/arp/arp.c:1.55 Mon Apr 4 07:37:08 2016 +++ src/usr.sbin/arp/arp.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: arp.c,v 1.55 2016/04/04 07:37:08 ozaki-r Exp $ */ +/* $NetBSD: arp.c,v 1.55.8.1 2017/07/07 13:57:26 martin Exp $ */ /* * Copyright (c) 1984, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1984, 19 #if 0 static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: arp.c,v 1.55 2016/04/04 07:37:08 ozaki-r Exp $"); +__RCSID("$NetBSD: arp.c,v 1.55.8.1 2017/07/07 13:57:26 martin Exp $"); #endif #endif /* not lint */ @@ -79,9 +79,9 @@ __RCSID("$NetBSD: arp.c,v 1.55 2016/04/0 #include "prog_ops.h" static int is_llinfo(const struct sockaddr_dl *, int); -static int delete(const char *, const char *); +static int delete_one(struct rt_msghdr *); static void dump(uint32_t); -static void delete_all(void); +static void delete(const char *, const char *); static void sdl_print(const struct sockaddr_dl *); static int getifname(u_int16_t, char *, size_t); static int atosdl(const char *s, struct sockaddr_dl *sdl); @@ -90,13 +90,13 @@ static void get(const char *); static int getinetaddr(const char *, struct in_addr *); static int getsocket(void); static struct rt_msghdr * - rtmsg(const int, const int, const struct sockaddr_inarp *, - const struct sockaddr_dl *); + rtmsg(const int, const int, struct rt_msghdr *, + const struct sockaddr_inarp *, const struct sockaddr_dl *); static int set(int, char **); static void usage(void) __dead; static int aflag, nflag, vflag; -static struct sockaddr_in so_mask = { +static struct sockaddr_in so_mask = { .sin_len = 8, .sin_addr = { .s_addr = 0xffffffff @@ -157,11 +157,11 @@ main(int argc, char **argv) break; case 'd': if (aflag && argc == 0) - delete_all(); + delete(NULL, NULL); else { if (aflag || argc < 1 || argc > 2) usage(); - (void)delete(argv[0], argv[1]); + delete(argv[0], argv[1]); } break; case 's': @@ -206,7 +206,7 @@ file(const char *name) inputstring = line; for (ap = argv; ap < &argv[sizeof(argv) / sizeof(argv[0])] && (*ap = stresep(&inputstring, " \t", '\\')) != NULL;) { - if (**ap != '\0') + if (**ap != '\0') ap++; } i = ap - argv; @@ -257,7 +257,7 @@ getlink(const char *name, struct sockadd } /* - * Set an individual arp entry + * Set an individual arp entry */ static int set(int argc, char **argv) @@ -291,8 +291,8 @@ set(int argc, char **argv) flags |= RTF_ANNOUNCE; doing_proxy = 1; if (argc && strncmp(argv[1], "pro", 3) == 0) { - export_only = 1; - argc--; argv++; + export_only = 1; + argc--; argv++; } } else if (strncmp(argv[0], "trail", 5) == 0) { warnx("%s: Sending trailers is no longer supported", @@ -310,7 +310,7 @@ set(int argc, char **argv) } tryagain: - rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m); + rtm = rtmsg(s, RTM_GET, NULL, &sin_m, &sdl_m); if (rtm == NULL) { warn("%s", host); return (1); @@ -344,7 +344,7 @@ overwrite: sin_m.sin_other = 0; if (doing_proxy && export_only) sin_m.sin_other = SIN_PROXY; - rtm = rtmsg(s, RTM_ADD, &sin_m, &sdl_m); + rtm = rtmsg(s, RTM_ADD, NULL, &sin_m, &sdl_m); if (vflag) (void)printf("%s (%s) added\n", host, eaddr); return (rtm == NULL) ? 1 : 0; @@ -387,53 +387,24 @@ is_llinfo(const struct sockaddr_dl *sdl, } /* - * Delete an arp entry + * Delete an arp entry */ int -delete(const char *host, const char *info) +delete_one(struct rt_msghdr *rtm) { struct sockaddr_inarp *sina; struct sockaddr_dl *sdl; - struct rt_msghdr *rtm; - struct sockaddr_inarp sin_m = blank_sin; /* struct copy */ - struct sockaddr_dl sdl_m = blank_sdl; /* struct copy */ int s; s = getsocket(); - if (info && strncmp(info, "pro", 3) == 0) - sin_m.sin_other = SIN_PROXY; - if (getinetaddr(host, &sin_m.sin_addr) == -1) - return (1); -tryagain: - rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m); - if (rtm == NULL) { - warn("%s", host); - return (1); - } sina = (struct sockaddr_inarp *)(void *)(rtm + 1); sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(sina->sin_len) + (char *)(void *)sina); - if (sina->sin_addr.s_addr == sin_m.sin_addr.s_addr && - is_llinfo(sdl, rtm->rtm_flags)) - goto delete; - if (sin_m.sin_other & SIN_PROXY) { - warnx("delete: can't locate %s", host); - return (1); - } else { - sin_m.sin_other = SIN_PROXY; - goto tryagain; - } -delete: - if (sdl->sdl_family != AF_LINK) { - (void)warnx("cannot locate %s", host); + if (sdl->sdl_family != AF_LINK) return (1); - } - rtm = rtmsg(s, RTM_DELETE, &sin_m, sdl); + rtm = rtmsg(s, RTM_DELETE, rtm, sina, sdl); if (rtm == NULL) return (1); - if (vflag) - (void)printf("%s (%s) deleted\n", host, - inet_ntoa(sin_m.sin_addr)); return (0); } @@ -519,36 +490,56 @@ dump(uint32_t addr) * Delete the entire arp table */ void -delete_all(void) +delete(const char *host, const char *info) { int mib[6]; size_t needed; - char addr[sizeof("000.000.000.000\0")]; char *lim, *buf, *next; struct rt_msghdr *rtm; struct sockaddr_inarp *sina; + struct sockaddr_inarp sin_m = blank_sin; /* struct copy */ + + if (host != NULL) { + int ret = getinetaddr(host, &sin_m.sin_addr); + if (ret == -1) + return; + } + if (info && strncmp(info, "pro", 3) == 0) + sin_m.sin_other = SIN_PROXY; +retry: mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_FLAGS; - mib[5] = 0; + mib[5] = RTF_LLDATA; if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) err(1, "route-sysctl-estimate"); if (needed == 0) return; if ((buf = malloc(needed)) == NULL) err(1, "malloc"); - if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + if (errno == ENOBUFS) + goto retry; err(1, "actual retrieval of routing table"); + } lim = buf + needed; + for (next = buf; next < lim; next += rtm->rtm_msglen) { + int ret; rtm = (struct rt_msghdr *)(void *)next; sina = (struct sockaddr_inarp *)(void *)(rtm + 1); - (void)snprintf(addr, sizeof(addr), "%s", - inet_ntoa(sina->sin_addr)); - (void)delete(addr, NULL); + if (host != NULL && + sina->sin_addr.s_addr != sin_m.sin_addr.s_addr) + continue; + ret = delete_one(rtm); + if (vflag && ret == 0) { + (void)printf("%s (%s) deleted\n", host, + inet_ntoa(sina->sin_addr)); + } } free(buf); } @@ -572,13 +563,13 @@ atosdl(const char *ss, struct sockaddr_d int i; unsigned long b; char *endp; - char *p; + char *p; char *t, *r; p = LLADDR(sdl); endp = ((char *)(void *)sdl) + sdl->sdl_len; i = 0; - + b = strtoul(ss, &t, 16); if (b > 255 || t == ss) return 1; @@ -605,8 +596,8 @@ usage(void) progname = getprogname(); (void)fprintf(stderr, "Usage: %s [-n] hostname\n", progname); - (void)fprintf(stderr, " %s [-nv] -a\n", progname); - (void)fprintf(stderr, " %s [-v] -d [-a|hostname [pub [proxy]]]\n", + (void)fprintf(stderr, " %s [-nv] -a\n", progname); + (void)fprintf(stderr, " %s [-v] -d [-a|hostname [pub [proxy]]]\n", progname); (void)fprintf(stderr, " %s -s hostname ether_addr [temp] [pub [proxy]]\n", progname); @@ -615,11 +606,11 @@ usage(void) } static struct rt_msghdr * -rtmsg(const int s, const int cmd, const struct sockaddr_inarp *sin, - const struct sockaddr_dl *sdl) +rtmsg(const int s, const int cmd, struct rt_msghdr *_rtm, + const struct sockaddr_inarp *sin, const struct sockaddr_dl *sdl) { static int seq; - struct rt_msghdr *rtm; + struct rt_msghdr *rtm = _rtm; char *cp; int l; static struct { @@ -628,16 +619,16 @@ rtmsg(const int s, const int cmd, const } m_rtmsg; pid_t pid; - rtm = &m_rtmsg.m_rtm; - cp = m_rtmsg.m_space; errno = 0; - - /* XXX depends on rtm is filled by RTM_GET */ - if (cmd == RTM_DELETE) { - rtm->rtm_flags |= RTF_LLDATA; + if (rtm != NULL) { + memcpy(&m_rtmsg, rtm, rtm->rtm_msglen); + rtm = &m_rtmsg.m_rtm; goto doit; } (void)memset(&m_rtmsg, 0, sizeof(m_rtmsg)); + rtm = &m_rtmsg.m_rtm; + cp = m_rtmsg.m_space; + rtm->rtm_flags = flags; rtm->rtm_version = RTM_VERSION; @@ -660,7 +651,7 @@ rtmsg(const int s, const int cmd, const break; case RTM_GET: rtm->rtm_flags |= RTF_LLDATA; - rtm->rtm_addrs |= RTA_DST | RTA_IFP; + rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY; } #define NEXTADDR(w, s) \ @@ -725,7 +716,7 @@ getifname(u_int16_t ifindex, char *ifnam } for (addr = ifaddrs; addr; addr = addr->ifa_next) { - if (addr->ifa_addr == NULL || + if (addr->ifa_addr == NULL || addr->ifa_addr->sa_family != AF_LINK) continue; Index: src/usr.sbin/ndp/ndp.c diff -u src/usr.sbin/ndp/ndp.c:1.48 src/usr.sbin/ndp/ndp.c:1.48.6.1 --- src/usr.sbin/ndp/ndp.c:1.48 Mon Sep 19 19:13:14 2016 +++ src/usr.sbin/ndp/ndp.c Fri Jul 7 13:57:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ndp.c,v 1.48 2016/09/19 19:13:14 christos Exp $ */ +/* $NetBSD: ndp.c,v 1.48.6.1 2017/07/07 13:57:26 martin Exp $ */ /* $KAME: ndp.c,v 1.121 2005/07/13 11:30:13 keiichi Exp $ */ /* @@ -122,13 +122,14 @@ static char ifix_buf[IFNAMSIZ]; /* if_i static void getsocket(void); static int set(int, char **); static void get(char *); -static int delete(char *); -static void dump(struct in6_addr *, int); +static int delete(struct rt_msghdr *, char *); +static void delete_one(char *); +static void do_foreach(struct in6_addr *, char *, int); static struct in6_nbrinfo *getnbrinfo(struct in6_addr *, unsigned int, int); static char *ether_str(struct sockaddr_dl *); static int ndp_ether_aton(char *, u_char *); __dead static void usage(void); -static int rtmsg(int); +static int rtmsg(int, struct rt_msghdr *); static void ifinfo(char *, int, char **); static void rtrlist(void); static void plist(void); @@ -144,6 +145,9 @@ static const char *sec2str(time_t); static char *ether_str(struct sockaddr_dl *); static void ts_print(const struct timeval *); +#define NDP_F_CLEAR 1 +#define NDP_F_DELETE 2 + #ifdef ICMPV6CTL_ND6_DRLIST static const char *rtpref_str[] = { "medium", /* 00 */ @@ -223,14 +227,14 @@ main(int argc, char **argv) usage(); /*NOTREACHED*/ } - dump(0, mode == 'c'); + do_foreach(0, NULL, mode == 'c' ? NDP_F_CLEAR : 0); break; case 'd': if (argc != 0) { usage(); /*NOTREACHED*/ } - (void)delete(arg); + delete_one(arg); break; case 'I': #ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ @@ -386,7 +390,7 @@ set(int argc, char **argv) flags |= RTF_ANNOUNCE; argv++; } - if (rtmsg(RTM_GET) < 0) { + if (rtmsg(RTM_GET, NULL) < 0) { errx(1, "RTM_GET(%s) failed", host); /* NOTREACHED */ } @@ -415,7 +419,7 @@ overwrite: } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; - return (rtmsg(RTM_ADD)); + return (rtmsg(RTM_ADD, NULL)); } /* @@ -437,7 +441,7 @@ get(char *host) return; } makeaddr(mysin, res->ai_addr); - dump(&mysin->sin6_addr, 0); + do_foreach(&mysin->sin6_addr, host, 0); if (found_entry == 0) { (void)getnameinfo((struct sockaddr *)(void *)mysin, (socklen_t)mysin->sin6_len, @@ -447,52 +451,44 @@ get(char *host) } } -/* - * Delete a neighbor cache entry - */ -static int -delete(char *host) +static void +delete_one(char *host) { struct sockaddr_in6 *mysin = &sin_m; - register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; - struct sockaddr_dl *sdl; struct addrinfo hints, *res; int gai_error; - getsocket(); sin_m = blank_sin; - - bzero(&hints, sizeof(hints)); + (void)memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; gai_error = getaddrinfo(host, NULL, &hints, &res); if (gai_error) { warnx("%s: %s", host, gai_strerror(gai_error)); - return 1; + return; } makeaddr(mysin, res->ai_addr); - if (rtmsg(RTM_GET) < 0) - errx(1, "RTM_GET(%s) failed", host); + do_foreach(&mysin->sin6_addr, host, NDP_F_DELETE); +} + +/* + * Delete a neighbor cache entry + */ +static int +delete(struct rt_msghdr *rtm, char *host) +{ + struct sockaddr_in6 *mysin = &sin_m; + struct sockaddr_dl *sdl; + + getsocket(); mysin = (struct sockaddr_in6 *)(void *)(rtm + 1); sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(mysin->sin6_len) + (char *)(void *)mysin); - if (IN6_ARE_ADDR_EQUAL(&mysin->sin6_addr, &sin_m.sin6_addr)) { - if (sdl->sdl_family == AF_LINK && - !(rtm->rtm_flags & RTF_GATEWAY)) { - goto delete; - } - /* - * IPv4 arp command retries with sin_other = SIN_PROXY here. - */ - warnx("delete: cannot delete non-NDP entry"); - return 1; - } -delete: if (sdl->sdl_family != AF_LINK) { (void)printf("cannot locate %s\n", host); return (1); } - if (rtmsg(RTM_DELETE) == 0) { + if (rtmsg(RTM_DELETE, rtm) == 0) { struct sockaddr_in6 s6 = *mysin; /* XXX: for safety */ mysin->sin6_scope_id = 0; @@ -512,10 +508,13 @@ delete: #define W_IF 6 /* - * Dump the entire neighbor cache + * Iterate on neighbor caches and do + * - dump all caches, + * - clear all caches (NDP_F_CLEAR) or + * - remove matched caches (NDP_F_DELETE) */ static void -dump(struct in6_addr *addr, int cflag) +do_foreach(struct in6_addr *addr, char *host, int _flags) { int mib[6]; size_t needed; @@ -530,6 +529,8 @@ dump(struct in6_addr *addr, int cflag) int ifwidth; char flgbuf[8], *fl; const char *ifname; + int cflag = _flags == NDP_F_CLEAR; + int dflag = _flags == NDP_F_DELETE; /* Print header */ if (!tflag && !cflag) @@ -543,14 +544,18 @@ again:; mib[2] = 0; mib[3] = AF_INET6; mib[4] = NET_RT_FLAGS; - mib[5] = 0; + mib[5] = RTF_LLDATA; if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) err(1, "sysctl(PF_ROUTE estimate)"); if (needed > 0) { if ((buf = malloc(needed)) == NULL) err(1, "malloc"); - if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + if (errno == ENOBUFS) + goto again; err(1, "sysctl(PF_ROUTE, NET_RT_FLAGS)"); + } lim = buf + needed; } else buf = lim = NULL; @@ -587,6 +592,10 @@ again:; found_entry = 1; } else if (IN6_IS_ADDR_MULTICAST(&mysin->sin6_addr)) continue; + if (dflag) { + (void)delete(rtm, host_buf); + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&mysin->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&mysin->sin6_addr)) { uint16_t scopeid = mysin->sin6_scope_id; @@ -600,8 +609,13 @@ again:; host_buf, sizeof(host_buf), NULL, 0, (nflag ? NI_NUMERICHOST : 0)); if (cflag) { + /* Restore scopeid */ + if (IN6_IS_ADDR_LINKLOCAL(&mysin->sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&mysin->sin6_addr)) + inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL| + INET6_IS_ADDR_MC_LINKLOCAL); if ((rtm->rtm_flags & RTF_STATIC) == 0) - (void)delete(host_buf); + (void)delete(rtm, host_buf); continue; } (void)gettimeofday(&tim, 0); @@ -776,19 +790,21 @@ usage(void) } static int -rtmsg(int cmd) +rtmsg(int cmd, struct rt_msghdr *_rtm) { static int seq; - register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; + register struct rt_msghdr *rtm = _rtm; register char *cp = m_rtmsg.m_space; register int l; errno = 0; - if (cmd == RTM_DELETE) { - rtm->rtm_flags |= RTF_LLDATA; + if (rtm != NULL) { + memcpy(&m_rtmsg, rtm, rtm->rtm_msglen); + rtm = &m_rtmsg.m_rtm; goto doit; } (void)memset(&m_rtmsg, 0, sizeof(m_rtmsg)); + rtm = &m_rtmsg.m_rtm; rtm->rtm_flags = flags; rtm->rtm_version = RTM_VERSION; @@ -813,7 +829,7 @@ rtmsg(int cmd) break; case RTM_GET: rtm->rtm_flags |= RTF_LLDATA; - rtm->rtm_addrs |= RTA_DST | RTA_IFP; + rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY; } #define NEXTADDR(w, s) \ if (rtm->rtm_addrs & (w)) { \