4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/socket.h>
27 #include <sys/stream.h>
28 #include <sys/param.h>
30 #include <net/route.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
45 #include <libdliptun.h>
47 static void usage(void);
49 static dladm_handle_t handle
;
50 /* booleans corresponding to command line flags */
51 static boolean_t eflag
= B_FALSE
;
52 static boolean_t dflag
= B_FALSE
;
53 static boolean_t aflag
= B_FALSE
;
59 * Queries the kernel for the current 6to4 Relay Router value, prints
60 * a status message based on the value and exits this command.
61 * INADDR_ANY is used to denote that Relay Router communication support is
62 * disabled within the kernel.
67 struct in_addr rr_addr
;
68 char buf
[INET6_ADDRSTRLEN
];
69 char errstr
[DLADM_STRSIZE
];
70 dladm_status_t status
;
72 status
= dladm_iptun_get6to4relay(handle
, &rr_addr
);
73 if (status
!= DLADM_STATUS_OK
) {
74 (void) fprintf(stderr
, gettext("6to4relay: unable to get "
75 "6to4 relay status: %s\n"),
76 dladm_status2str(status
, errstr
));
79 (void) printf("6to4relay: ");
80 if (rr_addr
.s_addr
== INADDR_ANY
) {
81 (void) printf(gettext("6to4 Relay Router communication "
82 "support is disabled.\n"));
84 (void) printf(gettext("6to4 Relay Router communication "
85 "support is enabled.\n"));
86 (void) printf(gettext("IPv4 destination address of Relay "
89 inet_ntop(AF_INET
, &rr_addr
, buf
, sizeof (buf
)));
94 * modifyroute(cmd, in_gw)
96 * Modifies a default IPv6 route with DST = ::, GATEWAY = in_gw, NETMASK = ::
97 * and flags = <GATEWAY, STATIC>.
98 * This route is to be propagated through the 6to4 site so that 6to4 hosts
99 * can send packets to native IPv6 hosts behind a remote 6to4 Relay Router.
102 modifyroute(unsigned int cmd
, in6_addr_t
*in_gw
)
109 struct rt_msghdr rt_hdr
;
110 struct sockaddr_in6 rt_dst
;
111 struct sockaddr_in6 rt_gate
;
112 struct sockaddr_in6 rt_mask
;
115 /* Open a routing socket for passing route commands */
116 if ((rtsock
= socket(AF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
117 (void) fprintf(stderr
, gettext("6to4relay: unable to modify "
118 "default IPv6 route: socket: %s\n"), strerror(errno
));
122 (void) memset(&rt_msg
, 0, sizeof (rt_msg
));
123 rt_msg
.rt_hdr
.rtm_msglen
= sizeof (rt_msg
);
124 rt_msg
.rt_hdr
.rtm_version
= RTM_VERSION
;
125 rt_msg
.rt_hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
| RTA_NETMASK
;
126 rt_msg
.rt_hdr
.rtm_pid
= getpid();
127 rt_msg
.rt_hdr
.rtm_type
= cmd
;
128 rt_msg
.rt_hdr
.rtm_seq
= ++rtmseq
;
129 rt_msg
.rt_hdr
.rtm_flags
= RTF_STATIC
| RTF_GATEWAY
;
132 rt_msg
.rt_dst
.sin6_family
= AF_INET6
;
133 (void) memset(&rt_msg
.rt_dst
.sin6_addr
.s6_addr
, 0,
134 sizeof (in6_addr_t
));
137 rt_msg
.rt_gate
.sin6_family
= AF_INET6
;
138 bcopy(in_gw
->s6_addr
, &rt_msg
.rt_gate
.sin6_addr
.s6_addr
,
139 sizeof (in6_addr_t
));
142 rt_msg
.rt_mask
.sin6_family
= AF_INET6
;
143 (void) memset(&rt_msg
.rt_mask
.sin6_addr
.s6_addr
, 0,
144 sizeof (in6_addr_t
));
146 /* Send the routing message */
147 rlen
= write(rtsock
, &rt_msg
, rt_msg
.rt_hdr
.rtm_msglen
);
148 if (rlen
< rt_msg
.rt_hdr
.rtm_msglen
) {
150 (void) fprintf(stderr
,
151 gettext("6to4relay: write to routing socket: %s\n"),
154 (void) fprintf(stderr
, gettext("6to4relay: write to "
155 "routing socket got only %d for rlen\n"), rlen
);
158 (void) close(rtsock
);
164 (void) fprintf(stderr
,
167 "\t6to4relay -e [-a <addr>]\n"
169 "\t6to4relay -h\n"));
173 main(int argc
, char **argv
)
176 char *relay_arg
= NULL
;
177 dladm_status_t status
;
178 char errstr
[DLADM_STRSIZE
];
180 (void) setlocale(LC_ALL
, "");
182 #if !defined(TEXT_DOMAIN)
183 #define TEXT_DOMAIN "SYS_TEST"
185 (void) textdomain(TEXT_DOMAIN
);
187 if ((status
= dladm_open(&handle
)) != DLADM_STATUS_OK
) {
188 (void) fprintf(stderr
, gettext("6to4relay: error opening "
189 "dladm handle: %s\n"), dladm_status2str(status
, errstr
));
190 return (EXIT_FAILURE
);
193 /* If no args are specified, print the current status. */
196 return (EXIT_SUCCESS
);
199 while ((ch
= getopt(argc
, argv
, "ea:dh")) != EOF
) {
213 return (EXIT_SUCCESS
);
216 return (EXIT_FAILURE
);
220 * If -a is specified, -e must also be specified. Also, the
221 * combination of -e and -d is illegal. Fail on either case.
223 if ((aflag
&& !eflag
) || (eflag
&& dflag
)) {
225 return (EXIT_FAILURE
);
229 * Enable Relay Router communication support in the kernel.
232 struct in_addr current_addr
;
233 struct in_addr new_addr
;
237 * if -a was not specified, the well-known anycast will
241 new_addr
.s_addr
= htonl(INADDR_6TO4RRANYCAST
);
242 } else if (inet_pton(AF_INET
, relay_arg
, &new_addr
) <= 0) {
243 (void) fprintf(stderr
, gettext("6to4relay: input "
244 "address (%s) is not a valid IPv4 dotted-decimal "
245 "string.\n"), relay_arg
);
246 return (EXIT_FAILURE
);
249 status
= dladm_iptun_get6to4relay(handle
, ¤t_addr
);
250 if (status
!= DLADM_STATUS_OK
) {
251 (void) fprintf(stderr
, gettext("6to4relay: "
252 "unable to obtain current 6to4 relay address: %s"),
253 dladm_status2str(status
, errstr
));
254 return (EXIT_FAILURE
);
257 if (current_addr
.s_addr
== new_addr
.s_addr
)
258 return (EXIT_SUCCESS
);
260 status
= dladm_iptun_set6to4relay(handle
, &new_addr
);
261 if (status
!= DLADM_STATUS_OK
) {
262 (void) fprintf(stderr
, gettext("6to4relay: "
263 "unable to set the 6to4 relay router address: "
264 "%s\n"), dladm_status2str(status
, errstr
));
265 return (EXIT_FAILURE
);
268 if (current_addr
.s_addr
!= INADDR_ANY
) {
269 /* remove old default IPv6 route */
270 IN6_V4ADDR_TO_6TO4(¤t_addr
, &v6_rt
);
271 modifyroute(RTM_DELETE
, &v6_rt
);
274 IN6_V4ADDR_TO_6TO4(&new_addr
, &v6_rt
);
275 modifyroute(RTM_ADD
, &v6_rt
);
279 * Disable Relay Router communication support in kernel.
282 struct in_addr rr_addr
;
286 * get Relay Router address from the kernel and delete
287 * default IPv6 route that was added for it.
289 status
= dladm_iptun_get6to4relay(handle
, &rr_addr
);
290 if (status
!= DLADM_STATUS_OK
) {
291 (void) fprintf(stderr
, gettext("6to4relay: "
292 "unable to obtain current 6to4 relay address: %s"),
293 dladm_status2str(status
, errstr
));
294 return (EXIT_FAILURE
);
296 if (rr_addr
.s_addr
== INADDR_ANY
)
297 return (EXIT_SUCCESS
);
299 IN6_V4ADDR_TO_6TO4(&rr_addr
, &v6_rt
);
300 modifyroute(RTM_DELETE
, &v6_rt
);
303 * INADDR_ANY (0.0.0.0) is used by the kernel to disable Relay
304 * Router communication support.
306 rr_addr
.s_addr
= INADDR_ANY
;
307 status
= dladm_iptun_set6to4relay(handle
, &rr_addr
);
308 if (status
!= DLADM_STATUS_OK
) {
309 (void) fprintf(stderr
, gettext("6to4relay: "
310 "unable to disable tunneling to 6to4 relay router: "
311 "%s\n"), dladm_status2str(status
, errstr
));
312 return (EXIT_FAILURE
);
316 return (EXIT_SUCCESS
);