]> git.saurik.com Git - apple/network_cmds.git/blob - ip6conf.tproj/ip6tool.c
37f7846e26a5abb620b2b5fc7b13322d5f25a31f
[apple/network_cmds.git] / ip6conf.tproj / ip6tool.c
1 /* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 *
24 */
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/errno.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
32 #include <net/if.h>
33 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <netinet6/in6_var.h>
36 #include <ifaddrs.h>
37
38 /* From netinet6/in6_var.h */
39 #ifndef SIOCPROTOATTACH_IN6
40 #define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq) /* attach proto to interface */
41 #endif
42 #ifndef SIOCPROTODETACH_IN6
43 #define SIOCPROTODETACH_IN6 _IOWR('i', 111, struct in6_ifreq) /* detach proto from interface */
44 #endif
45 #ifndef SIOCLL_START
46 #define SIOCLL_START _IOWR('i', 130, struct in6_aliasreq) /* start aquiring linklocal on interface */
47 #endif
48 #ifndef SIOCLL_STOP
49 #define SIOCLL_STOP _IOWR('i', 131, struct in6_ifreq) /* deconfigure linklocal from interface */
50 #endif
51
52 /* options */
53 #define IPv6_STARTUP 1
54 #define IPv6_SHUTDOWN 2
55 #define IPv6_STARTUP_ALL 3
56 #define IPv6_SHUTDOWN_ALL 4
57
58 const char *if_exceptions[] = {"lo0", "gif0", "faith0", "stf0"};
59
60 extern char *optarg;
61
62 void do_usage(void);
63 int do_protoattach(int s, char *name);
64 int do_protodetach(int s, char *name);
65 void do_protoattach_all(int s);
66 void do_protodetach_all(int s);
67
68
69 int
70 main(int argc, char **argv)
71 {
72 int s,
73 ch,
74 option = 0,
75 err;
76 char *interface = NULL;
77
78 if ((ch = getopt(argc, argv, "u:d:ax")) != -1) {
79 switch (ch) {
80 case 'u':
81 /* option -u: start up proto */
82 option = IPv6_STARTUP;
83 interface = optarg;
84 break;
85 case 'd':
86 /* option -d: shut down proto */
87 option = IPv6_SHUTDOWN;
88 interface = optarg;
89 break;
90 case 'a':
91 /* option -a: start up proto on all interfaces */
92 option = IPv6_STARTUP_ALL;
93 break;
94 case 'x':
95 /* option -x: shut down proto on all interfaces */
96 option = IPv6_SHUTDOWN_ALL;
97 break;
98 default:
99 break;
100 }
101 }
102
103 if (!option) {
104 do_usage();
105 return 0;
106 }
107
108 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
109 err = s;
110 printf("%s: Error %d creating socket.\n", argv[0], err);
111 return 0;
112 }
113
114 switch (option) {
115 case IPv6_STARTUP:
116 err = do_protoattach(s, interface);
117 if (err < 0)
118 printf("%s: Error %d encountered attaching interface %s.\n", argv[0], err, interface);
119
120 break;
121 case IPv6_SHUTDOWN:
122 err = do_protodetach(s, interface);
123 if (err < 0)
124 printf("%s: Error %d encountered detaching interface %s.\n", argv[0], err, interface);
125
126 break;
127 case IPv6_STARTUP_ALL:
128 do_protoattach_all(s);
129
130 break;
131 case IPv6_SHUTDOWN_ALL:
132 do_protodetach_all(s);
133
134 break;
135 default:
136 break;
137 }
138
139 close(s);
140
141 return 0;
142 }
143
144 void
145 do_usage(void)
146 {
147 printf("Usage: \n\
148 Start up IPv6 on ALL interfaces: -a\n\
149 Shut down IPv6 on ALL interfaces: -x\n\
150 Start up IPv6 on given interface: -u [interface]\n\
151 Shut down IPv6 on given interface: -d [interface].\n");
152 }
153
154 int
155 do_protoattach(int s, char *name)
156 {
157 struct in6_aliasreq ifr;
158 int err;
159
160 bzero(&ifr, sizeof(ifr));
161 strncpy(ifr.ifra_name, name, sizeof(ifr.ifra_name));
162
163 if ((err = ioctl(s, SIOCPROTOATTACH_IN6, &ifr)) != 0)
164 return (err);
165
166 return (ioctl(s, SIOCLL_START, &ifr));
167 }
168
169 int
170 do_protodetach(int s, char *name)
171 {
172 struct in6_ifreq ifr;
173 int err;
174
175 bzero(&ifr, sizeof(ifr));
176 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
177
178 if ((err = ioctl(s, SIOCLL_STOP, &ifr)) != 0)
179 return (err);
180
181 return (ioctl(s, SIOCPROTODETACH_IN6, &ifr));
182 }
183
184 void
185 do_protoattach_all(int s)
186 {
187 struct ifaddrs *ifaddrs, *ifa;
188
189 if (getifaddrs(&ifaddrs)) {
190 printf("ip6: getifaddrs returned error (%s)", strerror(errno));
191 }
192
193 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
194 /* skip over invalid interfaces */
195 if ((strcmp(ifa->ifa_name, if_exceptions[0])))
196 if (strcmp(ifa->ifa_name, if_exceptions[1]))
197 if (strcmp(ifa->ifa_name, if_exceptions[2]))
198 if (strcmp(ifa->ifa_name, if_exceptions[3])) {
199 /* this is a valid interface */
200 if (do_protoattach(s, ifa->ifa_name)) {
201 printf("ip6: error attaching %s\n", ifa->ifa_name);
202 }
203
204 while (ifa->ifa_next != NULL &&
205 !(strcmp(ifa->ifa_name, ifa->ifa_next->ifa_name))) {
206 /* skip multiple entries for same interface */
207 ifa = ifa->ifa_next;
208 }
209 }
210 }
211
212 freeifaddrs(ifaddrs);
213
214 return;
215 }
216
217 void
218 do_protodetach_all(int s)
219 {
220 struct ifaddrs *ifaddrs, *ifa;
221
222 if (getifaddrs(&ifaddrs)) {
223 printf("ip6: getifaddrs returned error (%s)", strerror(errno));
224 }
225
226 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
227 /* skip over invalid interfaces */
228 if ((strcmp(ifa->ifa_name, if_exceptions[0])))
229 if (strcmp(ifa->ifa_name, if_exceptions[1]))
230 if (strcmp(ifa->ifa_name, if_exceptions[2]))
231 if (strcmp(ifa->ifa_name, if_exceptions[3])) {
232 /* this is a valid interface */
233 if (do_protodetach(s, ifa->ifa_name)) {
234 printf("ip6: error detaching %s\n", ifa->ifa_name);
235 }
236
237 while (ifa->ifa_next != NULL &&
238 !(strcmp(ifa->ifa_name, ifa->ifa_next->ifa_name))) {
239 /* skip multiple entries for same interface */
240 ifa = ifa->ifa_next;
241 }
242 }
243 }
244
245 freeifaddrs(ifaddrs);
246
247 return;
248 }