2 * Copyright (c) 2000-2003 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>
49 do_checkReachability(int argc
, char **argv
)
51 SCNetworkConnectionFlags flags
= 0;
52 SCNetworkReachabilityRef target
= NULL
;
55 struct sockaddr_in sin
;
56 struct sockaddr_in6 sin6
;
58 bzero(&sin
, sizeof(sin
));
59 sin
.sin_len
= sizeof(sin
);
60 sin
.sin_family
= AF_INET
;
62 bzero(&sin6
, sizeof(sin6
));
63 sin6
.sin6_len
= sizeof(sin6
);
64 sin6
.sin6_family
= AF_INET6
;
66 if (inet_aton(argv
[0], &sin
.sin_addr
) == 1) {
67 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
68 } else if (inet_pton(AF_INET6
, argv
[0], &sin6
.sin6_addr
) == 1) {
71 p
= strchr(argv
[0], '%');
73 sin6
.sin6_scope_id
= if_nametoindex(p
+1);
76 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin6
);
78 target
= SCNetworkReachabilityCreateWithName(NULL
, argv
[0]);
80 } else /* if (argc == 2) */ {
81 struct sockaddr_in l_sin
;
82 struct sockaddr_in r_sin
;
84 bzero(&l_sin
, sizeof(l_sin
));
85 l_sin
.sin_len
= sizeof(l_sin
);
86 l_sin
.sin_family
= AF_INET
;
87 if (inet_aton(argv
[0], &l_sin
.sin_addr
) == 0) {
88 SCPrint(TRUE
, stderr
, CFSTR("Could not interpret address \"%s\"\n"), argv
[0]);
92 bzero(&r_sin
, sizeof(r_sin
));
93 r_sin
.sin_len
= sizeof(r_sin
);
94 r_sin
.sin_family
= AF_INET
;
95 if (inet_aton(argv
[1], &r_sin
.sin_addr
) == 0) {
96 SCPrint(TRUE
, stderr
, CFSTR("Could not interpret address \"%s\"\n"), argv
[1]);
100 target
= SCNetworkReachabilityCreateWithAddressPair(NULL
,
101 (struct sockaddr
*)&l_sin
,
102 (struct sockaddr
*)&r_sin
);
106 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
110 if (!SCNetworkReachabilityGetFlags(target
, &flags
)) {
111 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
115 SCPrint(_sc_debug
, stdout
, CFSTR("flags = 0x%x"), flags
);
117 SCPrint(_sc_debug
, stdout
, CFSTR(" ("));
118 if (flags
& kSCNetworkFlagsReachable
) {
119 SCPrint(TRUE
, stdout
, CFSTR("Reachable"));
120 flags
&= ~kSCNetworkFlagsReachable
;
121 SCPrint(flags
!= 0, stdout
, CFSTR(","));
123 if (flags
& kSCNetworkFlagsTransientConnection
) {
124 SCPrint(TRUE
, stdout
, CFSTR("Transient Connection"));
125 flags
&= ~kSCNetworkFlagsTransientConnection
;
126 SCPrint(flags
!= 0, stdout
, CFSTR(","));
128 if (flags
& kSCNetworkFlagsConnectionRequired
) {
129 SCPrint(TRUE
, stdout
, CFSTR("Connection Required"));
130 flags
&= ~kSCNetworkFlagsConnectionRequired
;
131 SCPrint(flags
!= 0, stdout
, CFSTR(","));
133 if (flags
& kSCNetworkFlagsConnectionAutomatic
) {
134 SCPrint(TRUE
, stdout
, CFSTR("Connection Automatic"));
135 flags
&= ~kSCNetworkFlagsConnectionAutomatic
;
136 SCPrint(flags
!= 0, stdout
, CFSTR(","));
138 if (flags
& kSCNetworkFlagsInterventionRequired
) {
139 SCPrint(TRUE
, stdout
, CFSTR("Intervention Required"));
140 flags
&= ~kSCNetworkFlagsInterventionRequired
;
141 SCPrint(flags
!= 0, stdout
, CFSTR(","));
143 if (flags
& kSCNetworkFlagsIsLocalAddress
) {
144 SCPrint(TRUE
, stdout
, CFSTR("Local Address"));
145 flags
&= ~kSCNetworkFlagsIsLocalAddress
;
146 SCPrint(flags
!= 0, stdout
, CFSTR(","));
148 if (flags
& kSCNetworkFlagsIsDirect
) {
149 SCPrint(TRUE
, stdout
, CFSTR("Directly Reachable Address"));
150 flags
&= ~kSCNetworkFlagsIsDirect
;
151 SCPrint(flags
!= 0, stdout
, CFSTR(","));
153 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
155 SCPrint(_sc_debug
, stdout
, CFSTR(" ("));
156 SCPrint(TRUE
, stdout
, CFSTR("Not Reachable"));
157 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
159 SCPrint(TRUE
, stdout
, CFSTR("\n"));
165 do_snapshot(int argc
, char **argv
)
167 if (!SCDynamicStoreSnapshot(store
)) {
168 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
182 waitTimeout(int sigraised
)
189 do_wait(char *waitKey
, int timeout
)
191 struct itimerval itv
;
193 CFMutableArrayRef keys
;
195 store
= SCDynamicStoreCreate(NULL
, CFSTR("scutil (wait)"), waitKeyFound
, NULL
);
197 SCPrint(TRUE
, stderr
,
198 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
202 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
203 key
= CFStringCreateWithCString(NULL
, waitKey
, kCFStringEncodingMacRoman
);
204 CFArrayAppendValue(keys
, key
);
206 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
)) {
207 SCPrint(TRUE
, stderr
,
208 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
212 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
214 SCPrint(TRUE
, stderr
,
215 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
219 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
221 value
= SCDynamicStoreCopyValue(store
, key
);
223 /* if the key is already present */
228 if (waitTimeout
> 0) {
229 signal(SIGALRM
, waitTimeout
);
230 bzero(&itv
, sizeof(itv
));
231 itv
.it_value
.tv_sec
= timeout
;
232 if (setitimer(ITIMER_REAL
, &itv
, NULL
) < 0) {
233 SCPrint(TRUE
, stderr
,
234 CFSTR("setitimer() failed: %s\n"), strerror(errno
));