11de7b4b8SPedro F. Giffuni /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 4a283298cSHiroki Sato * Copyright (c) 2009 Hiroki Sato. All rights reserved. 5a283298cSHiroki Sato * 6a283298cSHiroki Sato * Redistribution and use in source and binary forms, with or without 7a283298cSHiroki Sato * modification, are permitted provided that the following conditions 8a283298cSHiroki Sato * are met: 9a283298cSHiroki Sato * 1. Redistributions of source code must retain the above copyright 10a283298cSHiroki Sato * notice, this list of conditions and the following disclaimer. 11a283298cSHiroki Sato * 2. Redistributions in binary form must reproduce the above copyright 12a283298cSHiroki Sato * notice, this list of conditions and the following disclaimer in the 13a283298cSHiroki Sato * documentation and/or other materials provided with the distribution. 14a283298cSHiroki Sato * 15a283298cSHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 16a283298cSHiroki Sato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17a283298cSHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18a283298cSHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 19a283298cSHiroki Sato * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20a283298cSHiroki Sato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21a283298cSHiroki Sato * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a283298cSHiroki Sato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23a283298cSHiroki Sato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24a283298cSHiroki Sato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25a283298cSHiroki Sato * SUCH DAMAGE. 26a283298cSHiroki Sato */ 27a283298cSHiroki Sato 28a283298cSHiroki Sato #include <sys/param.h> 29a283298cSHiroki Sato #include <sys/ioctl.h> 30a283298cSHiroki Sato #include <sys/socket.h> 31a283298cSHiroki Sato #include <sys/sysctl.h> 32a283298cSHiroki Sato #include <net/if.h> 33a283298cSHiroki Sato #include <net/route.h> 34a283298cSHiroki Sato 35a283298cSHiroki Sato #include <err.h> 36a283298cSHiroki Sato #include <errno.h> 37a283298cSHiroki Sato #include <stdio.h> 38a283298cSHiroki Sato #include <stdlib.h> 39a283298cSHiroki Sato #include <string.h> 40a283298cSHiroki Sato #include <unistd.h> 41a283298cSHiroki Sato #include <ifaddrs.h> 42a283298cSHiroki Sato 43a283298cSHiroki Sato #include <arpa/inet.h> 44a283298cSHiroki Sato 45a283298cSHiroki Sato #include <netinet/in.h> 46a283298cSHiroki Sato #include <netinet/in_var.h> 47a283298cSHiroki Sato #include <arpa/inet.h> 48a283298cSHiroki Sato #include <netdb.h> 49a283298cSHiroki Sato 50a283298cSHiroki Sato #include <netinet6/nd6.h> 51a283298cSHiroki Sato 52a283298cSHiroki Sato #include "ifconfig.h" 53a283298cSHiroki Sato 54a283298cSHiroki Sato #define MAX_SYSCTL_TRY 5 55*a68e4f7aSGordon Tetlow static const char *ND6BITS[] = { 56*a68e4f7aSGordon Tetlow [0] = "PERFORMNUD", 57*a68e4f7aSGordon Tetlow [1] = "ACCEPT_RTADV", 58*a68e4f7aSGordon Tetlow [2] = "PREFER_SOURCE", 59*a68e4f7aSGordon Tetlow [3] = "IFDISABLED", 60*a68e4f7aSGordon Tetlow [4] = "DONT_SET_IFROUTE", 61*a68e4f7aSGordon Tetlow [5] = "AUTO_LINKLOCAL", 62*a68e4f7aSGordon Tetlow [6] = "NO_RADR", 63*a68e4f7aSGordon Tetlow [7] = "NO_PREFER_IFACE", 64*a68e4f7aSGordon Tetlow [8] = "NO_DAD", 65201100c5SBjoern A. Zeeb #ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG 66*a68e4f7aSGordon Tetlow [9] = "IPV6_ONLY", 67*a68e4f7aSGordon Tetlow [10] = "IPV6_ONLY_MANUAL", 68201100c5SBjoern A. Zeeb #endif 69*a68e4f7aSGordon Tetlow [15] = "DEFAULTIF", 70*a68e4f7aSGordon Tetlow }; 71a283298cSHiroki Sato 727fa282e6SAlexander V. Chernikov static int isnd6defif(if_ctx *ctx, int s); 736e3a9d7fSAlexander V. Chernikov void setnd6flags(if_ctx *, const char *, int); 746e3a9d7fSAlexander V. Chernikov void setnd6defif(if_ctx *,const char *, int); 756e3a9d7fSAlexander V. Chernikov void nd6_status(if_ctx *); 76a283298cSHiroki Sato 77a283298cSHiroki Sato void 786e3a9d7fSAlexander V. Chernikov setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d) 79a283298cSHiroki Sato { 807fa282e6SAlexander V. Chernikov struct in6_ndireq nd = {}; 81a283298cSHiroki Sato int error; 82a283298cSHiroki Sato 837fa282e6SAlexander V. Chernikov strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname)); 846e3a9d7fSAlexander V. Chernikov error = ioctl_ctx(ctx, SIOCGIFINFO_IN6, &nd); 85a283298cSHiroki Sato if (error) { 86a283298cSHiroki Sato warn("ioctl(SIOCGIFINFO_IN6)"); 87a283298cSHiroki Sato return; 88a283298cSHiroki Sato } 89a283298cSHiroki Sato if (d < 0) 90a283298cSHiroki Sato nd.ndi.flags &= ~(-d); 91a283298cSHiroki Sato else 92a283298cSHiroki Sato nd.ndi.flags |= d; 936e3a9d7fSAlexander V. Chernikov error = ioctl_ctx(ctx, SIOCSIFINFO_IN6, (caddr_t)&nd); 94a283298cSHiroki Sato if (error) 95a283298cSHiroki Sato warn("ioctl(SIOCSIFINFO_IN6)"); 96a283298cSHiroki Sato } 97a283298cSHiroki Sato 98a283298cSHiroki Sato void 996e3a9d7fSAlexander V. Chernikov setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d) 100a283298cSHiroki Sato { 1017fa282e6SAlexander V. Chernikov struct in6_ndifreq ndifreq = {}; 102a283298cSHiroki Sato int ifindex; 103a283298cSHiroki Sato int error; 104a283298cSHiroki Sato 1057fa282e6SAlexander V. Chernikov strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname)); 106a283298cSHiroki Sato 107a283298cSHiroki Sato if (d < 0) { 1087fa282e6SAlexander V. Chernikov if (isnd6defif(ctx, ctx->io_s)) { 109a283298cSHiroki Sato /* ifindex = 0 means to remove default if */ 110a283298cSHiroki Sato ifindex = 0; 111a283298cSHiroki Sato } else 112a283298cSHiroki Sato return; 113a283298cSHiroki Sato } else if ((ifindex = if_nametoindex(ndifreq.ifname)) == 0) { 114a283298cSHiroki Sato warn("if_nametoindex(%s)", ndifreq.ifname); 115a283298cSHiroki Sato return; 116a283298cSHiroki Sato } 117a283298cSHiroki Sato 118a283298cSHiroki Sato ndifreq.ifindex = ifindex; 1196e3a9d7fSAlexander V. Chernikov error = ioctl_ctx(ctx, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq); 120a283298cSHiroki Sato if (error) 121a283298cSHiroki Sato warn("ioctl(SIOCSDEFIFACE_IN6)"); 122a283298cSHiroki Sato } 123a283298cSHiroki Sato 124a283298cSHiroki Sato static int 1257fa282e6SAlexander V. Chernikov isnd6defif(if_ctx *ctx, int s) 126a283298cSHiroki Sato { 1277fa282e6SAlexander V. Chernikov struct in6_ndifreq ndifreq = {}; 128a283298cSHiroki Sato unsigned int ifindex; 129a283298cSHiroki Sato int error; 130a283298cSHiroki Sato 1317fa282e6SAlexander V. Chernikov strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname)); 132a283298cSHiroki Sato 133a283298cSHiroki Sato ifindex = if_nametoindex(ndifreq.ifname); 134a283298cSHiroki Sato error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq); 135a283298cSHiroki Sato if (error) { 136a283298cSHiroki Sato warn("ioctl(SIOCGDEFIFACE_IN6)"); 137a283298cSHiroki Sato return (error); 138a283298cSHiroki Sato } 139a283298cSHiroki Sato return (ndifreq.ifindex == ifindex); 140a283298cSHiroki Sato } 141a283298cSHiroki Sato 142c3cc3217SHiroki Sato void 1437fa282e6SAlexander V. Chernikov nd6_status(if_ctx *ctx) 144a283298cSHiroki Sato { 1457fa282e6SAlexander V. Chernikov struct in6_ndireq nd = {}; 146a283298cSHiroki Sato int s6; 1477590eb54SHiroki Sato int error; 148c3cc3217SHiroki Sato int isdefif; 149*a68e4f7aSGordon Tetlow uint32_t bits; 150a283298cSHiroki Sato 1517fa282e6SAlexander V. Chernikov strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname)); 152a283298cSHiroki Sato if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1534099f7e6SHiroki Sato if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) 154a283298cSHiroki Sato warn("socket(AF_INET6, SOCK_DGRAM)"); 155a283298cSHiroki Sato return; 156a283298cSHiroki Sato } 157a283298cSHiroki Sato error = ioctl(s6, SIOCGIFINFO_IN6, &nd); 158a283298cSHiroki Sato if (error) { 1598a3beec6SHiroki Sato if (errno != EPFNOSUPPORT) 160a283298cSHiroki Sato warn("ioctl(SIOCGIFINFO_IN6)"); 161a283298cSHiroki Sato close(s6); 162a283298cSHiroki Sato return; 163a283298cSHiroki Sato } 1647fa282e6SAlexander V. Chernikov isdefif = isnd6defif(ctx, s6); 165a283298cSHiroki Sato close(s6); 166a283298cSHiroki Sato if (nd.ndi.flags == 0 && !isdefif) 167a283298cSHiroki Sato return; 168*a68e4f7aSGordon Tetlow bits = (nd.ndi.flags | (isdefif << 15)); 169*a68e4f7aSGordon Tetlow printf("\tnd6 options=%x", bits); 170*a68e4f7aSGordon Tetlow print_bits("options", &bits, 1, ND6BITS, nitems(ND6BITS)); 1717590eb54SHiroki Sato putchar('\n'); 172a283298cSHiroki Sato } 173