2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * July 9, 2001 Allan Nathanson <ajn@apple.com>
28 * - added "-r" option for checking network reachability
29 * - added "-w" option to check/wait for the presence of a
32 * June 1, 2001 Allan Nathanson <ajn@apple.com>
33 * - public API conversion
35 * November 9, 2000 Allan Nathanson <ajn@apple.com>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
51 do_checkReachability(int argc
, char **argv
)
53 SCNetworkConnectionFlags flags
= 0;
54 SCNetworkReachabilityRef target
= NULL
;
57 struct sockaddr_in sin
;
58 struct sockaddr_in6 sin6
;
60 bzero(&sin
, sizeof(sin
));
61 sin
.sin_len
= sizeof(sin
);
62 sin
.sin_family
= AF_INET
;
64 bzero(&sin6
, sizeof(sin6
));
65 sin6
.sin6_len
= sizeof(sin6
);
66 sin6
.sin6_family
= AF_INET6
;
68 if (inet_aton(argv
[0], &sin
.sin_addr
) == 1) {
69 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
70 } else if (inet_pton(AF_INET6
, argv
[0], &sin6
.sin6_addr
) == 1) {
73 p
= strchr(argv
[0], '%');
75 sin6
.sin6_scope_id
= if_nametoindex(p
+1);
78 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin6
);
80 target
= SCNetworkReachabilityCreateWithName(NULL
, argv
[0]);
82 } else /* if (argc == 2) */ {
83 struct sockaddr_in l_sin
;
84 struct sockaddr_in r_sin
;
86 bzero(&l_sin
, sizeof(l_sin
));
87 l_sin
.sin_len
= sizeof(l_sin
);
88 l_sin
.sin_family
= AF_INET
;
89 if (inet_aton(argv
[0], &l_sin
.sin_addr
) == 0) {
90 SCPrint(TRUE
, stderr
, CFSTR("Could not interpret address \"%s\"\n"), argv
[0]);
94 bzero(&r_sin
, sizeof(r_sin
));
95 r_sin
.sin_len
= sizeof(r_sin
);
96 r_sin
.sin_family
= AF_INET
;
97 if (inet_aton(argv
[1], &r_sin
.sin_addr
) == 0) {
98 SCPrint(TRUE
, stderr
, CFSTR("Could not interpret address \"%s\"\n"), argv
[1]);
102 target
= SCNetworkReachabilityCreateWithAddressPair(NULL
,
103 (struct sockaddr
*)&l_sin
,
104 (struct sockaddr
*)&r_sin
);
108 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
112 if (!SCNetworkReachabilityGetFlags(target
, &flags
)) {
113 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
117 SCPrint(_sc_debug
, stdout
, CFSTR("flags = 0x%x"), flags
);
119 SCPrint(_sc_debug
, stdout
, CFSTR(" ("));
120 if (flags
& kSCNetworkFlagsReachable
) {
121 SCPrint(TRUE
, stdout
, CFSTR("Reachable"));
122 flags
&= ~kSCNetworkFlagsReachable
;
123 SCPrint(flags
!= 0, stdout
, CFSTR(","));
125 if (flags
& kSCNetworkFlagsTransientConnection
) {
126 SCPrint(TRUE
, stdout
, CFSTR("Transient Connection"));
127 flags
&= ~kSCNetworkFlagsTransientConnection
;
128 SCPrint(flags
!= 0, stdout
, CFSTR(","));
130 if (flags
& kSCNetworkFlagsConnectionRequired
) {
131 SCPrint(TRUE
, stdout
, CFSTR("Connection Required"));
132 flags
&= ~kSCNetworkFlagsConnectionRequired
;
133 SCPrint(flags
!= 0, stdout
, CFSTR(","));
135 if (flags
& kSCNetworkFlagsConnectionAutomatic
) {
136 SCPrint(TRUE
, stdout
, CFSTR("Connection Automatic"));
137 flags
&= ~kSCNetworkFlagsConnectionAutomatic
;
138 SCPrint(flags
!= 0, stdout
, CFSTR(","));
140 if (flags
& kSCNetworkFlagsInterventionRequired
) {
141 SCPrint(TRUE
, stdout
, CFSTR("Intervention Required"));
142 flags
&= ~kSCNetworkFlagsInterventionRequired
;
143 SCPrint(flags
!= 0, stdout
, CFSTR(","));
145 if (flags
& kSCNetworkFlagsIsLocalAddress
) {
146 SCPrint(TRUE
, stdout
, CFSTR("Local Address"));
147 flags
&= ~kSCNetworkFlagsIsLocalAddress
;
148 SCPrint(flags
!= 0, stdout
, CFSTR(","));
150 if (flags
& kSCNetworkFlagsIsDirect
) {
151 SCPrint(TRUE
, stdout
, CFSTR("Directly Reachable Address"));
152 flags
&= ~kSCNetworkFlagsIsDirect
;
153 SCPrint(flags
!= 0, stdout
, CFSTR(","));
155 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
157 SCPrint(_sc_debug
, stdout
, CFSTR(" ("));
158 SCPrint(TRUE
, stdout
, CFSTR("Not Reachable"));
159 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
161 SCPrint(TRUE
, stdout
, CFSTR("\n"));
168 do_showDNSConfiguration(int argc
, char **argv
)
170 dns_config_t
*dns_config
;
172 dns_config
= dns_configuration_copy();
176 SCPrint(TRUE
, stdout
, CFSTR("DNS configuration\n"));
178 for (n
= 0; n
< dns_config
->n_resolver
; n
++) {
180 dns_resolver_t
*resolver
= dns_config
->resolver
[n
];
182 SCPrint(TRUE
, stdout
, CFSTR("\nresolver #%d\n"), n
+ 1);
184 if (resolver
->domain
!= NULL
) {
185 SCPrint(TRUE
, stdout
, CFSTR(" domain : %s\n"), resolver
->domain
);
188 for (i
= 0; i
< resolver
->n_search
; i
++) {
189 SCPrint(TRUE
, stdout
, CFSTR(" search domain[%d] : %s\n"), i
, resolver
->search
[i
]);
192 for (i
= 0; i
< resolver
->n_nameserver
; i
++) {
195 _SC_sockaddr_to_string(resolver
->nameserver
[i
], buf
, sizeof(buf
));
196 SCPrint(TRUE
, stdout
, CFSTR(" nameserver[%d] : %s\n"), i
, buf
);
199 for (i
= 0; i
< resolver
->n_sortaddr
; i
++) {
200 SCPrint(TRUE
, stdout
, CFSTR(" sortaddr[%d] : %s/%s\n"),
202 inet_ntoa(resolver
->sortaddr
[i
]->address
),
203 inet_ntoa(resolver
->sortaddr
[i
]->mask
));
206 if (resolver
->options
!= NULL
) {
207 SCPrint(TRUE
, stdout
, CFSTR(" options : %s\n"), resolver
->options
);
210 if (resolver
->port
!= 0) {
211 SCPrint(TRUE
, stdout
, CFSTR(" port : %hd\n"), resolver
->port
);
214 if (resolver
->timeout
!= 0) {
215 SCPrint(TRUE
, stdout
, CFSTR(" timeout : %d\n"), resolver
->timeout
);
218 if (resolver
->search_order
!= 0) {
219 SCPrint(TRUE
, stdout
, CFSTR(" order : %d\n"), resolver
->search_order
);
223 dns_configuration_free(dns_config
);
225 SCPrint(TRUE
, stdout
, CFSTR("No DNS configuration available\n"));
234 do_showProxyConfiguration(int argc
, char **argv
)
236 CFDictionaryRef proxies
;
238 proxies
= SCDynamicStoreCopyProxies(NULL
);
239 if (proxies
!= NULL
) {
240 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), proxies
);
242 SCPrint(TRUE
, stdout
, CFSTR("No proxy configuration available\n"));
251 do_snapshot(int argc
, char **argv
)
253 if (!SCDynamicStoreSnapshot(store
)) {
254 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
268 waitTimeout(int sigraised
)
276 do_wait(char *waitKey
, int timeout
)
278 struct itimerval itv
;
280 CFMutableArrayRef keys
;
282 store
= SCDynamicStoreCreate(NULL
, CFSTR("scutil (wait)"), waitKeyFound
, NULL
);
284 SCPrint(TRUE
, stderr
,
285 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
289 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
290 key
= CFStringCreateWithCString(NULL
, waitKey
, kCFStringEncodingUTF8
);
291 CFArrayAppendValue(keys
, key
);
293 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
)) {
294 SCPrint(TRUE
, stderr
,
295 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
299 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
301 SCPrint(TRUE
, stderr
,
302 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
306 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
308 value
= SCDynamicStoreCopyValue(store
, key
);
310 /* if the key is already present */
316 signal(SIGALRM
, waitTimeout
);
317 bzero(&itv
, sizeof(itv
));
318 itv
.it_value
.tv_sec
= timeout
;
319 if (setitimer(ITIMER_REAL
, &itv
, NULL
) < 0) {
320 SCPrint(TRUE
, stderr
,
321 CFSTR("setitimer() failed: %s\n"), strerror(errno
));