2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * July 9, 2001 Allan Nathanson <ajn@apple.com>
30 * - added "-r" option for checking network reachability
31 * - added "-w" option to check/wait for the presence of a
34 * June 1, 2001 Allan Nathanson <ajn@apple.com>
35 * - public API conversion
37 * November 9, 2000 Allan Nathanson <ajn@apple.com>
46 #include <netinet/in.h>
47 #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"));
167 do_snapshot(int argc
, char **argv
)
169 if (!SCDynamicStoreSnapshot(store
)) {
170 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
184 waitTimeout(int sigraised
)
191 do_wait(char *waitKey
, int timeout
)
193 struct itimerval itv
;
195 CFMutableArrayRef keys
;
197 store
= SCDynamicStoreCreate(NULL
, CFSTR("scutil (wait)"), waitKeyFound
, NULL
);
199 SCPrint(TRUE
, stderr
,
200 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
204 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
205 key
= CFStringCreateWithCString(NULL
, waitKey
, kCFStringEncodingMacRoman
);
206 CFArrayAppendValue(keys
, key
);
208 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
)) {
209 SCPrint(TRUE
, stderr
,
210 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
214 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
216 SCPrint(TRUE
, stderr
,
217 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
221 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
223 value
= SCDynamicStoreCopyValue(store
, key
);
225 /* if the key is already present */
230 if (waitTimeout
> 0) {
231 signal(SIGALRM
, waitTimeout
);
232 bzero(&itv
, sizeof(itv
));
233 itv
.it_value
.tv_sec
= timeout
;
234 if (setitimer(ITIMER_REAL
, &itv
, NULL
) < 0) {
235 SCPrint(TRUE
, stderr
,
236 CFSTR("setitimer() failed: %s\n"), strerror(errno
));