Date: Fri, 12 Sep 2014 10:08:12 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r271460 - user/ae/inet6/tools/tools/ipv6sasdebug Message-ID: <201409121008.s8CA8CPW031776@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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@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@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@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409121008.s8CA8CPW031776>