1197138Shrs/* 2197138Shrs * Copyright (c) 2009 Hiroki Sato. All rights reserved. 3197138Shrs * 4197138Shrs * Redistribution and use in source and binary forms, with or without 5197138Shrs * modification, are permitted provided that the following conditions 6197138Shrs * are met: 7197138Shrs * 1. Redistributions of source code must retain the above copyright 8197138Shrs * notice, this list of conditions and the following disclaimer. 9197138Shrs * 2. Redistributions in binary form must reproduce the above copyright 10197138Shrs * notice, this list of conditions and the following disclaimer in the 11197138Shrs * documentation and/or other materials provided with the distribution. 12197138Shrs * 13197138Shrs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 14197138Shrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15197138Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16197138Shrs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 17197138Shrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18197138Shrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19197138Shrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20197138Shrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21197138Shrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22197138Shrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23197138Shrs * SUCH DAMAGE. 24197138Shrs */ 25197138Shrs 26197138Shrs#ifndef lint 27197138Shrsstatic const char rcsid[] = 28197138Shrs "$FreeBSD$"; 29197138Shrs#endif /* not lint */ 30197138Shrs 31197138Shrs#include <sys/param.h> 32197138Shrs#include <sys/ioctl.h> 33197138Shrs#include <sys/socket.h> 34197138Shrs#include <sys/sysctl.h> 35197138Shrs#include <net/if.h> 36197138Shrs#include <net/route.h> 37197138Shrs 38197138Shrs#include <err.h> 39197138Shrs#include <errno.h> 40197138Shrs#include <stdio.h> 41197138Shrs#include <stdlib.h> 42197138Shrs#include <string.h> 43197138Shrs#include <unistd.h> 44197138Shrs#include <ifaddrs.h> 45197138Shrs 46197138Shrs#include <arpa/inet.h> 47197138Shrs 48197138Shrs#include <netinet/in.h> 49197138Shrs#include <net/if_var.h> 50197138Shrs#include <netinet/in_var.h> 51197138Shrs#include <arpa/inet.h> 52197138Shrs#include <netdb.h> 53197138Shrs 54197138Shrs#include <netinet6/nd6.h> 55197138Shrs 56197138Shrs#include "ifconfig.h" 57197138Shrs 58197138Shrs#define MAX_SYSCTL_TRY 5 59198006Shrs#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ 60198006Shrs "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ 61245555Sume "\007NO_RADR\010NO_PREFER_IFACE\020DEFAULTIF" 62197138Shrs 63197138Shrsstatic int isnd6defif(int); 64197138Shrsvoid setnd6flags(const char *, int, int, const struct afswtch *); 65197138Shrsvoid setnd6defif(const char *, int, int, const struct afswtch *); 66222711Shrsvoid nd6_status(int); 67197138Shrs 68197138Shrsvoid 69197138Shrssetnd6flags(const char *dummyaddr __unused, 70197138Shrs int d, int s, 71197138Shrs const struct afswtch *afp) 72197138Shrs{ 73197138Shrs struct in6_ndireq nd; 74197138Shrs int error; 75197138Shrs 76197138Shrs memset(&nd, 0, sizeof(nd)); 77197138Shrs strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); 78197138Shrs error = ioctl(s, SIOCGIFINFO_IN6, &nd); 79197138Shrs if (error) { 80197138Shrs warn("ioctl(SIOCGIFINFO_IN6)"); 81197138Shrs return; 82197138Shrs } 83197138Shrs if (d < 0) 84197138Shrs nd.ndi.flags &= ~(-d); 85197138Shrs else 86197138Shrs nd.ndi.flags |= d; 87197138Shrs error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd); 88197138Shrs if (error) 89197138Shrs warn("ioctl(SIOCSIFINFO_IN6)"); 90197138Shrs} 91197138Shrs 92197138Shrsvoid 93197138Shrssetnd6defif(const char *dummyaddr __unused, 94197138Shrs int d, int s, 95197138Shrs const struct afswtch *afp) 96197138Shrs{ 97197138Shrs struct in6_ndifreq ndifreq; 98197138Shrs int ifindex; 99197138Shrs int error; 100197138Shrs 101197138Shrs memset(&ndifreq, 0, sizeof(ndifreq)); 102197138Shrs strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname)); 103197138Shrs 104197138Shrs if (d < 0) { 105197138Shrs if (isnd6defif(s)) { 106197138Shrs /* ifindex = 0 means to remove default if */ 107197138Shrs ifindex = 0; 108197138Shrs } else 109197138Shrs return; 110197138Shrs } else if ((ifindex = if_nametoindex(ndifreq.ifname)) == 0) { 111197138Shrs warn("if_nametoindex(%s)", ndifreq.ifname); 112197138Shrs return; 113197138Shrs } 114197138Shrs 115197138Shrs ndifreq.ifindex = ifindex; 116197138Shrs error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq); 117197138Shrs if (error) 118197138Shrs warn("ioctl(SIOCSDEFIFACE_IN6)"); 119197138Shrs} 120197138Shrs 121197138Shrsstatic int 122197138Shrsisnd6defif(int s) 123197138Shrs{ 124197138Shrs struct in6_ndifreq ndifreq; 125197138Shrs unsigned int ifindex; 126197138Shrs int error; 127197138Shrs 128197138Shrs memset(&ndifreq, 0, sizeof(ndifreq)); 129197138Shrs strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname)); 130197138Shrs 131197138Shrs ifindex = if_nametoindex(ndifreq.ifname); 132197138Shrs error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq); 133197138Shrs if (error) { 134197138Shrs warn("ioctl(SIOCGDEFIFACE_IN6)"); 135197138Shrs return (error); 136197138Shrs } 137197138Shrs return (ndifreq.ifindex == ifindex); 138197138Shrs} 139197138Shrs 140222711Shrsvoid 141197138Shrsnd6_status(int s) 142197138Shrs{ 143197138Shrs struct in6_ndireq nd; 144197138Shrs int s6; 145198006Shrs int error; 146222711Shrs int isdefif; 147197138Shrs 148197138Shrs memset(&nd, 0, sizeof(nd)); 149197138Shrs strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); 150197138Shrs if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 151253062Shrs if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) 152238872Shrs warn("socket(AF_INET6, SOCK_DGRAM)"); 153197138Shrs return; 154197138Shrs } 155197138Shrs error = ioctl(s6, SIOCGIFINFO_IN6, &nd); 156197138Shrs if (error) { 157238872Shrs if (errno != EPFNOSUPPORT) 158238872Shrs warn("ioctl(SIOCGIFINFO_IN6)"); 159197138Shrs close(s6); 160197138Shrs return; 161197138Shrs } 162197138Shrs isdefif = isnd6defif(s6); 163197138Shrs close(s6); 164197138Shrs if (nd.ndi.flags == 0 && !isdefif) 165197138Shrs return; 166198006Shrs printb("\tnd6 options", 167198006Shrs (unsigned int)(nd.ndi.flags | (isdefif << 15)), ND6BITS); 168198006Shrs putchar('\n'); 169197138Shrs} 170