Move /var/svc/log to /var/log/svc
[unleashed/lotheac.git] / usr / src / cmd / cmd-inet / usr.sbin / 6to4relay.c
blob19a59915f3e0c56fffe1abd9b4ec051b81668f2b
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
31 #include <net/if.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
35 #include <locale.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <string.h>
43 #include <stropts.h>
44 #include <fcntl.h>
45 #include <libdliptun.h>
47 /* Well known 6to4 Relay Router Anycast address defined in RFC 3068 */
48 #define INADDR_6TO4RRANYCAST 0xc0586301U /* 192.88.99.1 */
50 static void usage(void);
52 static dladm_handle_t handle;
53 /* booleans corresponding to command line flags */
54 static boolean_t eflag = B_FALSE;
55 static boolean_t dflag = B_FALSE;
56 static boolean_t aflag = B_FALSE;
60 * printkstatus()
62 * Queries the kernel for the current 6to4 Relay Router value, prints
63 * a status message based on the value and exits this command.
64 * INADDR_ANY is used to denote that Relay Router communication support is
65 * disabled within the kernel.
67 static void
68 printkstatus(void)
70 struct in_addr rr_addr;
71 char buf[INET6_ADDRSTRLEN];
72 char errstr[DLADM_STRSIZE];
73 dladm_status_t status;
75 status = dladm_iptun_get6to4relay(handle, &rr_addr);
76 if (status != DLADM_STATUS_OK) {
77 (void) fprintf(stderr, gettext("6to4relay: unable to get "
78 "6to4 relay status: %s\n"),
79 dladm_status2str(status, errstr));
80 return;
82 (void) printf("6to4relay: ");
83 if (rr_addr.s_addr == INADDR_ANY) {
84 (void) printf(gettext("6to4 Relay Router communication "
85 "support is disabled.\n"));
86 } else {
87 (void) printf(gettext("6to4 Relay Router communication "
88 "support is enabled.\n"));
89 (void) printf(gettext("IPv4 destination address of Relay "
90 "Router = "));
91 (void) printf("%s\n",
92 inet_ntop(AF_INET, &rr_addr, buf, sizeof (buf)));
97 * modifyroute(cmd, in_gw)
99 * Modifies a default IPv6 route with DST = ::, GATEWAY = in_gw, NETMASK = ::
100 * and flags = <GATEWAY, STATIC>.
101 * This route is to be propagated through the 6to4 site so that 6to4 hosts
102 * can send packets to native IPv6 hosts behind a remote 6to4 Relay Router.
104 static void
105 modifyroute(unsigned int cmd, in6_addr_t *in_gw)
107 static int rtmseq;
108 int rtsock;
109 int rlen;
111 static struct {
112 struct rt_msghdr rt_hdr;
113 struct sockaddr_in6 rt_dst;
114 struct sockaddr_in6 rt_gate;
115 struct sockaddr_in6 rt_mask;
116 } rt_msg;
118 /* Open a routing socket for passing route commands */
119 if ((rtsock = socket(AF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
120 (void) fprintf(stderr, gettext("6to4relay: unable to modify "
121 "default IPv6 route: socket: %s\n"), strerror(errno));
122 return;
125 (void) memset(&rt_msg, 0, sizeof (rt_msg));
126 rt_msg.rt_hdr.rtm_msglen = sizeof (rt_msg);
127 rt_msg.rt_hdr.rtm_version = RTM_VERSION;
128 rt_msg.rt_hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
129 rt_msg.rt_hdr.rtm_pid = getpid();
130 rt_msg.rt_hdr.rtm_type = cmd;
131 rt_msg.rt_hdr.rtm_seq = ++rtmseq;
132 rt_msg.rt_hdr.rtm_flags = RTF_STATIC | RTF_GATEWAY;
134 /* DST */
135 rt_msg.rt_dst.sin6_family = AF_INET6;
136 (void) memset(&rt_msg.rt_dst.sin6_addr.s6_addr, 0,
137 sizeof (in6_addr_t));
139 /* GATEWAY */
140 rt_msg.rt_gate.sin6_family = AF_INET6;
141 bcopy(in_gw->s6_addr, &rt_msg.rt_gate.sin6_addr.s6_addr,
142 sizeof (in6_addr_t));
144 /* NETMASK */
145 rt_msg.rt_mask.sin6_family = AF_INET6;
146 (void) memset(&rt_msg.rt_mask.sin6_addr.s6_addr, 0,
147 sizeof (in6_addr_t));
149 /* Send the routing message */
150 rlen = write(rtsock, &rt_msg, rt_msg.rt_hdr.rtm_msglen);
151 if (rlen < rt_msg.rt_hdr.rtm_msglen) {
152 if (rlen < 0) {
153 (void) fprintf(stderr,
154 gettext("6to4relay: write to routing socket: %s\n"),
155 strerror(errno));
156 } else {
157 (void) fprintf(stderr, gettext("6to4relay: write to "
158 "routing socket got only %d for rlen\n"), rlen);
161 (void) close(rtsock);
164 static void
165 usage(void)
167 (void) fprintf(stderr,
168 gettext("usage:\n"
169 "\t6to4relay\n"
170 "\t6to4relay -e [-a <addr>]\n"
171 "\t6to4relay -d\n"
172 "\t6to4relay -h\n"));
176 main(int argc, char **argv)
178 int ch;
179 char *relay_arg = NULL;
180 dladm_status_t status;
181 char errstr[DLADM_STRSIZE];
183 (void) setlocale(LC_ALL, "");
185 #if !defined(TEXT_DOMAIN)
186 #define TEXT_DOMAIN "SYS_TEST"
187 #endif
188 (void) textdomain(TEXT_DOMAIN);
190 if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
191 (void) fprintf(stderr, gettext("6to4relay: error opening "
192 "dladm handle: %s\n"), dladm_status2str(status, errstr));
193 return (EXIT_FAILURE);
196 /* If no args are specified, print the current status. */
197 if (argc < 2) {
198 printkstatus();
199 return (EXIT_SUCCESS);
202 while ((ch = getopt(argc, argv, "ea:dh")) != EOF) {
203 switch (ch) {
204 case 'e':
205 eflag = B_TRUE;
206 break;
207 case 'd':
208 dflag = B_TRUE;
209 break;
210 case 'a':
211 aflag = B_TRUE;
212 relay_arg = optarg;
213 break;
214 case 'h':
215 usage();
216 return (EXIT_SUCCESS);
217 default:
218 usage();
219 return (EXIT_FAILURE);
223 * If -a is specified, -e must also be specified. Also, the
224 * combination of -e and -d is illegal. Fail on either case.
226 if ((aflag && !eflag) || (eflag && dflag)) {
227 usage();
228 return (EXIT_FAILURE);
232 * Enable Relay Router communication support in the kernel.
234 if (eflag) {
235 struct in_addr current_addr;
236 struct in_addr new_addr;
237 in6_addr_t v6_rt;
240 * if -a was not specified, the well-known anycast will
241 * be used.
243 if (!aflag) {
244 new_addr.s_addr = htonl(INADDR_6TO4RRANYCAST);
245 } else if (inet_pton(AF_INET, relay_arg, &new_addr) <= 0) {
246 (void) fprintf(stderr, gettext("6to4relay: input "
247 "address (%s) is not a valid IPv4 dotted-decimal "
248 "string.\n"), relay_arg);
249 return (EXIT_FAILURE);
252 status = dladm_iptun_get6to4relay(handle, &current_addr);
253 if (status != DLADM_STATUS_OK) {
254 (void) fprintf(stderr, gettext("6to4relay: "
255 "unable to obtain current 6to4 relay address: %s"),
256 dladm_status2str(status, errstr));
257 return (EXIT_FAILURE);
260 if (current_addr.s_addr == new_addr.s_addr)
261 return (EXIT_SUCCESS);
263 status = dladm_iptun_set6to4relay(handle, &new_addr);
264 if (status != DLADM_STATUS_OK) {
265 (void) fprintf(stderr, gettext("6to4relay: "
266 "unable to set the 6to4 relay router address: "
267 "%s\n"), dladm_status2str(status, errstr));
268 return (EXIT_FAILURE);
271 if (current_addr.s_addr != INADDR_ANY) {
272 /* remove old default IPv6 route */
273 IN6_V4ADDR_TO_6TO4(&current_addr, &v6_rt);
274 modifyroute(RTM_DELETE, &v6_rt);
277 IN6_V4ADDR_TO_6TO4(&new_addr, &v6_rt);
278 modifyroute(RTM_ADD, &v6_rt);
282 * Disable Relay Router communication support in kernel.
284 if (dflag) {
285 struct in_addr rr_addr;
286 in6_addr_t v6_rt;
289 * get Relay Router address from the kernel and delete
290 * default IPv6 route that was added for it.
292 status = dladm_iptun_get6to4relay(handle, &rr_addr);
293 if (status != DLADM_STATUS_OK) {
294 (void) fprintf(stderr, gettext("6to4relay: "
295 "unable to obtain current 6to4 relay address: %s"),
296 dladm_status2str(status, errstr));
297 return (EXIT_FAILURE);
299 if (rr_addr.s_addr == INADDR_ANY)
300 return (EXIT_SUCCESS);
302 IN6_V4ADDR_TO_6TO4(&rr_addr, &v6_rt);
303 modifyroute(RTM_DELETE, &v6_rt);
306 * INADDR_ANY (0.0.0.0) is used by the kernel to disable Relay
307 * Router communication support.
309 rr_addr.s_addr = INADDR_ANY;
310 status = dladm_iptun_set6to4relay(handle, &rr_addr);
311 if (status != DLADM_STATUS_OK) {
312 (void) fprintf(stderr, gettext("6to4relay: "
313 "unable to disable tunneling to 6to4 relay router: "
314 "%s\n"), dladm_status2str(status, errstr));
315 return (EXIT_FAILURE);
319 return (EXIT_SUCCESS);