svn commit: r271460 - user/ae/inet6/tools/tools/ipv6sasdebug
Andrey V. Elsukov
ae at FreeBSD.org
Fri Sep 12 10:08:13 UTC 2014
Author: ae
Date: Fri Sep 12 10:08:11 2014
New Revision: 271460
URL: http://svnweb.freebsd.org/changeset/base/271460
Log:
Add utility for debugging IPv6 source address selection algorithm.
It uses the kernel code and emulates algorithm with debug output.
Added:
user/ae/inet6/tools/tools/ipv6sasdebug/
user/ae/inet6/tools/tools/ipv6sasdebug/Makefile (contents, props changed)
user/ae/inet6/tools/tools/ipv6sasdebug/ctl.c (contents, props changed)
user/ae/inet6/tools/tools/ipv6sasdebug/main.c (contents, props changed)
user/ae/inet6/tools/tools/ipv6sasdebug/stub.c (contents, props changed)
user/ae/inet6/tools/tools/ipv6sasdebug/stub.h (contents, props changed)
Added: user/ae/inet6/tools/tools/ipv6sasdebug/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ae/inet6/tools/tools/ipv6sasdebug/Makefile Fri Sep 12 10:08:11 2014 (r271460)
@@ -0,0 +1,26 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../sys/netinet6
+
+BINDIR?= /usr/bin
+
+PROG= ipv6sasdebug
+MAN=
+
+SRCS= main.c stub.c ctl.c in6_src.c
+SRCS+= opt_inet.h opt_inet6.h opt_mpath.h
+CLEANFILES+= opt_inet.h opt_inet6.h opt_mpath.h
+
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -I${.CURDIR}/../../../sys
+
+opt_inet.h:
+ echo "#define INET 1" > opt_inet.h
+
+opt_inet6.h:
+ echo "#define INET6 1" > opt_inet6.h
+
+opt_mpath.h:
+ echo "#include \"stub.h\"" > opt_mpath.h
+
+.include <bsd.prog.mk>
Added: user/ae/inet6/tools/tools/ipv6sasdebug/ctl.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ae/inet6/tools/tools/ipv6sasdebug/ctl.c Fri Sep 12 10:08:11 2014 (r271460)
@@ -0,0 +1,263 @@
+/*-
+ * Copyright (c) 2014 Andrey V. Elsukov <ae at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+#define _WANT_RTENTRY
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_carp.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int sock6;
+extern int V_ip6_use_deprecated;
+extern int V_ip6_prefer_tempaddr;
+extern int V_ip6_defhlim;
+extern int in6_mask2len(struct in6_addr *, u_char *);
+extern struct ifnet* ifnet_byname(const char *name);
+static struct carpreq carp[CARP_MAXVHID];
+static int has_carp = 0;
+
+void
+ifnet_getcarpstatus(const char *name)
+{
+ struct ifreq req;
+
+ if (has_carp)
+ return;
+ memset(&req, 0, sizeof(req));
+ memset(carp, 0, sizeof(struct carpreq) * CARP_MAXVHID);
+ strncpy(req.ifr_name, name, sizeof(req.ifr_name));
+ req.ifr_ifru.ifru_data = (caddr_t)carp;
+ carp[0].carpr_count = CARP_MAXVHID;
+ if (ioctl(sock6, SIOCGVH, &req) < 0)
+ return;
+ has_carp = 1;
+}
+
+int
+carp_master(uint8_t vhid)
+{
+ int i;
+
+ if (has_carp == 0)
+ return (0);
+ for (i = 0; i < carp[0].carpr_count; i++)
+ if (carp[i].carpr_vhid == vhid)
+ return (carp[i].carpr_state == CARP_MAXSTATE);
+ return (0);
+}
+
+int
+ifnet_getflags(const char *name, struct sockaddr_in6 *addr)
+{
+ struct ifreq req;
+
+ memset(&req, 0, sizeof(req));
+ strncpy(req.ifr_name, name, sizeof(req.ifr_name));
+ if (ioctl(sock6, SIOCGIFFLAGS, &req) < 0)
+ err(EXIT_FAILURE, "ioctl(SIOCGIFFLAGS)");
+ return ((req.ifr_flags & 0xffff) | (req.ifr_flagshigh << 16));
+}
+
+void
+ifnet_getndinfo(const char *name, uint32_t *linkmtu, uint32_t *maxmtu,
+ uint32_t *flags, uint8_t *chlim)
+{
+ struct in6_ndireq req;
+
+ strncpy(req.ifname, name, sizeof(req.ifname));
+ if (ioctl(sock6, SIOCGIFINFO_IN6, &req) < 0)
+ err(EXIT_FAILURE, "ioctl(SIOCGIFINFO_IN6)");
+ *linkmtu = req.ndi.linkmtu;
+ *maxmtu = req.ndi.maxmtu;
+ *flags = req.ndi.flags;
+ *chlim = req.ndi.chlim;
+}
+
+int
+addr_getflags(const char *name, struct sockaddr_in6 *addr)
+{
+ struct in6_ifreq req;
+
+ strncpy(req.ifr_name, name, sizeof(req.ifr_name));
+ req.ifr_ifru.ifru_addr = *addr;
+ if (ioctl(sock6, SIOCGIFAFLAG_IN6, &req) < 0)
+ err(EXIT_FAILURE, "ioctl(SIOCGIFAFLAG_IN6)");
+ return (req.ifr_ifru.ifru_flags6);
+}
+
+void
+addr_getlifetime(const char *name, struct sockaddr_in6 *addr,
+ struct in6_addrlifetime *lt)
+{
+ struct in6_ifreq req;
+
+ strncpy(req.ifr_name, name, sizeof(req.ifr_name));
+ req.ifr_ifru.ifru_addr = *addr;
+ if (ioctl(sock6, SIOCGIFALIFETIME_IN6, &req) < 0)
+ err(EXIT_FAILURE, "ioctl(SIOCGIFALIFETIME_IN6)");
+ *lt = req.ifr_ifru.ifru_lifetime;
+}
+
+void
+v_getsysctl(void)
+{
+ size_t len;
+
+ len = sizeof(V_ip6_use_deprecated);
+ if (sysctlbyname("net.inet6.ip6.use_deprecated",
+ &V_ip6_use_deprecated, &len, NULL, 0) == -1)
+ err(EXIT_FAILURE, "net.inet6.ip6.use_deprecated");
+
+ len = sizeof(V_ip6_prefer_tempaddr);
+ if (sysctlbyname("net.inet6.ip6.prefer_tempaddr",
+ &V_ip6_prefer_tempaddr, &len, NULL, 0) == -1)
+ err(EXIT_FAILURE, "net.inet6.ip6.prefer_tempaddr");
+
+ len = sizeof(V_ip6_defhlim);
+ if (sysctlbyname("net.inet6.ip6.hlim",
+ &V_ip6_defhlim, &len, NULL, 0) == -1)
+ err(EXIT_FAILURE, "net.inet6.ip6.hlim");
+}
+
+void
+addrsel_policy_populate(int add(struct in6_addrpolicy *), int debug)
+{
+ struct in6_addrpolicy *pp, *p;
+ size_t len;
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ char buf[NI_MAXHOST + IFNAMSIZ + 10];
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) < 0)
+ err(EXIT_FAILURE, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ if ((pp = malloc(len)) == NULL)
+ err(EXIT_FAILURE, "malloc");
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), pp, &len, NULL, 0) < 0)
+ err(EXIT_FAILURE, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ if (debug)
+ printf("\nIPv6 address selection policy table:\n"
+ "%-30s %5s %5s %8s\n", "Prefix", "Prec", "Label", "Use");
+ for (p = pp; p < pp + len/sizeof(*p); p++) {
+ add(p);
+ if (debug) {
+ if (getnameinfo((struct sockaddr *)&p->addr,
+ sizeof(p->addr), buf, sizeof(buf), NULL, 0,
+ NI_NUMERICHOST) != 0)
+ continue;
+ snprintf(buf, sizeof(buf), "%s/%d", buf,
+ in6_mask2len(&p->addrmask.sin6_addr, NULL));
+ printf("%-30s %5d %5d %8llu\n", buf, p->preced,
+ p->label, (unsigned long long)p->use);
+ }
+ }
+ free(pp);
+}
+
+struct {
+ struct rt_msghdr m_rtm;
+ char m_space[512];
+} m_rtmsg;
+
+void
+in6_rtalloc(struct route_in6 *ro, u_int fibnum)
+{
+ static int seq = 0;
+ struct rtentry *rt;
+ struct sockaddr_dl *ifp;
+ struct sockaddr_in6 *sa6;
+ char *cp = m_rtmsg.m_space;
+ pid_t pid;
+ int i, l, s;
+
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0)
+ err(EXIT_FAILURE, "socket(PF_ROUTE)");
+ memset(&m_rtmsg, 0, sizeof(m_rtmsg));
+
+#define rtm m_rtmsg.m_rtm
+ rtm.rtm_type = RTM_GET;
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_seq = ++seq;
+ rtm.rtm_addrs = RTA_DST | RTA_IFP;
+
+ sa6 = (struct sockaddr_in6 *)cp;
+ *sa6 = ro->ro_dst;
+ rtm.rtm_msglen = sizeof(m_rtmsg.m_rtm) + SA_SIZE(sa6);
+ l = write(s, (char *)&m_rtmsg, rtm.rtm_msglen);
+ if (l < 0)
+ err(EXIT_FAILURE, "write()");
+ pid = getpid();
+ do {
+ l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+ } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
+ if (l < 0)
+ err(EXIT_FAILURE, "read()");
+ close(s);
+ ro->ro_rt = NULL;
+ if (rtm.rtm_errno != 0 || (rtm.rtm_addrs &
+ (RTA_GATEWAY | RTA_IFP)) != (RTA_GATEWAY | RTA_IFP))
+ return;
+ for (i = 1; i < RTA_IFP; i <<= 1) {
+ if ((i & rtm.rtm_addrs) == 0)
+ continue;
+ if (i == RTA_GATEWAY)
+ sa6 = (struct sockaddr_in6 *)cp;
+ cp += SA_SIZE(cp);
+ }
+ ifp = (struct sockaddr_dl *)cp;
+ if (sa6->sin6_family != AF_INET6)
+ return;
+ if (ifp->sdl_family != AF_LINK ||
+ ifp->sdl_nlen == 0)
+ return;
+ ifp->sdl_data[ifp->sdl_nlen] = '\0';
+ if ((rt = calloc(1, sizeof(*rt))) == NULL)
+ return;
+ if ((rt->rt_gateway = calloc(1, sizeof(*sa6))) == NULL)
+ err(EXIT_FAILURE, "calloc()");
+ memcpy(rt->rt_gateway, sa6, sizeof(*sa6));
+ rt->rt_fibnum = fibnum;
+ rt->rt_ifp = ifnet_byname(ifp->sdl_data);
+ ro->ro_rt = rt;
+}
Added: user/ae/inet6/tools/tools/ipv6sasdebug/main.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ae/inet6/tools/tools/ipv6sasdebug/main.c Fri Sep 12 10:08:11 2014 (r271460)
@@ -0,0 +1,236 @@
+/*-
+ * Copyright (c) 2014 Andrey V. Elsukov <ae at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include "stub.h"
+
+static SLIST_HEAD(, ifnet) iflist = SLIST_HEAD_INITIALIZER(iflist);
+const struct sockaddr_in6 sa6_any = { sizeof(sa6_any), AF_INET6, 0, 0,
+ IN6ADDR_ANY_INIT, 0 };
+struct in6_ifaddrhead V_in6_ifaddrhead = TAILQ_HEAD_INITIALIZER(V_in6_ifaddrhead);
+int V_ip6_use_deprecated;
+int V_ip6_prefer_tempaddr;
+int V_ip6_defhlim;
+int sock6;
+
+const char *
+ip6_sprintf(char *buf, const struct in6_addr *addr)
+{
+
+ return (inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN));
+}
+
+struct ifnet*
+ifnet_byindex(uint32_t index)
+{
+ struct ifnet *ifp;
+
+ SLIST_FOREACH(ifp, &iflist, if_link)
+ if (ifp->if_index == index)
+ return (ifp);
+ return (NULL);
+}
+
+struct ifnet*
+ifnet_byname(const char *name)
+{
+ struct ifnet *ifp;
+
+ SLIST_FOREACH(ifp, &iflist, if_link)
+ if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0)
+ return (ifp);
+ ifp = calloc(1, sizeof(struct ifnet));
+ if (ifp == NULL)
+ return (NULL);
+ SLIST_INSERT_HEAD(&iflist, ifp, if_link);
+ TAILQ_INIT(&ifp->if_addrhead);
+ strlcpy(ifp->if_xname, name, IFNAMSIZ);
+ ifp->if_flags = ifnet_getflags(name);
+ ifp->if_index = if_nametoindex(name);
+ ifnet_getndinfo(name, &ifp->if_ndifinfo.linkmtu,
+ &ifp->if_ndifinfo.maxmtu, &ifp->if_ndifinfo.flags,
+ &ifp->if_ndifinfo.chlim);
+ ifnet_getcarpstatus(name);
+ return (ifp);
+}
+
+static void
+addr_add(char *name, struct ifaddrs *ifa)
+{
+ struct ifnet *ifp;
+ struct in6_ifaddr *ia;
+ struct sockaddr_in6 *addr;
+ struct if_data *ifd;
+
+ ifp = ifnet_byname(name);
+ if (ifp == NULL)
+ return;
+ addr = (struct sockaddr_in6 *)ifa->ifa_addr;
+ ia = calloc(1, sizeof(struct in6_ifaddr));
+ TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+ TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
+ ia->ia_ifp = ifp;
+ ia->ia_addr = *addr;
+ ia->ia6_flags = addr_getflags(name, addr);
+ if (ifa->ifa_data != NULL) {
+ ifd = ifa->ifa_data;
+ ia->ia_ifa.ifa_carp = ifd->ifi_vhid;
+ }
+ addr_getlifetime(name, addr, &ia->ia6_lifetime);
+}
+
+static int
+addrselpolicy_add(struct in6_addrpolicy *p)
+{
+
+ return (in6_src_ioctl(SIOCAADDRCTL_POLICY, (caddr_t)p));
+}
+
+static void
+debug_list(void)
+{
+ struct ifnet *ifp;
+ struct in6_ifaddr *ia;
+ struct ifaddr *ifa;
+ char buf[NI_MAXHOST + IFNAMSIZ + 1];
+
+ printf("List of IPv6 interfaces:\n");
+ SLIST_FOREACH(ifp, &iflist, if_link) {
+ printf("%s: <%04x>\n", ifp->if_xname, ifp->if_flags);
+ printf("\tlinkmtu %d, maxmtu %d, hlim %d, ND <%04x>\n",
+ ifp->if_ndifinfo.linkmtu, ifp->if_ndifinfo.maxmtu,
+ ifp->if_ndifinfo.chlim, ifp->if_ndifinfo.flags);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
+ printf("\tinet6 %s\n", ip6_sprintf(buf,
+ &((struct sockaddr_in6 *)
+ ifa->ifa_addr)->sin6_addr));
+ }
+ printf("\nList of IPv6 addresses:\n");
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ getnameinfo((struct sockaddr *)&ia->ia_addr, sizeof(ia->ia_addr),
+ buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
+ printf("%s <%04x>\n", buf, ia->ia6_flags);
+ }
+ printf("\nSysctl variables:\n");
+ printf("%s: %d\n", "net.inet6.ip6.use_deprecated", V_ip6_use_deprecated);
+ printf("%s: %d\n", "net.inet6.ip6.prefer_tempaddr", V_ip6_prefer_tempaddr);
+ printf("%s: %d\n", "net.inet6.ip6.hlim", V_ip6_defhlim);
+}
+
+static void
+usage(void)
+{
+
+ printf("ipv6sasdebug [-vh] <IPv6 destination address>\n");
+ printf("\t-v show collected information related to IPv6 SAS\n");
+ printf("\t-h show usage message\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct addrinfo hints, *res, *res0;
+ struct sockaddr_in6 dst;
+ struct in6_addr src;
+ struct ifaddrs *ifap, *ifa;
+ struct ifnet *ifp;
+ int debug, ch, error;
+ char buf[INET6_ADDRSTRLEN];
+
+ debug = 0;
+ while ((ch = getopt(argc, argv, ":vh")) != -1) {
+ switch (ch) {
+ case 'v':
+ debug = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(argv[0], NULL, &hints, &res0);
+ if (error != 0)
+ err(EXIT_FAILURE, "%s", gai_strerror(error));
+ for (res = res0; res; res = res->ai_next)
+ if (res->ai_addr->sa_family == AF_INET6) {
+ dst = *(struct sockaddr_in6 *)res->ai_addr;
+ break;
+ }
+ freeaddrinfo(res0);
+
+ v_getsysctl();
+ sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sock6 < 0)
+ err(EXIT_FAILURE, "socket");
+ if (getifaddrs(&ifap) != 0)
+ err(EXIT_FAILURE, "getifaddrs");
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ addr_add(ifa->ifa_name, ifa);
+ }
+ freeifaddrs(ifap);
+ close(sock6);
+
+ if (debug)
+ debug_list();
+ /* Populate the address selection policy table */
+ addrsel_policy_init();
+ addrsel_policy_populate(addrselpolicy_add, debug);
+
+ ifp = NULL;
+ error = in6_selectsrc(&dst, NULL, NULL, NULL, NULL, &ifp, &src);
+ if (error == 0) {
+ printf("\nin6_selectsrc returned %s address and %s"
+ " outgoing interface.\n", ip6_sprintf(buf, &src),
+ ifp->if_xname);
+ } else {
+ printf("in6_selectsrc() failed\n");
+ }
+ return (0);
+}
Added: user/ae/inet6/tools/tools/ipv6sasdebug/stub.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ae/inet6/tools/tools/ipv6sasdebug/stub.c Fri Sep 12 10:08:11 2014 (r271460)
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 2014 Andrey V. Elsukov <ae at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "stub.h"
+
+void
+ifa_free(void *ifa)
+{
+
+}
+
+void
+ifa_ref(void *ifa)
+{
+
+}
+
+int
+in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
+ struct ucred *cred, int lookupflags)
+{
+
+ return (EINVAL);
+}
+
+int
+in_pcbinshash(struct inpcb *inp)
+{
+
+ return (EINVAL);
+}
+
+int
+prison_local_ip6(struct ucred *cred, const struct sockaddr_in6 *ia6,
+ int v6only)
+{
+
+ return (EAFNOSUPPORT);
+}
+
+int
+prison_check_ip6(struct ucred *cred, const struct sockaddr_in6 *ia6)
+{
+
+ return (EAFNOSUPPORT);
+}
+
+int
+prison_saddrsel_ip6(struct ucred *cred, const struct sockaddr_in6 *ia6)
+{
+
+ return (EAFNOSUPPORT);
+}
+
+/* Copy from netinet6/in6.c */
+int
+in6_mask2len(struct in6_addr *mask, u_char *lim0)
+{
+ int x = 0, y;
+ u_char *lim = lim0, *p;
+
+ /* ignore the scope_id part */
+ if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
+ lim = (u_char *)mask + sizeof(*mask);
+ for (p = (u_char *)mask; p < lim; x++, p++) {
+ if (*p != 0xff)
+ break;
+ }
+ y = 0;
+ if (p < lim) {
+ for (y = 0; y < 8; y++) {
+ if ((*p & (0x80 >> y)) == 0)
+ break;
+ }
+ }
+
+ /*
+ * when the limit pointer is given, do a stricter check on the
+ * remaining bits.
+ */
+ if (p < lim) {
+ if (y != 0 && (*p & (0x00ff >> y)) != 0)
+ return (-1);
+ for (p = p + 1; p < lim; p++)
+ if (*p != 0)
+ return (-1);
+ }
+
+ return (x * 8 + y);
+}
+
+int
+in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
+{
+ int match = 0;
+ u_char *s = (u_char *)src, *d = (u_char *)dst;
+ u_char *lim = s + 16, r;
+
+ while (s < lim)
+ if ((r = (*d++ ^ *s++)) != 0) {
+ while (r < 128) {
+ match++;
+ r <<= 1;
+ }
+ break;
+ } else
+ match += 8;
+ return (match);
+}
+
+struct in6_ifaddr *
+in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
+{
+ struct in6_ifaddr *ia;
+
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) {
+ if (zoneid != 0 &&
+ zoneid != ia->ia_addr.sin6_scope_id)
+ continue;
+ break;
+ }
+ }
+ return (ia);
+}
+/* Copy from netinet6/scope6.c */
+struct ifnet*
+in6_getlinkifnet(uint32_t zoneid)
+{
+
+ return (ifnet_byindex(zoneid));
+}
+
+uint32_t
+in6_getscopezone(const struct ifnet *ifp, int scope)
+{
+
+ if (scope == __IPV6_ADDR_SCOPE_INTFACELOCAL ||
+ scope == __IPV6_ADDR_SCOPE_LINKLOCAL)
+ return (ifp->if_index);
+ return (0);
+}
+
+int
+in6_addrscope(const struct in6_addr *addr)
+{
+
+ if (IN6_IS_ADDR_MULTICAST(addr))
+ return (__IPV6_ADDR_MC_SCOPE(addr));
+ if (IN6_IS_ADDR_LINKLOCAL(addr) ||
+ IN6_IS_ADDR_LOOPBACK(addr))
+ return (__IPV6_ADDR_SCOPE_LINKLOCAL);
+ return (__IPV6_ADDR_SCOPE_GLOBAL);
+}
+
+int
+ifa_preferred(struct ifaddr *cur, struct ifaddr *next)
+{
+
+ return (cur->ifa_carp && (!next->ifa_carp ||
+ (carp_master(next->ifa_carp) && !carp_master(cur->ifa_carp))));
+}
+
+
Added: user/ae/inet6/tools/tools/ipv6sasdebug/stub.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ae/inet6/tools/tools/ipv6sasdebug/stub.h Fri Sep 12 10:08:11 2014 (r271460)
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 2014 Andrey V. Elsukov <ae at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/mutex.h>
+
+#define _SYS_SYSTM_H_
+#define _SYS_RMLOCK_H_
+#define _NET_IF_LLATBL_H_
+#define _NETINET_IN_VAR_H_
+#define _NETINET6_IN6_VAR_H_
+#define _NETINET6_ND6_H_
+#define _NET_IF_VAR_H_
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#define _WANT_RTENTRY
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* net/vnet.h */
+#define VNET_DEFINE(type, var) type var
+#define VNET(var) var
+#define IS_DEFAULT_VNET(v) 1
+
+/* netinet6/nd6.h */
+#define ND_IFINFO(ifp) (&(ifp)->if_ndifinfo)
+#define ND6_IFF_PERFORMNUD 0x1
+#define ND6_IFF_ACCEPT_RTADV 0x2
+#define ND6_IFF_IFDISABLED 0x8
+#define ND6_IFF_DONT_SET_IFROUTE 0x10
+#define ND6_IFF_AUTO_LINKLOCAL 0x20
+#define ND6_IFF_NO_RADR 0x40
+#define ND6_IFF_NO_PREFER_IFACE 0x80
+
+struct nd_ifinfo {
+ uint32_t linkmtu;
+ uint32_t maxmtu;
+ uint32_t flags;
+ uint8_t chlim;
+};
+
+/* net/if_var.h */
+TAILQ_HEAD(ifaddrhead, ifaddr);
+struct ifnet {
+ uint32_t if_index;
+ int if_flags;
+
+ char if_xname[IFNAMSIZ];
+ struct ifaddrhead if_addrhead;
+ struct nd_ifinfo if_ndifinfo;
+ SLIST_ENTRY(ifnet) if_link;
+};
+
+struct ifaddr {
+ struct sockaddr *ifa_addr;
+ struct ifnet *ifa_ifp;
+ uint8_t ifa_carp;
+ TAILQ_ENTRY(ifaddr) ifa_link;
+};
+
+/* netinet6/in6.h */
+#define IN6_IS_ADDR_MC_INTFACELOCAL IN6_IS_ADDR_MC_NODELOCAL
+#define IPV6_ADDR_SCOPE_LINKLOCAL __IPV6_ADDR_SCOPE_LINKLOCAL
+#define IFA6_IS_DEPRECATED(ia) \
+ ((ia)->ia6_lifetime.ia6t_preferred > (ia)->ia6_lifetime.ia6t_pltime)
+#define IFA6_IS_VALID(ia) \
+ ((ia)->ia6_lifetime.ia6t_expire > (ia)->ia6_lifetime.ia6t_vltime)
+#define s6_addr32 __u6_addr.__u6_addr32
+
+/* netinet6/in6_var.h */
+#define IN6_IFF_ANYCAST 0x01
+#define IN6_IFF_TENTATIVE 0x02
+#define IN6_IFF_DUPLICATED 0x04
+#define IN6_IFF_DETACHED 0x08
+#define IN6_IFF_DEPRECATED 0x10
+#define IN6_IFF_NODAD 0x20
+#define IN6_IFF_AUTOCONF 0x40
+#define IN6_IFF_TEMPORARY 0x80
+#define IN6_IFF_PREFER_SOURCE 0x0100
+#define IN6_IFF_NOPFX 0x8000
+#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
+#define IN6_MASK_ADDR(a, m) do { \
+ (a)->s6_addr32[0] &= (m)->s6_addr32[0]; \
+ (a)->s6_addr32[1] &= (m)->s6_addr32[1]; \
+ (a)->s6_addr32[2] &= (m)->s6_addr32[2]; \
+ (a)->s6_addr32[3] &= (m)->s6_addr32[3]; \
+} while (0)
+
+struct in6_addrlifetime {
+ time_t ia6t_expire; /* valid lifetime expiration time */
+ time_t ia6t_preferred; /* preferred lifetime expiration time */
+ u_int32_t ia6t_vltime; /* valid lifetime */
+ u_int32_t ia6t_pltime; /* prefix lifetime */
+};
+
+TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr);
+struct in6_ifaddr {
+ struct ifaddr ia_ifa;
+ TAILQ_ENTRY(in6_ifaddr) ia_link;
+ struct sockaddr_in6 ia_addr;
+ struct in6_addrlifetime ia6_lifetime;
+ int ia6_flags;
+#define ia_ifp ia_ifa.ifa_ifp
+};
+
+#define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr))
+#define IA6_SIN6(ia) (&((ia)->ia_addr))
+#define SIOCAADDRCTL_POLICY 0
+#define SIOCDADDRCTL_POLICY 1
+#define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b))
+#define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b))
+
+struct in6_addrpolicy {
+ struct sockaddr_in6 addr;
+ struct sockaddr_in6 addrmask;
+ int preced;
+ int label;
+ uint64_t use;
+};
+
+/* netinet6/ip6_var.h */
+#define IP6STAT_INC(c)
+
+struct ucred {
+};
+
+#define IPV6SASDEBUG(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
+#define KASSERT(exp, msg)
+#define RO_RTFREE(ro)
+#define RTFREE(rt)
+#define INP_LOCK_ASSERT(pcb)
+#define INP_WLOCK_ASSERT(pcb)
+#define IF_ADDR_RLOCK(ifp)
+#define IF_ADDR_RUNLOCK(ifp)
+#define IN6_IFADDR_RLOCK()
+#define IN6_IFADDR_RUNLOCK()
+#define SYSCTL_DECL(n)
+#define SYSCTL_NODE(n, i, m, f, h, d) int sysctl_ ## m
+#define SYSCTL_HANDLER_ARGS struct sysctl_req *req
+#define SYSCTL_OUT(r, p, l) 0
+struct sysctl_req {
+ void *oldptr;
+ size_t oldlen;
+ void *newptr;
+ size_t newlen;
+};
+
+#define rw_assert(l,w)
+
+#define mtx_init(m,n,t,o)
+#define mtx_lock(m)
+#define mtx_unlock(m)
+#define mtx_assert(m, f)
+
+#define sx_init(l, n)
+#define sx_slock(l)
+#define sx_sunlock(l)
+#define sx_xlock(l)
+#define sx_xunlock(l)
+
+#define malloc(sz, t, f) malloc((sz))
+#define free(p, t) free((p))
+
+struct ifnet *ifnet_byindex(uint32_t);
+int ifnet_getflags(const char *);
+void ifnet_getcarpstatus(const char *);
+void ifnet_getndinfo(const char *, uint32_t*, uint32_t*, uint32_t*, uint8_t*);
+int addr_getflags(const char *, struct sockaddr_in6 *);
+void addr_getlifetime(const char *, struct sockaddr_in6 *, struct in6_addrlifetime *);
+void v_getsysctl(void);
+int carp_master(uint8_t);
+
+void in6_rtalloc(struct route_in6 *, u_int);
+
+const char *ip6_sprintf(char *, const struct in6_addr *);
+struct in6_ifaddr *in6ifa_ifwithaddr(const struct in6_addr *, uint32_t);
+void ifa_free(void *);
+void ifa_ref(void *);
+
+int in6_addrscope(const struct in6_addr *);
+uint32_t in6_getscopezone(const struct ifnet *, int);
+int in6_matchlen(struct in6_addr *, struct in6_addr *);
+int in6_mask2len(struct in6_addr *, u_char *);
+int prison_check_ip6(struct ucred *, const struct sockaddr_in6 *);
+int prison_local_ip6(struct ucred *, const struct sockaddr_in6 *, int);
+int prison_saddrsel_ip6(struct ucred *, const struct sockaddr_in6 *);
+struct ifnet *in6_getlinkifnet(uint32_t);
+int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *, struct ucred *, int);
+int in_pcbinshash(struct inpcb *);
+int ifa_preferred(struct ifaddr *, struct ifaddr *);
+
+void addrsel_policy_init(void);
+void addrsel_policy_populate(int (struct in6_addrpolicy *), int);
+int in6_src_ioctl(u_long, caddr_t);
+int in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
+ struct inpcb *, struct route_in6 *, struct ucred *,
+ struct ifnet **, struct in6_addr *);
+extern int V_ip6_use_deprecated;
+extern int V_ip6_prefer_tempaddr;
+extern int V_ip6_defhlim;
+extern const struct sockaddr_in6 sa6_any;
+extern struct in6_ifaddrhead V_in6_ifaddrhead;
+extern int has_carp;
More information about the svn-src-user
mailing list