2 * Copyright (c) 2009-2017, 2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 1983, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 #include <sys/param.h>
60 #include <sys/ioctl.h>
61 #include <sys/socket.h>
72 #include <arpa/inet.h>
74 #include <netinet/in.h>
75 #include <net/if_var.h> /* for struct ifaddr */
76 #include <netinet/in_var.h>
77 #include <arpa/inet.h>
80 #include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
84 #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
85 "\004IFDISABLED\005DONT_SET_IFROUTE\006PROXY_PREFIXES" \
86 "\007IGNORE_NA\010INSECURE\011REPLICATED\012DAD"
88 static struct in6_ifreq in6_ridreq
;
89 static struct in6_aliasreq in6_addreq
=
95 { 0, 0, ND6_INFINITE_LIFETIME
, ND6_INFINITE_LIFETIME
} };
96 static int ip6lifetime
;
98 static void in6_fillscopeid(struct sockaddr_in6
*sin6
);
99 static int prefix(void *, int);
100 static char *sec2str(time_t);
101 static int explicit_prefix
= 0;
103 static char addr_buf
[MAXHOSTNAMELEN
*2 + 1]; /*for getnameinfo()*/
106 setifprefixlen(const char *addr
, int dummy __unused
, int s
,
107 const struct afswtch
*afp
)
109 if (afp
->af_getprefix
!= NULL
)
110 afp
->af_getprefix(addr
, MASK
);
115 setnd6flags(const char *dummyaddr __unused
, int d
, int s
,
116 const struct afswtch
*afp
)
118 struct in6_ndireq nd
;
121 memset(&nd
, 0, sizeof(nd
));
122 strlcpy(nd
.ifname
, ifr
.ifr_name
, sizeof(nd
.ifname
));
123 error
= ioctl(s
, SIOCGIFINFO_IN6
, &nd
);
125 warn("ioctl(SIOCGIFINFO_IN6)");
129 nd
.ndi
.flags
&= ~(-d
);
132 error
= ioctl(s
, SIOCSIFINFO_FLAGS
, (caddr_t
)&nd
);
134 warn("ioctl(SIOCSIFINFO_FLAGS)");
138 setip6flags(const char *dummyaddr __unused
, int flag
, int dummysoc __unused
,
139 const struct afswtch
*afp
)
141 if (afp
->af_af
!= AF_INET6
)
142 err(1, "address flags can be set only for inet6 addresses");
145 in6_addreq
.ifra_flags
&= ~(-flag
);
147 in6_addreq
.ifra_flags
|= flag
;
151 setip6lifetime(const char *cmd
, const char *val
, int s
,
152 const struct afswtch
*afp
)
158 newval
= (time_t)strtoul(val
, &ep
, 0);
160 errx(1, "invalid %s", cmd
);
161 if (afp
->af_af
!= AF_INET6
)
162 errx(1, "%s not allowed for the AF", cmd
);
163 if (strcmp(cmd
, "vltime") == 0) {
164 in6_addreq
.ifra_lifetime
.ia6t_expire
= t
+ newval
;
165 in6_addreq
.ifra_lifetime
.ia6t_vltime
= newval
;
166 } else if (strcmp(cmd
, "pltime") == 0) {
167 in6_addreq
.ifra_lifetime
.ia6t_preferred
= t
+ newval
;
168 in6_addreq
.ifra_lifetime
.ia6t_pltime
= newval
;
173 setip6pltime(const char *seconds
, int dummy __unused
, int s
,
174 const struct afswtch
*afp
)
176 setip6lifetime("pltime", seconds
, s
, afp
);
180 setip6vltime(const char *seconds
, int dummy __unused
, int s
,
181 const struct afswtch
*afp
)
183 setip6lifetime("vltime", seconds
, s
, afp
);
187 setip6eui64(const char *cmd
, int dummy __unused
, int s
,
188 const struct afswtch
*afp
)
190 struct ifaddrs
*ifap
, *ifa
;
191 const struct sockaddr_in6
*sin6
= NULL
;
192 const struct in6_addr
*lladdr
= NULL
;
193 struct in6_addr
*in6
;
195 if (afp
->af_af
!= AF_INET6
)
196 errx(EXIT_FAILURE
, "%s not allowed for the AF", cmd
);
197 in6
= (struct in6_addr
*)&in6_addreq
.ifra_addr
.sin6_addr
;
198 if (memcmp(&in6addr_any
.s6_addr
[8], &in6
->s6_addr
[8], 8) != 0)
199 errx(EXIT_FAILURE
, "interface index is already filled");
200 if (getifaddrs(&ifap
) != 0)
201 err(EXIT_FAILURE
, "getifaddrs");
202 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
203 if (ifa
->ifa_addr
->sa_family
== AF_INET6
&&
204 strcmp(ifa
->ifa_name
, name
) == 0) {
205 sin6
= (const struct sockaddr_in6
*)ifa
->ifa_addr
;
206 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
207 lladdr
= &sin6
->sin6_addr
;
213 errx(EXIT_FAILURE
, "could not determine link local address");
215 memcpy(&in6
->s6_addr
[8], &lladdr
->s6_addr
[8], 8);
221 in6_fillscopeid(struct sockaddr_in6
*sin6
)
223 #if defined(__KAME__) && defined(KAME_SCOPEID)
224 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
225 sin6
->sin6_scope_id
=
226 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
227 sin6
->sin6_addr
.s6_addr
[2] = sin6
->sin6_addr
.s6_addr
[3] = 0;
233 in6_status(int s __unused
, const struct ifaddrs
*ifa
)
235 struct sockaddr_in6
*sin
, null_sin
;
236 struct in6_ifreq ifr6
;
239 struct in6_addrlifetime lifetime
;
240 time_t t
= time(NULL
);
244 memset(&null_sin
, 0, sizeof(null_sin
));
246 sin
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
250 strlcpy(ifr6
.ifr_name
, ifr
.ifr_name
, sizeof(ifr
.ifr_name
));
251 if ((s6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
252 warn("socket(AF_INET6,SOCK_DGRAM)");
255 ifr6
.ifr_addr
= *sin
;
256 if (ioctl(s6
, SIOCGIFAFLAG_IN6
, &ifr6
) < 0) {
257 warn("ioctl(SIOCGIFAFLAG_IN6)");
261 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
262 memset(&lifetime
, 0, sizeof(lifetime
));
263 ifr6
.ifr_addr
= *sin
;
264 if (ioctl(s6
, SIOCGIFALIFETIME_IN6
, &ifr6
) < 0) {
265 warn("ioctl(SIOCGIFALIFETIME_IN6)");
269 lifetime
= ifr6
.ifr_ifru
.ifru_lifetime
;
272 /* XXX: embedded link local addr check */
273 if (IN6_IS_ADDR_LINKLOCAL(&sin
->sin6_addr
) &&
274 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] != 0) {
277 index
= *(u_short
*)&sin
->sin6_addr
.s6_addr
[2];
278 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] = 0;
279 if (sin
->sin6_scope_id
== 0)
280 sin
->sin6_scope_id
= ntohs(index
);
282 scopeid
= sin
->sin6_scope_id
;
284 error
= getnameinfo((struct sockaddr
*)sin
, sin
->sin6_len
, addr_buf
,
285 sizeof(addr_buf
), NULL
, 0, NI_NUMERICHOST
);
287 inet_ntop(AF_INET6
, &sin
->sin6_addr
, addr_buf
,
289 printf("\tinet6 %s ", addr_buf
);
291 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
292 sin
= (struct sockaddr_in6
*)ifa
->ifa_dstaddr
;
294 * some of the interfaces do not have valid destination
297 if (sin
!= NULL
&& sin
->sin6_family
== AF_INET6
) {
300 /* XXX: embedded link local addr check */
301 if (IN6_IS_ADDR_LINKLOCAL(&sin
->sin6_addr
) &&
302 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] != 0) {
305 index
= *(u_short
*)&sin
->sin6_addr
.s6_addr
[2];
306 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] = 0;
307 if (sin
->sin6_scope_id
== 0)
308 sin
->sin6_scope_id
= ntohs(index
);
311 error
= getnameinfo((struct sockaddr
*)sin
,
312 sin
->sin6_len
, addr_buf
,
313 sizeof(addr_buf
), NULL
, 0,
316 inet_ntop(AF_INET6
, &sin
->sin6_addr
, addr_buf
,
318 printf("--> %s ", addr_buf
);
322 sin
= (struct sockaddr_in6
*)ifa
->ifa_netmask
;
325 printf("prefixlen %d ", prefix(&sin
->sin6_addr
,
326 sizeof(struct in6_addr
)));
328 if ((flags6
& IN6_IFF_ANYCAST
) != 0)
330 if ((flags6
& IN6_IFF_TENTATIVE
) != 0)
331 printf("tentative ");
332 if ((flags6
& IN6_IFF_OPTIMISTIC
) != 0)
333 printf("optimistic ");
334 if ((flags6
& IN6_IFF_DUPLICATED
) != 0)
335 printf("duplicated ");
336 if ((flags6
& IN6_IFF_DETACHED
) != 0)
338 if ((flags6
& IN6_IFF_DEPRECATED
) != 0)
339 printf("deprecated ");
340 if ((flags6
& IN6_IFF_AUTOCONF
) != 0)
342 if ((flags6
& IN6_IFF_TEMPORARY
) != 0)
343 printf("temporary ");
344 if ((flags6
& IN6_IFF_DYNAMIC
) != 0)
346 if ((flags6
& IN6_IFF_SECURED
) != 0)
348 if ((flags6
& IN6_IFF_CLAT46
) != 0)
352 printf("scopeid 0x%x ", scopeid
);
354 if (ip6lifetime
&& (lifetime
.ia6t_preferred
|| lifetime
.ia6t_expire
)) {
356 if (lifetime
.ia6t_preferred
) {
357 printf("%s ", lifetime
.ia6t_preferred
< t
358 ? "0" : sec2str(lifetime
.ia6t_preferred
- t
));
363 if (lifetime
.ia6t_expire
) {
364 printf("%s ", lifetime
.ia6t_expire
< t
365 ? "0" : sec2str(lifetime
.ia6t_expire
- t
));
373 #define SIN6(x) ((struct sockaddr_in6 *) &(x))
374 static struct sockaddr_in6
*sin6tab
[] = {
375 SIN6(in6_ridreq
.ifr_addr
), SIN6(in6_addreq
.ifra_addr
),
376 SIN6(in6_addreq
.ifra_prefixmask
), SIN6(in6_addreq
.ifra_dstaddr
)
380 in6_getprefix(const char *plen
, int which
)
382 struct sockaddr_in6
*sin
= sin6tab
[which
];
384 int len
= atoi(plen
);
386 if ((len
< 0) || (len
> 128))
387 errx(1, "%s: bad value", plen
);
388 sin
->sin6_len
= sizeof(*sin
);
390 sin
->sin6_family
= AF_INET6
;
391 if ((len
== 0) || (len
== 128)) {
392 memset(&sin
->sin6_addr
, 0xff, sizeof(struct in6_addr
));
395 memset((void *)&sin
->sin6_addr
, 0x00, sizeof(sin
->sin6_addr
));
396 for (cp
= (u_char
*)&sin
->sin6_addr
; len
> 7; len
-= 8)
398 *cp
= 0xff << (8 - len
);
402 in6_getaddr(const char *s
, int which
)
404 struct sockaddr_in6
*sin
= sin6tab
[which
];
405 struct addrinfo hints
, *res
;
410 sin
->sin6_len
= sizeof(*sin
);
412 sin
->sin6_family
= AF_INET6
;
416 if((p
= strrchr(s
, '/')) != NULL
) {
418 in6_getprefix(p
+ 1, MASK
);
423 if (sin
->sin6_family
== AF_INET6
) {
424 bzero(&hints
, sizeof(struct addrinfo
));
425 hints
.ai_family
= AF_INET6
;
426 error
= getaddrinfo(s
, NULL
, &hints
, &res
);
429 if (inet_pton(AF_INET6
, s
, &sin
->sin6_addr
) != 1)
430 errx(1, "%s: bad value", s
);
432 bcopy(res
->ai_addr
, sin
, res
->ai_addrlen
);
436 prefix(void *val
, int size
)
438 u_char
*name
= (u_char
*)val
;
439 int byte
, bit
, plen
= 0;
441 for (byte
= 0; byte
< size
; byte
++, plen
+= 8)
442 if (name
[byte
] != 0xff)
446 for (bit
= 7; bit
!= 0; bit
--, plen
++)
447 if (!(name
[byte
] & (1 << bit
)))
449 for (; bit
!= 0; bit
--)
450 if (name
[byte
] & (1 << bit
))
453 for (; byte
< size
; byte
++)
460 sec2str(time_t total
)
462 static char result
[256];
463 int days
, hours
, mins
, secs
;
468 days
= total
/ 3600 / 24;
469 hours
= (total
/ 3600) % 24;
470 mins
= (total
/ 60) % 60;
475 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dd", days
);
477 if (!first
|| hours
) {
479 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dh", hours
);
481 if (!first
|| mins
) {
483 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dm", mins
);
485 snprintf(p
, sizeof(result
) - (p
- result
), "%ds", secs
);
487 snprintf(result
, sizeof(result
), "%lu", (unsigned long)total
);
493 in6_postproc(int s
, const struct afswtch
*afp
)
495 if (explicit_prefix
== 0) {
496 /* Aggregatable address architecture defines all prefixes
497 are 64. So, it is convenient to set prefixlen to 64 if
498 it is not specified. */
499 setifprefixlen("64", 0, s
, afp
);
500 /* in6_getprefix("64", MASK) if MASK is available here... */
505 in6_status_tunnel(int s
)
507 char src
[NI_MAXHOST
];
508 char dst
[NI_MAXHOST
];
509 struct in6_ifreq in6_ifr
;
510 const struct sockaddr
*sa
= (const struct sockaddr
*) &in6_ifr
.ifr_addr
;
512 memset(&in6_ifr
, 0, sizeof(in6_ifr
));
513 strlcpy(in6_ifr
.ifr_name
, name
, sizeof(in6_ifr
.ifr_name
));
515 if (ioctl(s
, SIOCGIFPSRCADDR_IN6
, (caddr_t
)&in6_ifr
) < 0)
517 if (sa
->sa_family
!= AF_INET6
)
519 in6_fillscopeid(&in6_ifr
.ifr_addr
);
520 if (getnameinfo(sa
, sa
->sa_len
, src
, sizeof(src
), 0, 0,
521 NI_NUMERICHOST
) != 0)
524 if (ioctl(s
, SIOCGIFPDSTADDR_IN6
, (caddr_t
)&in6_ifr
) < 0)
526 if (sa
->sa_family
!= AF_INET6
)
528 in6_fillscopeid(&in6_ifr
.ifr_addr
);
529 if (getnameinfo(sa
, sa
->sa_len
, dst
, sizeof(dst
), 0, 0,
530 NI_NUMERICHOST
) != 0)
533 printf("\ttunnel inet6 %s --> %s\n", src
, dst
);
539 struct in6_ndireq nd
;
543 memset(&nd
, 0, sizeof(nd
));
544 strlcpy(nd
.ifname
, ifr
.ifr_name
, sizeof(nd
.ifname
));
545 if ((s6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
546 if (errno
!= EPROTONOSUPPORT
)
547 warn("socket(AF_INET6, SOCK_DGRAM)");
550 error
= ioctl(s6
, SIOCGIFINFO_IN6
, &nd
);
552 if (errno
!= EPFNOSUPPORT
&& errno
!= EINVAL
)
553 warn("ioctl(SIOCGIFINFO_IN6)");
558 if (nd
.ndi
.flags
== 0)
560 printb("\tnd6 options", (unsigned int)nd
.ndi
.flags
, ND6BITS
);
565 in6_set_tunnel(int s
, struct addrinfo
*srcres
, struct addrinfo
*dstres
)
567 struct in6_aliasreq in6_addreq
;
569 memset(&in6_addreq
, 0, sizeof(in6_addreq
));
570 strlcpy(in6_addreq
.ifra_name
, name
, sizeof(in6_addreq
.ifra_name
));
571 memcpy(&in6_addreq
.ifra_addr
, srcres
->ai_addr
, srcres
->ai_addr
->sa_len
);
572 memcpy(&in6_addreq
.ifra_dstaddr
, dstres
->ai_addr
,
573 dstres
->ai_addr
->sa_len
);
575 if (ioctl(s
, SIOCSIFPHYADDR_IN6
, &in6_addreq
) < 0)
576 warn("SIOCSIFPHYADDR_IN6");
579 #ifndef IPV6_ROUTER_MODE_EXCLUSIVE
580 #define IPV6_ROUTER_MODE_DISABLED 0
581 #define IPV6_ROUTER_MODE_EXCLUSIVE 1
582 #define IPV6_ROUTER_MODE_HYBRID 2
583 #endif /* IPV6_ROUTER_MODE_EXCLUSIVE */
586 in6_set_router(int s
, int enable
)
590 bzero(&ifr
, sizeof (ifr
));
591 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
592 ifr
.ifr_intval
= (enable
== 0)
593 ? IPV6_ROUTER_MODE_DISABLED
594 : IPV6_ROUTER_MODE_EXCLUSIVE
;
596 if (ioctl(s
, SIOCSETROUTERMODE_IN6
, &ifr
) < 0)
597 warn("SIOCSETROUTERMODE_IN6");
601 routermode_from_string(char * str
, int *mode_p
)
605 if (strcasecmp(str
, "exclusive") == 0 ||
606 strcasecmp(str
, "enabled") == 0) {
607 *mode_p
= IPV6_ROUTER_MODE_EXCLUSIVE
;
608 } else if (strcasecmp(str
, "hybrid") == 0) {
609 *mode_p
= IPV6_ROUTER_MODE_HYBRID
;
610 } else if (strcasecmp(str
, "disabled") == 0) {
611 *mode_p
= IPV6_ROUTER_MODE_DISABLED
;
619 routermode_string(int mode
)
624 case IPV6_ROUTER_MODE_EXCLUSIVE
:
627 case IPV6_ROUTER_MODE_HYBRID
:
630 case IPV6_ROUTER_MODE_DISABLED
:
641 in6_routermode(int s
, int argc
, char *const*argv
)
643 struct in6_ifreq ifr
;
646 bzero(&ifr
, sizeof (ifr
));
647 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
650 #ifndef SIOCGETROUTERMODE_IN6
651 #define SIOCGETROUTERMODE_IN6 _IOWR('i', 137, struct in6_ifreq)
652 #endif /* SIOCGETROUTERMODE_IN6 */
653 if (ioctl(s
, SIOCGETROUTERMODE_IN6
, &ifr
) < 0) {
655 warn("SIOCGETROUTERMODE_IN6");
658 /* argv is NULL if we're called from status() */
660 (argv
== NULL
) ? "\troutermode6: " : "",
661 routermode_string(ifr
.ifr_intval
));
667 if (routermode_from_string(argv
[0], &mode
) == 0) {
669 "mode '%s' invalid, must be one of "
670 "disabled, exclusive, or hybrid",
673 ifr
.ifr_intval
= mode
;
674 if (ioctl(s
, SIOCSETROUTERMODE_IN6
, &ifr
) < 0) {
675 warn("SIOCSETROUTERMODE_IN6");
682 static struct cmd inet6_cmds
[] = {
683 DEF_CMD_ARG("prefixlen", setifprefixlen
),
684 DEF_CMD("anycast", IN6_IFF_ANYCAST
, setip6flags
),
685 DEF_CMD("tentative", IN6_IFF_TENTATIVE
, setip6flags
),
686 DEF_CMD("-tentative", -IN6_IFF_TENTATIVE
, setip6flags
),
687 /* RFC 4429, section 3.1, says:
688 * "Optimistic DAD SHOULD NOT be used for manually entered
692 DEF_CMD("optimistic", IN6_IFF_OPTIMISTIC
, setip6flags
),
693 DEF_CMD("-optimistic", -IN6_IFF_OPTIMISTIC
, setip6flags
),
694 DEF_CMD("deprecated", IN6_IFF_DEPRECATED
, setip6flags
),
695 DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED
, setip6flags
),
696 DEF_CMD("autoconf", IN6_IFF_AUTOCONF
, setip6flags
),
697 DEF_CMD("-autoconf", -IN6_IFF_AUTOCONF
, setip6flags
),
698 DEF_CMD("nud", ND6_IFF_PERFORMNUD
, setnd6flags
),
699 DEF_CMD("-nud", -ND6_IFF_PERFORMNUD
, setnd6flags
),
700 DEF_CMD("ifdisabled", ND6_IFF_IFDISABLED
, setnd6flags
),
701 DEF_CMD("-ifdisabled", -ND6_IFF_IFDISABLED
, setnd6flags
),
702 DEF_CMD("replicated", ND6_IFF_REPLICATED
, setnd6flags
),
703 DEF_CMD("-replicated", -ND6_IFF_REPLICATED
, setnd6flags
),
704 DEF_CMD("proxy_prefixes", ND6_IFF_PROXY_PREFIXES
, setnd6flags
),
705 DEF_CMD("-proxy_prefixes", -ND6_IFF_PROXY_PREFIXES
, setnd6flags
),
706 DEF_CMD("insecure", ND6_IFF_INSECURE
, setnd6flags
),
707 DEF_CMD("-insecure", -ND6_IFF_INSECURE
, setnd6flags
),
708 DEF_CMD_ARG("pltime", setip6pltime
),
709 DEF_CMD_ARG("vltime", setip6vltime
),
710 DEF_CMD("eui64", 0, setip6eui64
),
711 DEF_CMD("secured", IN6_IFF_SECURED
, setip6flags
),
712 DEF_CMD("-secured", -IN6_IFF_SECURED
, setip6flags
),
713 DEF_CMD("dad", ND6_IFF_DAD
, setnd6flags
),
714 DEF_CMD("-dad", -ND6_IFF_DAD
, setnd6flags
),
717 static struct afswtch af_inet6
= {
720 .af_status
= in6_status
,
721 .af_getaddr
= in6_getaddr
,
722 .af_getprefix
= in6_getprefix
,
723 .af_other_status
= nd6_status
,
724 .af_postproc
= in6_postproc
,
725 .af_status_tunnel
= in6_status_tunnel
,
726 .af_settunnel
= in6_set_tunnel
,
727 .af_setrouter
= in6_set_router
,
728 .af_routermode
= in6_routermode
,
729 .af_difaddr
= SIOCDIFADDR_IN6
,
730 .af_aifaddr
= SIOCAIFADDR_IN6
,
731 .af_ridreq
= &in6_ridreq
,
732 .af_addreq
= &in6_addreq
,
736 in6_Lopt_cb(const char *optarg __unused
)
738 ip6lifetime
++; /* print IPv6 address lifetime */
740 static struct option in6_Lopt
= { "L", "[-L]", in6_Lopt_cb
};
742 static __constructor
void
745 #define N(a) (sizeof(a) / sizeof(a[0]))
748 for (i
= 0; i
< N(inet6_cmds
); i
++)
749 cmd_register(&inet6_cmds
[i
]);
750 af_register(&af_inet6
);
751 opt_register(&in6_Lopt
);