1*90b80121SDavid van Moolenbroek /* $NetBSD: af_inet6.c,v 1.33 2015/05/12 14:05:29 roy Exp $ */
2*90b80121SDavid van Moolenbroek
3*90b80121SDavid van Moolenbroek /*
4*90b80121SDavid van Moolenbroek * Copyright (c) 1983, 1993
5*90b80121SDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
6*90b80121SDavid van Moolenbroek *
7*90b80121SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*90b80121SDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*90b80121SDavid van Moolenbroek * are met:
10*90b80121SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*90b80121SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*90b80121SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
13*90b80121SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
14*90b80121SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
15*90b80121SDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
16*90b80121SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
17*90b80121SDavid van Moolenbroek * without specific prior written permission.
18*90b80121SDavid van Moolenbroek *
19*90b80121SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*90b80121SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*90b80121SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*90b80121SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*90b80121SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*90b80121SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*90b80121SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*90b80121SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*90b80121SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*90b80121SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*90b80121SDavid van Moolenbroek * SUCH DAMAGE.
30*90b80121SDavid van Moolenbroek */
31*90b80121SDavid van Moolenbroek
32*90b80121SDavid van Moolenbroek #include <sys/cdefs.h>
33*90b80121SDavid van Moolenbroek #ifndef lint
34*90b80121SDavid van Moolenbroek __RCSID("$NetBSD: af_inet6.c,v 1.33 2015/05/12 14:05:29 roy Exp $");
35*90b80121SDavid van Moolenbroek #endif /* not lint */
36*90b80121SDavid van Moolenbroek
37*90b80121SDavid van Moolenbroek #include <sys/param.h>
38*90b80121SDavid van Moolenbroek #include <sys/ioctl.h>
39*90b80121SDavid van Moolenbroek #include <sys/socket.h>
40*90b80121SDavid van Moolenbroek
41*90b80121SDavid van Moolenbroek #include <net/if.h>
42*90b80121SDavid van Moolenbroek #include <netinet/in.h>
43*90b80121SDavid van Moolenbroek #include <netinet/in_var.h>
44*90b80121SDavid van Moolenbroek #include <netinet6/nd6.h>
45*90b80121SDavid van Moolenbroek
46*90b80121SDavid van Moolenbroek #include <err.h>
47*90b80121SDavid van Moolenbroek #include <errno.h>
48*90b80121SDavid van Moolenbroek #include <ifaddrs.h>
49*90b80121SDavid van Moolenbroek #include <netdb.h>
50*90b80121SDavid van Moolenbroek #include <string.h>
51*90b80121SDavid van Moolenbroek #include <stdlib.h>
52*90b80121SDavid van Moolenbroek #include <stdio.h>
53*90b80121SDavid van Moolenbroek #include <util.h>
54*90b80121SDavid van Moolenbroek
55*90b80121SDavid van Moolenbroek #include "env.h"
56*90b80121SDavid van Moolenbroek #include "extern.h"
57*90b80121SDavid van Moolenbroek #include "parse.h"
58*90b80121SDavid van Moolenbroek #include "extern.h"
59*90b80121SDavid van Moolenbroek #include "af_inetany.h"
60*90b80121SDavid van Moolenbroek #include "prog_ops.h"
61*90b80121SDavid van Moolenbroek
62*90b80121SDavid van Moolenbroek static void in6_constructor(void) __attribute__((constructor));
63*90b80121SDavid van Moolenbroek static void in6_alias(const char *, prop_dictionary_t, prop_dictionary_t,
64*90b80121SDavid van Moolenbroek struct in6_ifreq *);
65*90b80121SDavid van Moolenbroek static void in6_commit_address(prop_dictionary_t, prop_dictionary_t);
66*90b80121SDavid van Moolenbroek
67*90b80121SDavid van Moolenbroek static int setia6eui64_impl(prop_dictionary_t, struct in6_aliasreq *);
68*90b80121SDavid van Moolenbroek static int setia6flags_impl(prop_dictionary_t, struct in6_aliasreq *);
69*90b80121SDavid van Moolenbroek static int setia6pltime_impl(prop_dictionary_t, struct in6_aliasreq *);
70*90b80121SDavid van Moolenbroek static int setia6vltime_impl(prop_dictionary_t, struct in6_aliasreq *);
71*90b80121SDavid van Moolenbroek
72*90b80121SDavid van Moolenbroek static int setia6lifetime(prop_dictionary_t, int64_t, time_t *, uint32_t *);
73*90b80121SDavid van Moolenbroek
74*90b80121SDavid van Moolenbroek static void in6_status(prop_dictionary_t, prop_dictionary_t, bool);
75*90b80121SDavid van Moolenbroek static bool in6_addr_tentative(struct ifaddrs *ifa);
76*90b80121SDavid van Moolenbroek
77*90b80121SDavid van Moolenbroek static struct usage_func usage;
78*90b80121SDavid van Moolenbroek static cmdloop_branch_t branch[2];
79*90b80121SDavid van Moolenbroek
80*90b80121SDavid van Moolenbroek static const struct kwinst ia6flagskw[] = {
81*90b80121SDavid van Moolenbroek IFKW("anycast", IN6_IFF_ANYCAST)
82*90b80121SDavid van Moolenbroek , IFKW("deprecated", IN6_IFF_DEPRECATED)
83*90b80121SDavid van Moolenbroek };
84*90b80121SDavid van Moolenbroek
85*90b80121SDavid van Moolenbroek static struct pinteger parse_pltime = PINTEGER_INITIALIZER(&parse_pltime,
86*90b80121SDavid van Moolenbroek "pltime", 0, NULL, "pltime", &command_root.pb_parser);
87*90b80121SDavid van Moolenbroek
88*90b80121SDavid van Moolenbroek static struct pinteger parse_vltime = PINTEGER_INITIALIZER(&parse_vltime,
89*90b80121SDavid van Moolenbroek "vltime", 0, NULL, "vltime", &command_root.pb_parser);
90*90b80121SDavid van Moolenbroek
91*90b80121SDavid van Moolenbroek static const struct kwinst inet6kw[] = {
92*90b80121SDavid van Moolenbroek {.k_word = "pltime", .k_nextparser = &parse_pltime.pi_parser}
93*90b80121SDavid van Moolenbroek , {.k_word = "vltime", .k_nextparser = &parse_vltime.pi_parser}
94*90b80121SDavid van Moolenbroek , {.k_word = "eui64", .k_key = "eui64", .k_type = KW_T_BOOL,
95*90b80121SDavid van Moolenbroek .k_bool = true, .k_nextparser = &command_root.pb_parser}
96*90b80121SDavid van Moolenbroek };
97*90b80121SDavid van Moolenbroek
98*90b80121SDavid van Moolenbroek struct pkw ia6flags = PKW_INITIALIZER(&ia6flags, "ia6flags", NULL,
99*90b80121SDavid van Moolenbroek "ia6flag", ia6flagskw, __arraycount(ia6flagskw), &command_root.pb_parser);
100*90b80121SDavid van Moolenbroek struct pkw inet6 = PKW_INITIALIZER(&inet6, "IPv6 keywords", NULL,
101*90b80121SDavid van Moolenbroek NULL, inet6kw, __arraycount(inet6kw), NULL);
102*90b80121SDavid van Moolenbroek
103*90b80121SDavid van Moolenbroek static struct afswtch in6af = {
104*90b80121SDavid van Moolenbroek .af_name = "inet6", .af_af = AF_INET6, .af_status = in6_status,
105*90b80121SDavid van Moolenbroek .af_addr_commit = in6_commit_address,
106*90b80121SDavid van Moolenbroek .af_addr_tentative = in6_addr_tentative
107*90b80121SDavid van Moolenbroek };
108*90b80121SDavid van Moolenbroek
109*90b80121SDavid van Moolenbroek static int
prefix(void * val,int size)110*90b80121SDavid van Moolenbroek prefix(void *val, int size)
111*90b80121SDavid van Moolenbroek {
112*90b80121SDavid van Moolenbroek u_char *pname = (u_char *)val;
113*90b80121SDavid van Moolenbroek int byte, bit, plen = 0;
114*90b80121SDavid van Moolenbroek
115*90b80121SDavid van Moolenbroek for (byte = 0; byte < size; byte++, plen += 8)
116*90b80121SDavid van Moolenbroek if (pname[byte] != 0xff)
117*90b80121SDavid van Moolenbroek break;
118*90b80121SDavid van Moolenbroek if (byte == size)
119*90b80121SDavid van Moolenbroek return (plen);
120*90b80121SDavid van Moolenbroek for (bit = 7; bit != 0; bit--, plen++)
121*90b80121SDavid van Moolenbroek if (!(pname[byte] & (1 << bit)))
122*90b80121SDavid van Moolenbroek break;
123*90b80121SDavid van Moolenbroek for (; bit != 0; bit--)
124*90b80121SDavid van Moolenbroek if (pname[byte] & (1 << bit))
125*90b80121SDavid van Moolenbroek return(0);
126*90b80121SDavid van Moolenbroek byte++;
127*90b80121SDavid van Moolenbroek for (; byte < size; byte++)
128*90b80121SDavid van Moolenbroek if (pname[byte])
129*90b80121SDavid van Moolenbroek return(0);
130*90b80121SDavid van Moolenbroek return (plen);
131*90b80121SDavid van Moolenbroek }
132*90b80121SDavid van Moolenbroek
133*90b80121SDavid van Moolenbroek int
setia6flags_impl(prop_dictionary_t env,struct in6_aliasreq * ifra)134*90b80121SDavid van Moolenbroek setia6flags_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
135*90b80121SDavid van Moolenbroek {
136*90b80121SDavid van Moolenbroek int64_t ia6flag;
137*90b80121SDavid van Moolenbroek
138*90b80121SDavid van Moolenbroek if (!prop_dictionary_get_int64(env, "ia6flag", &ia6flag)) {
139*90b80121SDavid van Moolenbroek errno = ENOENT;
140*90b80121SDavid van Moolenbroek return -1;
141*90b80121SDavid van Moolenbroek }
142*90b80121SDavid van Moolenbroek
143*90b80121SDavid van Moolenbroek if (ia6flag < 0) {
144*90b80121SDavid van Moolenbroek ia6flag = -ia6flag;
145*90b80121SDavid van Moolenbroek ifra->ifra_flags &= ~ia6flag;
146*90b80121SDavid van Moolenbroek } else
147*90b80121SDavid van Moolenbroek ifra->ifra_flags |= ia6flag;
148*90b80121SDavid van Moolenbroek return 0;
149*90b80121SDavid van Moolenbroek }
150*90b80121SDavid van Moolenbroek
151*90b80121SDavid van Moolenbroek int
setia6pltime_impl(prop_dictionary_t env,struct in6_aliasreq * ifra)152*90b80121SDavid van Moolenbroek setia6pltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
153*90b80121SDavid van Moolenbroek {
154*90b80121SDavid van Moolenbroek int64_t pltime;
155*90b80121SDavid van Moolenbroek
156*90b80121SDavid van Moolenbroek if (!prop_dictionary_get_int64(env, "pltime", &pltime)) {
157*90b80121SDavid van Moolenbroek errno = ENOENT;
158*90b80121SDavid van Moolenbroek return -1;
159*90b80121SDavid van Moolenbroek }
160*90b80121SDavid van Moolenbroek
161*90b80121SDavid van Moolenbroek return setia6lifetime(env, pltime,
162*90b80121SDavid van Moolenbroek &ifra->ifra_lifetime.ia6t_preferred,
163*90b80121SDavid van Moolenbroek &ifra->ifra_lifetime.ia6t_pltime);
164*90b80121SDavid van Moolenbroek }
165*90b80121SDavid van Moolenbroek
166*90b80121SDavid van Moolenbroek int
setia6vltime_impl(prop_dictionary_t env,struct in6_aliasreq * ifra)167*90b80121SDavid van Moolenbroek setia6vltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
168*90b80121SDavid van Moolenbroek {
169*90b80121SDavid van Moolenbroek int64_t vltime;
170*90b80121SDavid van Moolenbroek
171*90b80121SDavid van Moolenbroek if (!prop_dictionary_get_int64(env, "vltime", &vltime)) {
172*90b80121SDavid van Moolenbroek errno = ENOENT;
173*90b80121SDavid van Moolenbroek return -1;
174*90b80121SDavid van Moolenbroek }
175*90b80121SDavid van Moolenbroek
176*90b80121SDavid van Moolenbroek return setia6lifetime(env, vltime,
177*90b80121SDavid van Moolenbroek &ifra->ifra_lifetime.ia6t_expire,
178*90b80121SDavid van Moolenbroek &ifra->ifra_lifetime.ia6t_vltime);
179*90b80121SDavid van Moolenbroek }
180*90b80121SDavid van Moolenbroek
181*90b80121SDavid van Moolenbroek static int
setia6lifetime(prop_dictionary_t env,int64_t val,time_t * timep,uint32_t * ivalp)182*90b80121SDavid van Moolenbroek setia6lifetime(prop_dictionary_t env, int64_t val, time_t *timep,
183*90b80121SDavid van Moolenbroek uint32_t *ivalp)
184*90b80121SDavid van Moolenbroek {
185*90b80121SDavid van Moolenbroek time_t t;
186*90b80121SDavid van Moolenbroek int af;
187*90b80121SDavid van Moolenbroek
188*90b80121SDavid van Moolenbroek if ((af = getaf(env)) == -1 || af != AF_INET6) {
189*90b80121SDavid van Moolenbroek errx(EXIT_FAILURE,
190*90b80121SDavid van Moolenbroek "inet6 address lifetime not allowed for the AF");
191*90b80121SDavid van Moolenbroek }
192*90b80121SDavid van Moolenbroek
193*90b80121SDavid van Moolenbroek t = time(NULL);
194*90b80121SDavid van Moolenbroek *timep = t + val;
195*90b80121SDavid van Moolenbroek *ivalp = val;
196*90b80121SDavid van Moolenbroek return 0;
197*90b80121SDavid van Moolenbroek }
198*90b80121SDavid van Moolenbroek
199*90b80121SDavid van Moolenbroek int
setia6eui64_impl(prop_dictionary_t env,struct in6_aliasreq * ifra)200*90b80121SDavid van Moolenbroek setia6eui64_impl(prop_dictionary_t env, struct in6_aliasreq *ifra)
201*90b80121SDavid van Moolenbroek {
202*90b80121SDavid van Moolenbroek char buf[2][80];
203*90b80121SDavid van Moolenbroek struct ifaddrs *ifap, *ifa;
204*90b80121SDavid van Moolenbroek const struct sockaddr_in6 *sin6 = NULL;
205*90b80121SDavid van Moolenbroek const struct in6_addr *lladdr = NULL;
206*90b80121SDavid van Moolenbroek struct in6_addr *in6;
207*90b80121SDavid van Moolenbroek const char *ifname;
208*90b80121SDavid van Moolenbroek bool doit = false;
209*90b80121SDavid van Moolenbroek int af;
210*90b80121SDavid van Moolenbroek
211*90b80121SDavid van Moolenbroek if (!prop_dictionary_get_bool(env, "eui64", &doit) || !doit) {
212*90b80121SDavid van Moolenbroek errno = ENOENT;
213*90b80121SDavid van Moolenbroek return -1;
214*90b80121SDavid van Moolenbroek }
215*90b80121SDavid van Moolenbroek
216*90b80121SDavid van Moolenbroek if ((ifname = getifname(env)) == NULL)
217*90b80121SDavid van Moolenbroek return -1;
218*90b80121SDavid van Moolenbroek
219*90b80121SDavid van Moolenbroek af = getaf(env);
220*90b80121SDavid van Moolenbroek if (af != AF_INET6) {
221*90b80121SDavid van Moolenbroek errx(EXIT_FAILURE,
222*90b80121SDavid van Moolenbroek "eui64 address modifier not allowed for the AF");
223*90b80121SDavid van Moolenbroek }
224*90b80121SDavid van Moolenbroek in6 = &ifra->ifra_addr.sin6_addr;
225*90b80121SDavid van Moolenbroek if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) {
226*90b80121SDavid van Moolenbroek union {
227*90b80121SDavid van Moolenbroek struct sockaddr_in6 sin6;
228*90b80121SDavid van Moolenbroek struct sockaddr sa;
229*90b80121SDavid van Moolenbroek } any = {.sin6 = {.sin6_family = AF_INET6}};
230*90b80121SDavid van Moolenbroek memcpy(&any.sin6.sin6_addr, &in6addr_any,
231*90b80121SDavid van Moolenbroek sizeof(any.sin6.sin6_addr));
232*90b80121SDavid van Moolenbroek (void)sockaddr_snprintf(buf[0], sizeof(buf[0]), "%a%%S",
233*90b80121SDavid van Moolenbroek &any.sa);
234*90b80121SDavid van Moolenbroek (void)sockaddr_snprintf(buf[1], sizeof(buf[1]), "%a%%S",
235*90b80121SDavid van Moolenbroek (const struct sockaddr *)&ifra->ifra_addr);
236*90b80121SDavid van Moolenbroek errx(EXIT_FAILURE, "interface index is already filled, %s | %s",
237*90b80121SDavid van Moolenbroek buf[0], buf[1]);
238*90b80121SDavid van Moolenbroek }
239*90b80121SDavid van Moolenbroek if (getifaddrs(&ifap) != 0)
240*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "getifaddrs");
241*90b80121SDavid van Moolenbroek for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
242*90b80121SDavid van Moolenbroek if (ifa->ifa_addr->sa_family == AF_INET6 &&
243*90b80121SDavid van Moolenbroek strcmp(ifa->ifa_name, ifname) == 0) {
244*90b80121SDavid van Moolenbroek sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
245*90b80121SDavid van Moolenbroek if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
246*90b80121SDavid van Moolenbroek lladdr = &sin6->sin6_addr;
247*90b80121SDavid van Moolenbroek break;
248*90b80121SDavid van Moolenbroek }
249*90b80121SDavid van Moolenbroek }
250*90b80121SDavid van Moolenbroek }
251*90b80121SDavid van Moolenbroek if (lladdr == NULL)
252*90b80121SDavid van Moolenbroek errx(EXIT_FAILURE, "could not determine link local address");
253*90b80121SDavid van Moolenbroek
254*90b80121SDavid van Moolenbroek memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
255*90b80121SDavid van Moolenbroek
256*90b80121SDavid van Moolenbroek freeifaddrs(ifap);
257*90b80121SDavid van Moolenbroek return 0;
258*90b80121SDavid van Moolenbroek }
259*90b80121SDavid van Moolenbroek
260*90b80121SDavid van Moolenbroek /* XXX not really an alias */
261*90b80121SDavid van Moolenbroek void
in6_alias(const char * ifname,prop_dictionary_t env,prop_dictionary_t oenv,struct in6_ifreq * creq)262*90b80121SDavid van Moolenbroek in6_alias(const char *ifname, prop_dictionary_t env, prop_dictionary_t oenv,
263*90b80121SDavid van Moolenbroek struct in6_ifreq *creq)
264*90b80121SDavid van Moolenbroek {
265*90b80121SDavid van Moolenbroek struct in6_ifreq ifr6;
266*90b80121SDavid van Moolenbroek struct sockaddr_in6 *sin6;
267*90b80121SDavid van Moolenbroek char hbuf[NI_MAXHOST];
268*90b80121SDavid van Moolenbroek u_int32_t scopeid;
269*90b80121SDavid van Moolenbroek int s;
270*90b80121SDavid van Moolenbroek const int niflag = Nflag ? 0 : NI_NUMERICHOST;
271*90b80121SDavid van Moolenbroek unsigned short flags;
272*90b80121SDavid van Moolenbroek
273*90b80121SDavid van Moolenbroek /* Get the non-alias address for this interface. */
274*90b80121SDavid van Moolenbroek if ((s = getsock(AF_INET6)) == -1) {
275*90b80121SDavid van Moolenbroek if (errno == EAFNOSUPPORT)
276*90b80121SDavid van Moolenbroek return;
277*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "socket");
278*90b80121SDavid van Moolenbroek }
279*90b80121SDavid van Moolenbroek
280*90b80121SDavid van Moolenbroek sin6 = &creq->ifr_addr;
281*90b80121SDavid van Moolenbroek
282*90b80121SDavid van Moolenbroek inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL);
283*90b80121SDavid van Moolenbroek scopeid = sin6->sin6_scope_id;
284*90b80121SDavid van Moolenbroek if (getnameinfo((const struct sockaddr *)sin6, sin6->sin6_len,
285*90b80121SDavid van Moolenbroek hbuf, sizeof(hbuf), NULL, 0, niflag))
286*90b80121SDavid van Moolenbroek strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
287*90b80121SDavid van Moolenbroek printf("\tinet6 %s", hbuf);
288*90b80121SDavid van Moolenbroek
289*90b80121SDavid van Moolenbroek if (getifflags(env, oenv, &flags) == -1)
290*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "%s: getifflags", __func__);
291*90b80121SDavid van Moolenbroek
292*90b80121SDavid van Moolenbroek if (flags & IFF_POINTOPOINT) {
293*90b80121SDavid van Moolenbroek ifr6 = *creq;
294*90b80121SDavid van Moolenbroek if (prog_ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) {
295*90b80121SDavid van Moolenbroek if (errno != EADDRNOTAVAIL)
296*90b80121SDavid van Moolenbroek warn("SIOCGIFDSTADDR_IN6");
297*90b80121SDavid van Moolenbroek memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr));
298*90b80121SDavid van Moolenbroek ifr6.ifr_addr.sin6_family = AF_INET6;
299*90b80121SDavid van Moolenbroek ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
300*90b80121SDavid van Moolenbroek }
301*90b80121SDavid van Moolenbroek sin6 = &ifr6.ifr_addr;
302*90b80121SDavid van Moolenbroek inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL);
303*90b80121SDavid van Moolenbroek hbuf[0] = '\0';
304*90b80121SDavid van Moolenbroek if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
305*90b80121SDavid van Moolenbroek hbuf, sizeof(hbuf), NULL, 0, niflag))
306*90b80121SDavid van Moolenbroek strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
307*90b80121SDavid van Moolenbroek printf(" -> %s", hbuf);
308*90b80121SDavid van Moolenbroek }
309*90b80121SDavid van Moolenbroek
310*90b80121SDavid van Moolenbroek ifr6 = *creq;
311*90b80121SDavid van Moolenbroek if (prog_ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) {
312*90b80121SDavid van Moolenbroek if (errno != EADDRNOTAVAIL)
313*90b80121SDavid van Moolenbroek warn("SIOCGIFNETMASK_IN6");
314*90b80121SDavid van Moolenbroek } else {
315*90b80121SDavid van Moolenbroek sin6 = &ifr6.ifr_addr;
316*90b80121SDavid van Moolenbroek printf(" prefixlen %d", prefix(&sin6->sin6_addr,
317*90b80121SDavid van Moolenbroek sizeof(struct in6_addr)));
318*90b80121SDavid van Moolenbroek }
319*90b80121SDavid van Moolenbroek
320*90b80121SDavid van Moolenbroek ifr6 = *creq;
321*90b80121SDavid van Moolenbroek if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
322*90b80121SDavid van Moolenbroek if (errno != EADDRNOTAVAIL)
323*90b80121SDavid van Moolenbroek warn("SIOCGIFAFLAG_IN6");
324*90b80121SDavid van Moolenbroek } else {
325*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
326*90b80121SDavid van Moolenbroek printf(" anycast");
327*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
328*90b80121SDavid van Moolenbroek printf(" tentative");
329*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED)
330*90b80121SDavid van Moolenbroek printf(" duplicated");
331*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED)
332*90b80121SDavid van Moolenbroek printf(" detached");
333*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
334*90b80121SDavid van Moolenbroek printf(" deprecated");
335*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF)
336*90b80121SDavid van Moolenbroek printf(" autoconf");
337*90b80121SDavid van Moolenbroek if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY)
338*90b80121SDavid van Moolenbroek printf(" temporary");
339*90b80121SDavid van Moolenbroek }
340*90b80121SDavid van Moolenbroek
341*90b80121SDavid van Moolenbroek if (scopeid)
342*90b80121SDavid van Moolenbroek printf(" scopeid 0x%x", scopeid);
343*90b80121SDavid van Moolenbroek
344*90b80121SDavid van Moolenbroek if (get_flag('L')) {
345*90b80121SDavid van Moolenbroek struct in6_addrlifetime *lifetime;
346*90b80121SDavid van Moolenbroek ifr6 = *creq;
347*90b80121SDavid van Moolenbroek lifetime = &ifr6.ifr_ifru.ifru_lifetime;
348*90b80121SDavid van Moolenbroek if (prog_ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) {
349*90b80121SDavid van Moolenbroek if (errno != EADDRNOTAVAIL)
350*90b80121SDavid van Moolenbroek warn("SIOCGIFALIFETIME_IN6");
351*90b80121SDavid van Moolenbroek } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
352*90b80121SDavid van Moolenbroek time_t t = time(NULL);
353*90b80121SDavid van Moolenbroek printf(" pltime ");
354*90b80121SDavid van Moolenbroek if (lifetime->ia6t_preferred) {
355*90b80121SDavid van Moolenbroek printf("%lu",
356*90b80121SDavid van Moolenbroek (unsigned long)(lifetime->ia6t_preferred -
357*90b80121SDavid van Moolenbroek MIN(t, lifetime->ia6t_preferred)));
358*90b80121SDavid van Moolenbroek } else
359*90b80121SDavid van Moolenbroek printf("infty");
360*90b80121SDavid van Moolenbroek
361*90b80121SDavid van Moolenbroek printf(" vltime ");
362*90b80121SDavid van Moolenbroek if (lifetime->ia6t_expire) {
363*90b80121SDavid van Moolenbroek printf("%lu",
364*90b80121SDavid van Moolenbroek (unsigned long)(lifetime->ia6t_expire -
365*90b80121SDavid van Moolenbroek MIN(t, lifetime->ia6t_expire)));
366*90b80121SDavid van Moolenbroek } else
367*90b80121SDavid van Moolenbroek printf("infty");
368*90b80121SDavid van Moolenbroek }
369*90b80121SDavid van Moolenbroek }
370*90b80121SDavid van Moolenbroek }
371*90b80121SDavid van Moolenbroek
372*90b80121SDavid van Moolenbroek static void
in6_status(prop_dictionary_t env,prop_dictionary_t oenv,bool force)373*90b80121SDavid van Moolenbroek in6_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
374*90b80121SDavid van Moolenbroek {
375*90b80121SDavid van Moolenbroek struct ifaddrs *ifap, *ifa;
376*90b80121SDavid van Moolenbroek struct in6_ifreq ifr;
377*90b80121SDavid van Moolenbroek const char *ifname;
378*90b80121SDavid van Moolenbroek bool printprefs = false;
379*90b80121SDavid van Moolenbroek
380*90b80121SDavid van Moolenbroek if ((ifname = getifname(env)) == NULL)
381*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "%s: getifname", __func__);
382*90b80121SDavid van Moolenbroek
383*90b80121SDavid van Moolenbroek if (getifaddrs(&ifap) != 0)
384*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "getifaddrs");
385*90b80121SDavid van Moolenbroek printprefs = ifa_any_preferences(ifname, ifap, AF_INET6);
386*90b80121SDavid van Moolenbroek for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
387*90b80121SDavid van Moolenbroek if (strcmp(ifname, ifa->ifa_name) != 0)
388*90b80121SDavid van Moolenbroek continue;
389*90b80121SDavid van Moolenbroek if (ifa->ifa_addr->sa_family != AF_INET6)
390*90b80121SDavid van Moolenbroek continue;
391*90b80121SDavid van Moolenbroek if (sizeof(ifr.ifr_addr) < ifa->ifa_addr->sa_len)
392*90b80121SDavid van Moolenbroek continue;
393*90b80121SDavid van Moolenbroek
394*90b80121SDavid van Moolenbroek memset(&ifr, 0, sizeof(ifr));
395*90b80121SDavid van Moolenbroek estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
396*90b80121SDavid van Moolenbroek memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
397*90b80121SDavid van Moolenbroek in6_alias(ifname, env, oenv, &ifr);
398*90b80121SDavid van Moolenbroek if (printprefs)
399*90b80121SDavid van Moolenbroek ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
400*90b80121SDavid van Moolenbroek printf("\n");
401*90b80121SDavid van Moolenbroek }
402*90b80121SDavid van Moolenbroek freeifaddrs(ifap);
403*90b80121SDavid van Moolenbroek }
404*90b80121SDavid van Moolenbroek
405*90b80121SDavid van Moolenbroek static int
in6_pre_aifaddr(prop_dictionary_t env,const struct afparam * param)406*90b80121SDavid van Moolenbroek in6_pre_aifaddr(prop_dictionary_t env, const struct afparam *param)
407*90b80121SDavid van Moolenbroek {
408*90b80121SDavid van Moolenbroek struct in6_aliasreq *ifra = param->req.buf;
409*90b80121SDavid van Moolenbroek
410*90b80121SDavid van Moolenbroek setia6eui64_impl(env, ifra);
411*90b80121SDavid van Moolenbroek setia6vltime_impl(env, ifra);
412*90b80121SDavid van Moolenbroek setia6pltime_impl(env, ifra);
413*90b80121SDavid van Moolenbroek setia6flags_impl(env, ifra);
414*90b80121SDavid van Moolenbroek inet6_putscopeid(&ifra->ifra_addr, INET6_IS_ADDR_LINKLOCAL);
415*90b80121SDavid van Moolenbroek inet6_putscopeid(&ifra->ifra_dstaddr, INET6_IS_ADDR_LINKLOCAL);
416*90b80121SDavid van Moolenbroek
417*90b80121SDavid van Moolenbroek return 0;
418*90b80121SDavid van Moolenbroek }
419*90b80121SDavid van Moolenbroek
420*90b80121SDavid van Moolenbroek static void
in6_commit_address(prop_dictionary_t env,prop_dictionary_t oenv)421*90b80121SDavid van Moolenbroek in6_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
422*90b80121SDavid van Moolenbroek {
423*90b80121SDavid van Moolenbroek struct in6_ifreq in6_ifr = {
424*90b80121SDavid van Moolenbroek .ifr_addr = {
425*90b80121SDavid van Moolenbroek .sin6_family = AF_INET6,
426*90b80121SDavid van Moolenbroek .sin6_len = sizeof(in6_ifr.ifr_addr),
427*90b80121SDavid van Moolenbroek .sin6_addr = {
428*90b80121SDavid van Moolenbroek .s6_addr =
429*90b80121SDavid van Moolenbroek {0xff, 0xff, 0xff, 0xff,
430*90b80121SDavid van Moolenbroek 0xff, 0xff, 0xff, 0xff}
431*90b80121SDavid van Moolenbroek }
432*90b80121SDavid van Moolenbroek }
433*90b80121SDavid van Moolenbroek };
434*90b80121SDavid van Moolenbroek static struct sockaddr_in6 in6_defmask = {
435*90b80121SDavid van Moolenbroek .sin6_family = AF_INET6,
436*90b80121SDavid van Moolenbroek .sin6_len = sizeof(in6_defmask),
437*90b80121SDavid van Moolenbroek .sin6_addr = {
438*90b80121SDavid van Moolenbroek .s6_addr = {0xff, 0xff, 0xff, 0xff,
439*90b80121SDavid van Moolenbroek 0xff, 0xff, 0xff, 0xff}
440*90b80121SDavid van Moolenbroek }
441*90b80121SDavid van Moolenbroek };
442*90b80121SDavid van Moolenbroek
443*90b80121SDavid van Moolenbroek struct in6_aliasreq in6_ifra = {
444*90b80121SDavid van Moolenbroek .ifra_prefixmask = {
445*90b80121SDavid van Moolenbroek .sin6_family = AF_INET6,
446*90b80121SDavid van Moolenbroek .sin6_len = sizeof(in6_ifra.ifra_prefixmask),
447*90b80121SDavid van Moolenbroek .sin6_addr = {
448*90b80121SDavid van Moolenbroek .s6_addr =
449*90b80121SDavid van Moolenbroek {0xff, 0xff, 0xff, 0xff,
450*90b80121SDavid van Moolenbroek 0xff, 0xff, 0xff, 0xff}}},
451*90b80121SDavid van Moolenbroek .ifra_lifetime = {
452*90b80121SDavid van Moolenbroek .ia6t_pltime = ND6_INFINITE_LIFETIME
453*90b80121SDavid van Moolenbroek , .ia6t_vltime = ND6_INFINITE_LIFETIME
454*90b80121SDavid van Moolenbroek }
455*90b80121SDavid van Moolenbroek };
456*90b80121SDavid van Moolenbroek struct afparam in6param = {
457*90b80121SDavid van Moolenbroek .req = BUFPARAM(in6_ifra)
458*90b80121SDavid van Moolenbroek , .dgreq = BUFPARAM(in6_ifr)
459*90b80121SDavid van Moolenbroek , .name = {
460*90b80121SDavid van Moolenbroek {.buf = in6_ifr.ifr_name,
461*90b80121SDavid van Moolenbroek .buflen = sizeof(in6_ifr.ifr_name)},
462*90b80121SDavid van Moolenbroek {.buf = in6_ifra.ifra_name,
463*90b80121SDavid van Moolenbroek .buflen = sizeof(in6_ifra.ifra_name)}
464*90b80121SDavid van Moolenbroek }
465*90b80121SDavid van Moolenbroek , .dgaddr = BUFPARAM(in6_ifr.ifr_addr)
466*90b80121SDavid van Moolenbroek , .addr = BUFPARAM(in6_ifra.ifra_addr)
467*90b80121SDavid van Moolenbroek , .dst = BUFPARAM(in6_ifra.ifra_dstaddr)
468*90b80121SDavid van Moolenbroek , .brd = BUFPARAM(in6_ifra.ifra_broadaddr)
469*90b80121SDavid van Moolenbroek , .mask = BUFPARAM(in6_ifra.ifra_prefixmask)
470*90b80121SDavid van Moolenbroek , .aifaddr = IFADDR_PARAM(SIOCAIFADDR_IN6)
471*90b80121SDavid van Moolenbroek , .difaddr = IFADDR_PARAM(SIOCDIFADDR_IN6)
472*90b80121SDavid van Moolenbroek , .gifaddr = IFADDR_PARAM(SIOCGIFADDR_IN6)
473*90b80121SDavid van Moolenbroek , .defmask = BUFPARAM(in6_defmask)
474*90b80121SDavid van Moolenbroek , .pre_aifaddr = in6_pre_aifaddr
475*90b80121SDavid van Moolenbroek };
476*90b80121SDavid van Moolenbroek commit_address(env, oenv, &in6param);
477*90b80121SDavid van Moolenbroek }
478*90b80121SDavid van Moolenbroek
479*90b80121SDavid van Moolenbroek static bool
in6_addr_tentative(struct ifaddrs * ifa)480*90b80121SDavid van Moolenbroek in6_addr_tentative(struct ifaddrs *ifa)
481*90b80121SDavid van Moolenbroek {
482*90b80121SDavid van Moolenbroek int s;
483*90b80121SDavid van Moolenbroek struct in6_ifreq ifr;
484*90b80121SDavid van Moolenbroek
485*90b80121SDavid van Moolenbroek if ((s = getsock(AF_INET6)) == -1)
486*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "%s: getsock", __func__);
487*90b80121SDavid van Moolenbroek memset(&ifr, 0, sizeof(ifr));
488*90b80121SDavid van Moolenbroek strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
489*90b80121SDavid van Moolenbroek ifr.ifr_addr = *(struct sockaddr_in6 *)ifa->ifa_addr;
490*90b80121SDavid van Moolenbroek if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr) == -1)
491*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, "SIOCGIFAFLAG_IN6");
492*90b80121SDavid van Moolenbroek return ifr.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE ? true : false;
493*90b80121SDavid van Moolenbroek }
494*90b80121SDavid van Moolenbroek
495*90b80121SDavid van Moolenbroek static void
in6_usage(prop_dictionary_t env)496*90b80121SDavid van Moolenbroek in6_usage(prop_dictionary_t env)
497*90b80121SDavid van Moolenbroek {
498*90b80121SDavid van Moolenbroek fprintf(stderr,
499*90b80121SDavid van Moolenbroek "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n"
500*90b80121SDavid van Moolenbroek "\t[ pltime n ] [ vltime n ] "
501*90b80121SDavid van Moolenbroek "[ eui64 ]\n");
502*90b80121SDavid van Moolenbroek }
503*90b80121SDavid van Moolenbroek
504*90b80121SDavid van Moolenbroek static void
in6_constructor(void)505*90b80121SDavid van Moolenbroek in6_constructor(void)
506*90b80121SDavid van Moolenbroek {
507*90b80121SDavid van Moolenbroek if (register_flag('L') != 0)
508*90b80121SDavid van Moolenbroek err(EXIT_FAILURE, __func__);
509*90b80121SDavid van Moolenbroek register_family(&in6af);
510*90b80121SDavid van Moolenbroek usage_func_init(&usage, in6_usage);
511*90b80121SDavid van Moolenbroek register_usage(&usage);
512*90b80121SDavid van Moolenbroek cmdloop_branch_init(&branch[0], &ia6flags.pk_parser);
513*90b80121SDavid van Moolenbroek cmdloop_branch_init(&branch[1], &inet6.pk_parser);
514*90b80121SDavid van Moolenbroek register_cmdloop_branch(&branch[0]);
515*90b80121SDavid van Moolenbroek register_cmdloop_branch(&branch[1]);
516*90b80121SDavid van Moolenbroek }
517