17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2b24ab6bSSebastien Roy  * Common Development and Distribution License (the "License").
6*2b24ab6bSSebastien Roy  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*2b24ab6bSSebastien Roy  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/socket.h>
277c478bd9Sstevel@tonic-gate #include <sys/stream.h>
287c478bd9Sstevel@tonic-gate #include <sys/param.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <net/route.h>
317c478bd9Sstevel@tonic-gate #include <net/if.h>
327c478bd9Sstevel@tonic-gate #include <netinet/in.h>
337c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <locale.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <errno.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <strings.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <stropts.h>
447c478bd9Sstevel@tonic-gate #include <fcntl.h>
45*2b24ab6bSSebastien Roy #include <libdliptun.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static void usage(void);
487c478bd9Sstevel@tonic-gate 
49*2b24ab6bSSebastien Roy static dladm_handle_t	handle;
507c478bd9Sstevel@tonic-gate /* booleans corresponding to command line flags */
51*2b24ab6bSSebastien Roy static boolean_t	eflag = B_FALSE;
52*2b24ab6bSSebastien Roy static boolean_t	dflag = B_FALSE;
53*2b24ab6bSSebastien Roy static boolean_t	aflag = B_FALSE;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  * printkstatus()
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  * Queries the kernel for the current 6to4 Relay Router value, prints
607c478bd9Sstevel@tonic-gate  * a status message based on the value and exits this command.
617c478bd9Sstevel@tonic-gate  * INADDR_ANY is used to denote that Relay Router communication support is
627c478bd9Sstevel@tonic-gate  * disabled within the kernel.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate static void
printkstatus(void)657c478bd9Sstevel@tonic-gate printkstatus(void)
667c478bd9Sstevel@tonic-gate {
67*2b24ab6bSSebastien Roy 	struct in_addr	rr_addr;
68*2b24ab6bSSebastien Roy 	char		buf[INET6_ADDRSTRLEN];
69*2b24ab6bSSebastien Roy 	char		errstr[DLADM_STRSIZE];
70*2b24ab6bSSebastien Roy 	dladm_status_t	status;
71*2b24ab6bSSebastien Roy 
72*2b24ab6bSSebastien Roy 	status = dladm_iptun_get6to4relay(handle, &rr_addr);
73*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK) {
74*2b24ab6bSSebastien Roy 		(void) fprintf(stderr, gettext("6to4relay: unable to get "
75*2b24ab6bSSebastien Roy 		    "6to4 relay status: %s\n"),
76*2b24ab6bSSebastien Roy 		    dladm_status2str(status, errstr));
77*2b24ab6bSSebastien Roy 		return;
78*2b24ab6bSSebastien Roy 	}
797c478bd9Sstevel@tonic-gate 	(void) printf("6to4relay: ");
80*2b24ab6bSSebastien Roy 	if (rr_addr.s_addr == INADDR_ANY) {
817c478bd9Sstevel@tonic-gate 		(void) printf(gettext("6to4 Relay Router communication "
827c478bd9Sstevel@tonic-gate 		    "support is disabled.\n"));
837c478bd9Sstevel@tonic-gate 	} else {
847c478bd9Sstevel@tonic-gate 		(void) printf(gettext("6to4 Relay Router communication "
857c478bd9Sstevel@tonic-gate 		    "support is enabled.\n"));
867c478bd9Sstevel@tonic-gate 		(void) printf(gettext("IPv4 destination address of Relay "
877c478bd9Sstevel@tonic-gate 		    "Router = "));
887c478bd9Sstevel@tonic-gate 		(void) printf("%s\n",
897c478bd9Sstevel@tonic-gate 		    inet_ntop(AF_INET, &rr_addr, buf, sizeof (buf)));
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate  * modifyroute(cmd, in_gw)
957c478bd9Sstevel@tonic-gate  *
967c478bd9Sstevel@tonic-gate  * Modifies a default IPv6 route with DST = ::, GATEWAY = in_gw, NETMASK = ::
977c478bd9Sstevel@tonic-gate  * and flags = <GATEWAY, STATIC>.
987c478bd9Sstevel@tonic-gate  * This route is to be propagated through the 6to4 site so that 6to4 hosts
997c478bd9Sstevel@tonic-gate  * can send packets to native IPv6 hosts behind a remote 6to4 Relay Router.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate static void
modifyroute(unsigned int cmd,in6_addr_t * in_gw)1027c478bd9Sstevel@tonic-gate modifyroute(unsigned int cmd, in6_addr_t *in_gw)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	static int rtmseq;
1057c478bd9Sstevel@tonic-gate 	int rtsock;
1067c478bd9Sstevel@tonic-gate 	int rlen;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	static struct {
1097c478bd9Sstevel@tonic-gate 		struct rt_msghdr	rt_hdr;
1107c478bd9Sstevel@tonic-gate 		struct sockaddr_in6	rt_dst;
1117c478bd9Sstevel@tonic-gate 		struct sockaddr_in6	rt_gate;
1127c478bd9Sstevel@tonic-gate 		struct sockaddr_in6	rt_mask;
1137c478bd9Sstevel@tonic-gate 	} rt_msg;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/* Open a routing socket for passing route commands */
1167c478bd9Sstevel@tonic-gate 	if ((rtsock = socket(AF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
117*2b24ab6bSSebastien Roy 		(void) fprintf(stderr, gettext("6to4relay: unable to modify "
118*2b24ab6bSSebastien Roy 		    "default IPv6 route: socket: %s\n"), strerror(errno));
119*2b24ab6bSSebastien Roy 		return;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	(void) memset(&rt_msg, 0, sizeof (rt_msg));
1237c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_msglen = sizeof (rt_msg);
1247c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_version = RTM_VERSION;
1257c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
1267c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_pid = getpid();
1277c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_type = cmd;
1287c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_seq = ++rtmseq;
1297c478bd9Sstevel@tonic-gate 	rt_msg.rt_hdr.rtm_flags = RTF_STATIC | RTF_GATEWAY;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	/* DST */
1327c478bd9Sstevel@tonic-gate 	rt_msg.rt_dst.sin6_family = AF_INET6;
1337c478bd9Sstevel@tonic-gate 	(void) memset(&rt_msg.rt_dst.sin6_addr.s6_addr, 0,
1347c478bd9Sstevel@tonic-gate 	    sizeof (in6_addr_t));
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/* GATEWAY */
1377c478bd9Sstevel@tonic-gate 	rt_msg.rt_gate.sin6_family = AF_INET6;
1387c478bd9Sstevel@tonic-gate 	bcopy(in_gw->s6_addr, &rt_msg.rt_gate.sin6_addr.s6_addr,
1397c478bd9Sstevel@tonic-gate 	    sizeof (in6_addr_t));
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/* NETMASK */
1427c478bd9Sstevel@tonic-gate 	rt_msg.rt_mask.sin6_family = AF_INET6;
1437c478bd9Sstevel@tonic-gate 	(void) memset(&rt_msg.rt_mask.sin6_addr.s6_addr, 0,
1447c478bd9Sstevel@tonic-gate 	    sizeof (in6_addr_t));
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/* Send the routing message */
1477c478bd9Sstevel@tonic-gate 	rlen = write(rtsock, &rt_msg, rt_msg.rt_hdr.rtm_msglen);
1487c478bd9Sstevel@tonic-gate 	if (rlen < rt_msg.rt_hdr.rtm_msglen) {
1497c478bd9Sstevel@tonic-gate 		if (rlen < 0) {
1507c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1517c478bd9Sstevel@tonic-gate 			    gettext("6to4relay: write to routing socket: %s\n"),
1527c478bd9Sstevel@tonic-gate 			    strerror(errno));
1537c478bd9Sstevel@tonic-gate 		} else {
1547c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("6to4relay: write to "
1557c478bd9Sstevel@tonic-gate 			    "routing socket got only %d for rlen\n"), rlen);
1567c478bd9Sstevel@tonic-gate 		}
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 	(void) close(rtsock);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate static void
usage(void)1627c478bd9Sstevel@tonic-gate usage(void)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
1657c478bd9Sstevel@tonic-gate 	    gettext("usage:\n"
166*2b24ab6bSSebastien Roy 	    "\t6to4relay\n"
167*2b24ab6bSSebastien Roy 	    "\t6to4relay -e [-a <addr>]\n"
168*2b24ab6bSSebastien Roy 	    "\t6to4relay -d\n"
169*2b24ab6bSSebastien Roy 	    "\t6to4relay -h\n"));
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)1737c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1747c478bd9Sstevel@tonic-gate {
175*2b24ab6bSSebastien Roy 	int		ch;
176*2b24ab6bSSebastien Roy 	char		*relay_arg = NULL;
177*2b24ab6bSSebastien Roy 	dladm_status_t	status;
178*2b24ab6bSSebastien Roy 	char		errstr[DLADM_STRSIZE];
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1837c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
1847c478bd9Sstevel@tonic-gate #endif
1857c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1867c478bd9Sstevel@tonic-gate 
187*2b24ab6bSSebastien Roy 	if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
188*2b24ab6bSSebastien Roy 		(void) fprintf(stderr, gettext("6to4relay: error opening "
189*2b24ab6bSSebastien Roy 		    "dladm handle: %s\n"), dladm_status2str(status, errstr));
190*2b24ab6bSSebastien Roy 		return (EXIT_FAILURE);
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 
193*2b24ab6bSSebastien Roy 	/* If no args are specified, print the current status. */
1947c478bd9Sstevel@tonic-gate 	if (argc < 2) {
1957c478bd9Sstevel@tonic-gate 		printkstatus();
196*2b24ab6bSSebastien Roy 		return (EXIT_SUCCESS);
1977c478bd9Sstevel@tonic-gate 	}
198*2b24ab6bSSebastien Roy 
1997c478bd9Sstevel@tonic-gate 	while ((ch = getopt(argc, argv, "ea:dh")) != EOF) {
2007c478bd9Sstevel@tonic-gate 		switch (ch) {
2017c478bd9Sstevel@tonic-gate 		case 'e':
2027c478bd9Sstevel@tonic-gate 			eflag = B_TRUE;
2037c478bd9Sstevel@tonic-gate 			break;
2047c478bd9Sstevel@tonic-gate 		case 'd':
2057c478bd9Sstevel@tonic-gate 			dflag = B_TRUE;
2067c478bd9Sstevel@tonic-gate 			break;
2077c478bd9Sstevel@tonic-gate 		case 'a':
2087c478bd9Sstevel@tonic-gate 			aflag = B_TRUE;
209*2b24ab6bSSebastien Roy 			relay_arg = optarg;
2107c478bd9Sstevel@tonic-gate 			break;
2117c478bd9Sstevel@tonic-gate 		case 'h':
2127c478bd9Sstevel@tonic-gate 			usage();
213*2b24ab6bSSebastien Roy 			return (EXIT_SUCCESS);
2147c478bd9Sstevel@tonic-gate 		default:
2157c478bd9Sstevel@tonic-gate 			usage();
216*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
2177c478bd9Sstevel@tonic-gate 		}
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 	/*
2207c478bd9Sstevel@tonic-gate 	 * If -a is specified, -e must also be specified.  Also, the
2217c478bd9Sstevel@tonic-gate 	 * combination of -e and -d is illegal.  Fail on either case.
2227c478bd9Sstevel@tonic-gate 	 */
2237c478bd9Sstevel@tonic-gate 	if ((aflag && !eflag) || (eflag && dflag)) {
2247c478bd9Sstevel@tonic-gate 		usage();
225*2b24ab6bSSebastien Roy 		return (EXIT_FAILURE);
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/*
2297c478bd9Sstevel@tonic-gate 	 * Enable Relay Router communication support in the kernel.
2307c478bd9Sstevel@tonic-gate 	 */
2317c478bd9Sstevel@tonic-gate 	if (eflag) {
232*2b24ab6bSSebastien Roy 		struct in_addr current_addr;
233*2b24ab6bSSebastien Roy 		struct in_addr new_addr;
2347c478bd9Sstevel@tonic-gate 		in6_addr_t v6_rt;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 		/*
2377c478bd9Sstevel@tonic-gate 		 * if -a was not specified, the well-known anycast will
2387c478bd9Sstevel@tonic-gate 		 * be used.
2397c478bd9Sstevel@tonic-gate 		 */
2407c478bd9Sstevel@tonic-gate 		if (!aflag) {
2417c478bd9Sstevel@tonic-gate 			new_addr.s_addr = htonl(INADDR_6TO4RRANYCAST);
242*2b24ab6bSSebastien Roy 		} else if (inet_pton(AF_INET, relay_arg, &new_addr) <= 0) {
2437c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("6to4relay: input "
2447c478bd9Sstevel@tonic-gate 			    "address (%s) is not a valid IPv4 dotted-decimal "
245*2b24ab6bSSebastien Roy 			    "string.\n"), relay_arg);
246*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
2477c478bd9Sstevel@tonic-gate 		}
2487c478bd9Sstevel@tonic-gate 
249*2b24ab6bSSebastien Roy 		status = dladm_iptun_get6to4relay(handle, &current_addr);
250*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK) {
251*2b24ab6bSSebastien Roy 			(void) fprintf(stderr, gettext("6to4relay: "
252*2b24ab6bSSebastien Roy 			    "unable to obtain current 6to4 relay address: %s"),
253*2b24ab6bSSebastien Roy 			    dladm_status2str(status, errstr));
254*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 
257*2b24ab6bSSebastien Roy 		if (current_addr.s_addr == new_addr.s_addr)
258*2b24ab6bSSebastien Roy 			return (EXIT_SUCCESS);
259*2b24ab6bSSebastien Roy 
260*2b24ab6bSSebastien Roy 		status = dladm_iptun_set6to4relay(handle, &new_addr);
261*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK) {
262*2b24ab6bSSebastien Roy 			(void) fprintf(stderr, gettext("6to4relay: "
263*2b24ab6bSSebastien Roy 			    "unable to set the 6to4 relay router address: "
264*2b24ab6bSSebastien Roy 			    "%s\n"), dladm_status2str(status, errstr));
265*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
266*2b24ab6bSSebastien Roy 		}
267*2b24ab6bSSebastien Roy 
268*2b24ab6bSSebastien Roy 		if (current_addr.s_addr != INADDR_ANY) {
2697c478bd9Sstevel@tonic-gate 			/* remove old default IPv6 route */
270*2b24ab6bSSebastien Roy 			IN6_V4ADDR_TO_6TO4(&current_addr, &v6_rt);
2717c478bd9Sstevel@tonic-gate 			modifyroute(RTM_DELETE, &v6_rt);
2727c478bd9Sstevel@tonic-gate 		}
273*2b24ab6bSSebastien Roy 
274*2b24ab6bSSebastien Roy 		IN6_V4ADDR_TO_6TO4(&new_addr, &v6_rt);
275*2b24ab6bSSebastien Roy 		modifyroute(RTM_ADD, &v6_rt);
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	/*
2797c478bd9Sstevel@tonic-gate 	 * Disable Relay Router communication support in kernel.
2807c478bd9Sstevel@tonic-gate 	 */
2817c478bd9Sstevel@tonic-gate 	if (dflag) {
282*2b24ab6bSSebastien Roy 		struct in_addr rr_addr;
2837c478bd9Sstevel@tonic-gate 		in6_addr_t v6_rt;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 		/*
2867c478bd9Sstevel@tonic-gate 		 * get Relay Router address from the kernel and delete
2877c478bd9Sstevel@tonic-gate 		 * default IPv6 route that was added for it.
2887c478bd9Sstevel@tonic-gate 		 */
289*2b24ab6bSSebastien Roy 		status = dladm_iptun_get6to4relay(handle, &rr_addr);
290*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK) {
291*2b24ab6bSSebastien Roy 			(void) fprintf(stderr, gettext("6to4relay: "
292*2b24ab6bSSebastien Roy 			    "unable to obtain current 6to4 relay address: %s"),
293*2b24ab6bSSebastien Roy 			    dladm_status2str(status, errstr));
294*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
2957c478bd9Sstevel@tonic-gate 		}
296*2b24ab6bSSebastien Roy 		if (rr_addr.s_addr == INADDR_ANY)
297*2b24ab6bSSebastien Roy 			return (EXIT_SUCCESS);
2987c478bd9Sstevel@tonic-gate 
299*2b24ab6bSSebastien Roy 		IN6_V4ADDR_TO_6TO4(&rr_addr, &v6_rt);
3007c478bd9Sstevel@tonic-gate 		modifyroute(RTM_DELETE, &v6_rt);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		/*
3037c478bd9Sstevel@tonic-gate 		 * INADDR_ANY (0.0.0.0) is used by the kernel to disable Relay
3047c478bd9Sstevel@tonic-gate 		 * Router communication support.
3057c478bd9Sstevel@tonic-gate 		 */
306*2b24ab6bSSebastien Roy 		rr_addr.s_addr = INADDR_ANY;
307*2b24ab6bSSebastien Roy 		status = dladm_iptun_set6to4relay(handle, &rr_addr);
308*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK) {
309*2b24ab6bSSebastien Roy 			(void) fprintf(stderr, gettext("6to4relay: "
310*2b24ab6bSSebastien Roy 			    "unable to disable tunneling to 6to4 relay router: "
311*2b24ab6bSSebastien Roy 			    "%s\n"), dladm_status2str(status, errstr));
312*2b24ab6bSSebastien Roy 			return (EXIT_FAILURE);
313*2b24ab6bSSebastien Roy 		}
3147c478bd9Sstevel@tonic-gate 	}
315*2b24ab6bSSebastien Roy 
316*2b24ab6bSSebastien Roy 	return (EXIT_SUCCESS);
3177c478bd9Sstevel@tonic-gate }
318