]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/nc.c
configd-596.15.tar.gz
[apple/configd.git] / scutil.tproj / nc.c
CommitLineData
6bb65964 1/*
5e9ce69e 2 * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
6bb65964
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Modification History
26 *
27 * March 1, 2010 Christophe Allie <callie@apple.com>
28 * - initial revision
29 * February 8, 2011 Kevin Wells <kcw@apple.com>
30 * - added "select" command
17d3ee29
A
31 * January 2012 Kevin Wells <kcw@apple.com>
32 * - added arguments to "start" command to pass authentication credentials
33 * - "show" now takes a service name as an alternative to a service ID
34 * - fixes a bug whereby "IPv4" was being displayed as a subtype to IPsec services
35 * - improved format of "list" output
36 * - general cleanup of error messages and some variable names
6bb65964
A
37 */
38
39
40#include "scutil.h"
41#include "nc.h"
42#include "prefs.h"
43
5e9ce69e
A
44#include <SystemConfiguration/VPNConfiguration.h>
45
46#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
47#include <MobileInstallation/MobileInstallation.h>
48#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
49
6bb65964
A
50#include <sys/time.h>
51
5e9ce69e
A
52CFStringRef username = NULL;
53CFStringRef password = NULL;
54CFStringRef sharedsecret = NULL;
55
56static Boolean ondemandwatch = FALSE;
57static CFStringRef ondemand_nodename = NULL;
6bb65964 58
17d3ee29 59static SCNetworkConnectionRef connection = NULL;
6bb65964
A
60static int n_callback = 0;
61
62
63/* -----------------------------------------------------------------------------
64----------------------------------------------------------------------------- */
65static void
66my_CFRelease(void *t)
67{
68 void * * obj = (void * *)t;
69 if (obj && *obj) {
70 CFRelease(*obj);
71 *obj = NULL;
72 }
73 return;
74}
75
76/* -----------------------------------------------------------------------------
17d3ee29
A
77 ----------------------------------------------------------------------------- */
78static void
79nc_get_service_type_and_subtype(SCNetworkServiceRef service, CFStringRef *iftype, CFStringRef *ifsubtype) {
80 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
81 SCNetworkInterfaceRef child = SCNetworkInterfaceGetInterface(interface);
6bb65964 82
17d3ee29
A
83 *iftype = SCNetworkInterfaceGetInterfaceType(interface);
84 *ifsubtype = NULL;
85 if (CFEqual(*iftype, kSCNetworkInterfaceTypePPP) ||
86 CFEqual(*iftype, kSCNetworkInterfaceTypeVPN)) {
87 *ifsubtype = (child != NULL) ? SCNetworkInterfaceGetInterfaceType(child) : NULL;
6bb65964 88 }
6bb65964
A
89}
90
91/* -----------------------------------------------------------------------------
92 ----------------------------------------------------------------------------- */
93static SCNetworkServiceRef
94nc_copy_service(SCNetworkSetRef set, CFStringRef identifier)
95{
96 CFIndex i;
97 CFIndex n;
98 SCNetworkServiceRef selected = NULL;
99 CFArrayRef services;
100
101 services = SCNetworkConnectionCopyAvailableServices(set);
102 if (services == NULL) {
103 goto done;
104 }
105
106 n = CFArrayGetCount(services);
107
108 // try to select the service by its serviceID
109 for (i = 0; i < n; i++) {
110 SCNetworkServiceRef service = NULL;
111 CFStringRef serviceID;
112
113 service = CFArrayGetValueAtIndex(services, i);
114 serviceID = SCNetworkServiceGetServiceID(service);
115 if (CFEqual(identifier, serviceID)) {
116 selected = service;
117 goto done;
118 }
119 }
120
121 // try to select the service by service name
122 for (i = 0; i < n; i++) {
123 SCNetworkServiceRef service = NULL;
124 CFStringRef serviceName;
125
126 service = CFArrayGetValueAtIndex(services, i);
127 serviceName = SCNetworkServiceGetName(service);
128 if ((serviceName != NULL) && CFEqual(identifier, serviceName)) {
129 if (selected == NULL) {
130 selected = service;
131 } else {
132 // if multiple services match
133 selected = NULL;
17d3ee29 134 SCPrint(TRUE, stderr, CFSTR("Multiple services match\n"));
6bb65964
A
135 goto done;
136 }
137 }
138 }
139
17d3ee29 140done :
6bb65964
A
141
142 if (selected != NULL) CFRetain(selected);
143 if (services != NULL) CFRelease(services);
144 return selected;
145}
146
17d3ee29
A
147/* -----------------------------------------------------------------------------
148 ----------------------------------------------------------------------------- */
149static SCNetworkServiceRef
150nc_copy_service_from_arguments(int argc, char **argv, SCNetworkSetRef set) {
151 CFStringRef serviceID = NULL;
152 SCNetworkServiceRef service = NULL;
153
154 if (argc == 0) {
5e9ce69e 155 serviceID = _copyStringFromSTDIN(CFSTR("Service"), NULL);
17d3ee29
A
156 } else {
157 serviceID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
158 }
159 if (serviceID == NULL) {
160 SCPrint(TRUE, stderr, CFSTR("No service ID specified\n"));
161 return NULL;
162 }
163 service = nc_copy_service(set, serviceID);
164 my_CFRelease(&serviceID);
165 return service;
166}
167
6bb65964
A
168
169/* -----------------------------------------------------------------------------
170----------------------------------------------------------------------------- */
171static char *
172nc_status_string(SCNetworkConnectionStatus status)
173{
174 switch (status) {
175 case kSCNetworkConnectionInvalid:
176 return "Invalid";
177 case kSCNetworkConnectionDisconnected:
178 return "Disconnected";
179 case kSCNetworkConnectionConnecting:
180 return "Connecting";
181 case kSCNetworkConnectionConnected:
182 return "Connected";
183 case kSCNetworkConnectionDisconnecting:
184 return "Disconnecting";
185 }
186 return "Unknown";
187}
188
189static void
190nc_callback(SCNetworkConnectionRef connection, SCNetworkConnectionStatus status, void *info)
191{
192 int *n = (int *)info;
193 CFDictionaryRef status_dict;
194
195 // report status
196 if (n != NULL) {
197 if (*n == 0) {
198 SCPrint(TRUE, stdout, CFSTR("Current status = "));
199 } else {
200 struct tm tm_now;
201 struct timeval tv_now;
202
203 (void)gettimeofday(&tv_now, NULL);
204 (void)localtime_r(&tv_now.tv_sec, &tm_now);
205
206 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
207 tm_now.tm_hour,
208 tm_now.tm_min,
209 tm_now.tm_sec,
210 tv_now.tv_usec / 1000);
211 SCPrint(TRUE, stdout, CFSTR("Callback (%d) status = "), *n);
212 }
213 *n = *n + 1;
214 }
215 SCPrint(TRUE, stdout, CFSTR("%s%s%s\n"),
216 nc_status_string(status),
217 (status == kSCNetworkConnectionInvalid) ? ": " : "",
218 (status == kSCNetworkConnectionInvalid) ? SCErrorString(SCError()) : "");
219
220 // report extended status
221 status_dict = SCNetworkConnectionCopyExtendedStatus(connection);
222 if (status_dict) {
223 SCPrint(TRUE, stdout, CFSTR("Extended Status %@\n"), status_dict);
224 CFRelease(status_dict);
225 }
226
227 return;
228}
229
230static void
231nc_create_connection(int argc, char **argv, Boolean exit_on_failure)
232{
233 SCNetworkConnectionContext context = { 0, &n_callback, NULL, NULL, NULL };
234 SCNetworkServiceRef service;
6bb65964 235
17d3ee29 236 service = nc_copy_service_from_arguments(argc, argv, NULL);
6bb65964
A
237 if (service == NULL) {
238 SCPrint(TRUE, stderr, CFSTR("No service\n"));
239 if (exit_on_failure)
240 exit(1);
241 return;
242 }
243
17d3ee29
A
244 connection = SCNetworkConnectionCreateWithService(NULL, service, nc_callback, &context);
245 CFRelease(service);
246 if (connection == NULL) {
247 SCPrint(TRUE, stderr, CFSTR("Could not create connection: %s\n"), SCErrorString(SCError()));
6bb65964
A
248 if (exit_on_failure)
249 exit(1);
250 return;
251 }
252}
253
5e9ce69e
A
254/* -----------------------------------------------------------------------------
255 ----------------------------------------------------------------------------- */
256
257static void
258nc_trigger(int argc, char **argv)
259{
260 Boolean background = FALSE;
261 int i;
262 CFStringRef hostName = NULL;
263 int port = 80;
264
265 for (i = 0; i < 3 && i < argc; i++) {
266 /* Parse host name. Must be first arg. */
267 if (i == 0) {
268 hostName = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
269 continue;
270 }
271
272 /* Check for optional background flag */
273 if (strcmp(argv[i], "background") == 0) {
274 background = TRUE;
275 continue;
276 }
277
278 /* Parse optional port number */
279 CFStringRef str = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
280 if (str) {
281 int num = CFStringGetIntValue(str);
282 if (num) {
283 port = num;
284 }
285 my_CFRelease(&str);
286 }
287 }
288
289 if (hostName) {
290 CFReadStreamRef readStream = NULL;
291 CFWriteStreamRef writeStream = NULL;
292
293 CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostName, port, &readStream, &writeStream);
294
295 if (background) {
296 CFReadStreamSetProperty(readStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground"));
297 CFWriteStreamSetProperty(writeStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground"));
298 }
299
300 if (readStream && writeStream) {
301 CFReadStreamOpen(readStream);
302 CFWriteStreamOpen(writeStream);
303 SCPrint(TRUE, stdout, CFSTR("Opened stream to %@, port %d%s\n"), hostName, port, background ? ", background traffic class" : "");
304 sleep(1);
305 }
306
307 my_CFRelease(&readStream);
308 my_CFRelease(&writeStream);
309 } else {
310 SCPrint(TRUE, stderr, CFSTR("Invalid or missing host name\n"));
311 }
312
313 my_CFRelease(&hostName);
314
315 exit(0);
316}
317
6bb65964
A
318/* -----------------------------------------------------------------------------
319----------------------------------------------------------------------------- */
320static void
321nc_release_connection()
322{
17d3ee29 323 my_CFRelease(&connection);
6bb65964
A
324}
325
326/* -----------------------------------------------------------------------------
327----------------------------------------------------------------------------- */
328static void
329nc_start(int argc, char **argv)
330{
17d3ee29
A
331 CFMutableDictionaryRef userOptions = NULL;
332 CFStringRef iftype = NULL;
333 CFStringRef ifsubtype = NULL;
334 SCNetworkServiceRef service = NULL;
335
6bb65964
A
336 nc_create_connection(argc, argv, TRUE);
337
17d3ee29
A
338 service = SCNetworkConnectionGetService(connection);
339 nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
340
341 userOptions = CFDictionaryCreateMutable(NULL, 0,
342 &kCFTypeDictionaryKeyCallBacks,
343 &kCFTypeDictionaryValueCallBacks);
6bb65964 344
17d3ee29
A
345 Boolean isL2TP = (CFEqual(iftype, kSCEntNetPPP) &&
346 (ifsubtype != NULL) && CFEqual(ifsubtype, kSCValNetInterfaceSubTypeL2TP));
347
348 if (CFEqual(iftype, kSCEntNetPPP)) {
349 CFMutableDictionaryRef pppEntity = CFDictionaryCreateMutable(NULL, 0,
350 &kCFTypeDictionaryKeyCallBacks,
351 &kCFTypeDictionaryValueCallBacks);
352
353 if (username != NULL) {
354 CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthName, username);
355 }
356 if (password != NULL) {
357 CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthPassword, password);
358 }
359 CFDictionarySetValue(userOptions, kSCEntNetPPP, pppEntity);
360 my_CFRelease(&pppEntity);
361 }
362 if (CFEqual(iftype, kSCEntNetIPSec) || isL2TP) {
363 CFMutableDictionaryRef ipsecEntity = CFDictionaryCreateMutable(NULL, 0,
364 &kCFTypeDictionaryKeyCallBacks,
365 &kCFTypeDictionaryValueCallBacks);
366 if (!isL2TP) {
367 if (username != NULL) {
368 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthName, username);
369 }
370 if (password != NULL) {
371 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthPassword, password);
372 }
373 }
374 if (sharedsecret != NULL) {
375 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecSharedSecret, sharedsecret);
376 }
377 CFDictionarySetValue(userOptions, kSCEntNetIPSec, ipsecEntity);
378 my_CFRelease(&ipsecEntity);
379 }
380 if (CFEqual(iftype, kSCEntNetVPN)) {
381 CFMutableDictionaryRef vpnEntity = CFDictionaryCreateMutable(NULL, 0,
382 &kCFTypeDictionaryKeyCallBacks,
383 &kCFTypeDictionaryValueCallBacks);
384 if (username != NULL) {
385 CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthName, username);
386 }
387 if (password != NULL) {
388 CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthPassword, password);
389 }
390 CFDictionarySetValue(userOptions, kSCEntNetVPN, vpnEntity);
391 my_CFRelease(&vpnEntity);
392 }
393 // If it doesn't match any VPN type, fail silently
394
395 if (!SCNetworkConnectionStart(connection, userOptions, TRUE)) {
396 SCPrint(TRUE, stderr, CFSTR("Could not start connection: %s\n"), SCErrorString(SCError()));
397 exit(1);
398 };
399
400 CFRelease(userOptions);
6bb65964
A
401 nc_release_connection();
402 exit(0);
403}
404
405/* -----------------------------------------------------------------------------
406----------------------------------------------------------------------------- */
407static void
408nc_stop(int argc, char **argv)
409{
410 nc_create_connection(argc, argv, TRUE);
411
17d3ee29
A
412 if (!SCNetworkConnectionStop(connection, TRUE)) {
413 SCPrint(TRUE, stderr, CFSTR("Could not stop connection: %s\n"), SCErrorString(SCError()));
414 exit(1);
415 };
6bb65964
A
416
417 nc_release_connection();
418 exit(0);
419}
420
421/* -----------------------------------------------------------------------------
422 ----------------------------------------------------------------------------- */
423static void
424nc_suspend(int argc, char **argv)
425{
426 nc_create_connection(argc, argv, TRUE);
427
17d3ee29 428 SCNetworkConnectionSuspend(connection);
6bb65964
A
429
430 nc_release_connection();
431 exit(0);
432}
433
434/* -----------------------------------------------------------------------------
435 ----------------------------------------------------------------------------- */
436static void
437nc_resume(int argc, char **argv)
438{
439 nc_create_connection(argc, argv, TRUE);
440
17d3ee29 441 SCNetworkConnectionResume(connection);
6bb65964
A
442
443 nc_release_connection();
444 exit(0);
445}
446
447/* -----------------------------------------------------------------------------
448----------------------------------------------------------------------------- */
449static void
450nc_status(int argc, char **argv)
451{
452 SCNetworkConnectionStatus status;
453
454 nc_create_connection(argc, argv, TRUE);
455
17d3ee29
A
456 status = SCNetworkConnectionGetStatus(connection);
457 nc_callback(connection, status, NULL);
6bb65964
A
458
459 nc_release_connection();
460 exit(0);
461}
462
463static void
464nc_watch(int argc, char **argv)
465{
466 SCNetworkConnectionStatus status;
467
468 nc_create_connection(argc, argv, TRUE);
469
17d3ee29 470 status = SCNetworkConnectionGetStatus(connection);
6bb65964
A
471
472 // report initial status
473 n_callback = 0;
17d3ee29 474 nc_callback(connection, status, &n_callback);
6bb65964
A
475
476 // setup watcher
477 if (doDispatch) {
5e9ce69e 478 if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_main_queue())) {
17d3ee29 479 SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
6bb65964
A
480 exit(1);
481 }
482 } else {
17d3ee29
A
483 if (!SCNetworkConnectionScheduleWithRunLoop(connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
484 SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
6bb65964
A
485 exit(1);
486 }
487 }
488
489 // wait for changes
490 CFRunLoopRun();
491
492 nc_release_connection();
493 exit(0);
494}
495
496/* -----------------------------------------------------------------------------
497----------------------------------------------------------------------------- */
498static void
499nc_statistics(int argc, char **argv)
500{
501 CFDictionaryRef stats_dict;
502
503 nc_create_connection(argc, argv, TRUE);
504
17d3ee29 505 stats_dict = SCNetworkConnectionCopyStatistics(connection);
6bb65964
A
506
507 if (stats_dict) {
508 SCPrint(TRUE, stdout, CFSTR("%@\n"), stats_dict);
509 } else {
510 SCPrint(TRUE, stdout, CFSTR("No statistics available\n"));
511 }
512
513 my_CFRelease(&stats_dict);
514
515 nc_release_connection();
516 exit(0);
517}
518
519/* -----------------------------------------------------------------------------
520----------------------------------------------------------------------------- */
17d3ee29
A
521static void
522checkOnDemandHost(SCDynamicStoreRef store, CFStringRef nodeName, Boolean retry)
523{
524 Boolean ok;
525 CFStringRef connectionServiceID = NULL;
526 SCNetworkConnectionStatus connectionStatus = 0;
527 CFStringRef vpnRemoteAddress = NULL;
528
529 SCPrint(TRUE, stdout, CFSTR("OnDemand host/domain check (%sretry)\n"), retry ? "" : "no ");
530
531 ok = __SCNetworkConnectionCopyOnDemandInfoWithName(&store,
532 nodeName,
533 retry,
534 &connectionServiceID,
535 &connectionStatus,
536 &vpnRemoteAddress);
537
538 if (ok) {
539 SCPrint(TRUE, stdout, CFSTR(" serviceID = %@\n"), connectionServiceID);
540 SCPrint(TRUE, stdout, CFSTR(" remote address = %@\n"), vpnRemoteAddress);
541 } else if (SCError() != kSCStatusOK) {
542 SCPrint(TRUE, stdout, CFSTR("%sretry\n"), retry ? "" : "no ");
543 SCPrint(TRUE, stdout,
544 CFSTR(" Unable to copy OnDemand information for connection: %s\n"),
545 SCErrorString(SCError()));
546 } else {
547 SCPrint(TRUE, stdout, CFSTR(" no match\n"));
548 }
549
550 if (connectionServiceID != NULL) {
551 CFRelease(connectionServiceID);
552 connectionServiceID = NULL;
553 }
554 if (vpnRemoteAddress != NULL) {
555 CFRelease(vpnRemoteAddress);
556 vpnRemoteAddress = NULL;
557 }
558
559 return;
560}
561
5e9ce69e
A
562static void
563nc_ondemand_callback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
564{
565 CFStringRef key = NULL;
566 CFDictionaryRef ondemand_dict = NULL;
567 struct tm tm_now;
568 struct timeval tv_now;
569
570 if (CFArrayGetCount(changedKeys) < 1) {
571 return;
572 }
573
574 (void)gettimeofday(&tv_now, NULL);
575 (void)localtime_r(&tv_now.tv_sec, &tm_now);
576
577 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
578 tm_now.tm_hour,
579 tm_now.tm_min,
580 tm_now.tm_sec,
581 tv_now.tv_usec / 1000);
582
583 if (ondemand_nodename) {
584 checkOnDemandHost(store, ondemand_nodename, FALSE);
585 checkOnDemandHost(store, ondemand_nodename, TRUE);
586 } else {
587 key = CFArrayGetValueAtIndex(changedKeys, 0);
588
589 ondemand_dict = SCDynamicStoreCopyValue(store, key);
590 if (ondemand_dict) {
591 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
592 } else {
593 SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
594 }
595
596 my_CFRelease(&ondemand_dict);
597 }
598}
599
6bb65964
A
600static void
601nc_ondemand(int argc, char **argv)
602{
603 int exit_code = 1;
604 CFStringRef key = NULL;
605 CFDictionaryRef ondemand_dict = NULL;
606 SCDynamicStoreRef store;
607
5e9ce69e 608 store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), nc_ondemand_callback, NULL);
6bb65964 609 if (store == NULL) {
17d3ee29 610 SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
6bb65964
A
611 goto done;
612 }
613
5e9ce69e
A
614 if (argc == 1) {
615#if !TARGET_IPHONE_SIMULATOR
616 if (strcmp("--refresh", argv[0]) == 0) {
617 SCNetworkConnectionRef connection = NULL;
618
619 connection = SCNetworkConnectionCreate(kCFAllocatorDefault, NULL, NULL);
620 if (connection && SCNetworkConnectionRefreshOnDemandState(connection)) {
621 exit_code = 0;
622 }
623
624 if (exit_code) {
625 SCPrint(TRUE, stderr, CFSTR("Unable to refresh OnDemand state: %s\n"), SCErrorString(SCError()));
626 }
17d3ee29 627
5e9ce69e
A
628 my_CFRelease(&connection);
629 goto done;
630 }
631#endif // !TARGET_IPHONE_SIMULATOR
632
633 ondemand_nodename = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
634 } else if (argc != 0) {
635 SCPrint(TRUE, stderr, CFSTR("Usage: scutil --nc ondemand [-W] [hostname]\n"
636 " scutil --nc ondemand -- --refresh\n"));
6bb65964
A
637 goto done;
638 }
639
17d3ee29
A
640 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
641
5e9ce69e
A
642 if (ondemand_nodename) {
643 checkOnDemandHost(store, ondemand_nodename, FALSE);
644 checkOnDemandHost(store, ondemand_nodename, TRUE);
6bb65964 645 } else {
5e9ce69e
A
646 ondemand_dict = SCDynamicStoreCopyValue(store, key);
647 if (ondemand_dict) {
648 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
649 } else {
650 SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
651 }
652 }
653
654 if (ondemandwatch) {
655 CFMutableArrayRef keys = NULL;
656
657 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
658 CFArrayAppendValue(keys, key);
659 SCDynamicStoreSetNotificationKeys(store, keys, NULL);
660
661 my_CFRelease(&keys);
662
663 SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue());
664
665 CFRunLoopRun();
6bb65964
A
666 }
667
668 exit_code = 0;
669done:
670 my_CFRelease(&ondemand_dict);
671 my_CFRelease(&key);
672 my_CFRelease(&store);
5e9ce69e 673 my_CFRelease(&ondemand_nodename);
6bb65964
A
674 exit(exit_code);
675}
676
17d3ee29 677
6bb65964 678/* -----------------------------------------------------------------------------
17d3ee29 679 ----------------------------------------------------------------------------- */
17d3ee29 680CFStringRef
5e9ce69e 681copy_padded_string(CFStringRef original, int width, CFStringRef prefix, CFStringRef suffix)
6bb65964 682{
17d3ee29 683 CFMutableStringRef padded;
6bb65964 684
5e9ce69e
A
685 padded = CFStringCreateMutable(NULL, 0);
686 if (prefix != NULL) {
687 CFStringAppend(padded, prefix);
688 }
689 if (original != NULL) {
690 CFStringAppend(padded, original);
691 }
692 if (suffix != NULL) {
693 CFStringAppend(padded, suffix);
694 }
17d3ee29
A
695 CFStringPad(padded, CFSTR(" "), MAX(CFStringGetLength(original), width), 0);
696 return padded;
697}
6bb65964 698
5e9ce69e
A
699CFStringRef
700copy_VPN_status(SCNetworkServiceRef service)
701{
702 CFStringRef output = NULL;
703 SCNetworkConnectionStatus status = kSCNetworkConnectionInvalid;
704 SCNetworkConnectionRef service_connection = NULL;
705
706 /* Only calculate status is the service is enabled. Default is invalid. */
707 if (SCNetworkServiceGetEnabled(service)) {
708 service_connection = SCNetworkConnectionCreateWithService(NULL, service, NULL, NULL);
709 if (service_connection == NULL) goto done;
710 status = SCNetworkConnectionGetStatus(service_connection);
711 }
712
713 output = CFStringCreateWithCString(NULL, nc_status_string(status), kCFStringEncodingUTF8);
714
715done:
716 my_CFRelease(&service_connection);
717 return output;
718}
17d3ee29
A
719
720static void
721nc_print_VPN_service(SCNetworkServiceRef service)
722{
5e9ce69e
A
723 SCNetworkInterfaceRef interface = NULL;
724 CFStringRef display_name = NULL;
725 CFStringRef display_name_padded = NULL;
726 CFStringRef service_id = NULL;
727 CFStringRef service_name = NULL;
728 CFStringRef service_name_padded = NULL;
729 CFStringRef service_status = NULL;
730 CFStringRef service_status_padded = NULL;
17d3ee29 731 CFStringRef sub_type = NULL;
5e9ce69e 732 CFStringRef type = NULL;
17d3ee29
A
733
734 nc_get_service_type_and_subtype(service, &type, &sub_type);
735
5e9ce69e
A
736 service_name = SCNetworkServiceGetName(service);
737 service_name_padded = copy_padded_string(service_name, 32, CFSTR("\""), CFSTR("\""));
17d3ee29 738
5e9ce69e 739 service_id = SCNetworkServiceGetServiceID(service);
17d3ee29 740
5e9ce69e
A
741 interface = SCNetworkServiceGetInterface(service);
742 display_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
743 display_name_padded = copy_padded_string(display_name, 18, NULL, NULL);
744
745 service_status = copy_VPN_status(service);
746 service_status_padded = copy_padded_string(service_status, 16, CFSTR("("), CFSTR(")"));
17d3ee29
A
747
748 SCPrint(TRUE,
749 stdout,
5e9ce69e 750 CFSTR("%@ %@ %@ %@ %@ [%@%@%@]\n"),
17d3ee29 751 SCNetworkServiceGetEnabled(service) ? CFSTR("*") : CFSTR(" "),
5e9ce69e 752 service_status_padded,
17d3ee29
A
753 service_id,
754 display_name_padded,
755 service_name_padded,
756 type,
757 (sub_type == NULL) ? CFSTR("") : CFSTR(":"),
758 (sub_type == NULL) ? CFSTR("") : sub_type);
5e9ce69e 759
17d3ee29
A
760 CFRelease(display_name_padded);
761 CFRelease(service_name_padded);
5e9ce69e
A
762 CFRelease(service_status_padded);
763 my_CFRelease(&service_status);
6bb65964
A
764}
765
766
767/* -----------------------------------------------------------------------------
768----------------------------------------------------------------------------- */
769static void
770nc_list(int argc, char **argv)
771{
772 int count;
6bb65964 773 int i;
6bb65964 774 CFArrayRef services = NULL;
6bb65964 775
17d3ee29 776 SCPrint(TRUE, stdout, CFSTR("Available network connection services in the current set (*=enabled):\n"));
6bb65964
A
777 services = SCNetworkConnectionCopyAvailableServices(NULL);
778 if (services != NULL) {
779 count = CFArrayGetCount(services);
780
781 for (i = 0; i < count; i++) {
782 SCNetworkServiceRef service;
6bb65964
A
783
784 service = CFArrayGetValueAtIndex(services, i);
17d3ee29 785 nc_print_VPN_service(service);
6bb65964
A
786 }
787
6bb65964 788 }
6bb65964 789 my_CFRelease(&services);
17d3ee29 790 exit(0);
6bb65964
A
791}
792
5e9ce69e
A
793/* -----------------------------------------------------------------------------
794 ----------------------------------------------------------------------------- */
795static Boolean
796nc_enable_vpntype(CFStringRef vpnType)
797{
798 Boolean is_enabled = FALSE;
799 Boolean success = FALSE;
800
801 if (vpnType == NULL) {
802 SCPrint(TRUE, stderr, CFSTR("No VPN type provided\n"));
803 goto done;
804 }
805
806 is_enabled = VPNConfigurationIsVPNTypeEnabled(vpnType);
807
808 if (is_enabled) {
809 SCPrint(TRUE, stdout, CFSTR("VPN is already enabled\n"));
810 } else {
811#if !TARGET_OS_IPHONE
812 AuthorizationRef authorization;
813
814 authorization = _prefs_AuthorizationCreate();
815 if ((authorization == NULL) ||
816 !VPNConfigurationSetAuthorization(authorization)) {
817 SCPrint(TRUE, stderr, CFSTR("VPNConfigurationSetAuthorization failed: %s\n"), SCErrorString(SCError()));
818 goto done;
819 }
820#endif // !TARGET_OS_IPHONE
821
822 if (!VPNConfigurationEnableVPNType(vpnType)) {
823 SCPrint(TRUE, stderr, CFSTR("VPN could not be enabled: %s\n"), SCErrorString(SCError()));
824 goto done;
825 }
826
827#if !TARGET_OS_IPHONE
828 _prefs_AuthorizationFree(authorization);
829#endif // !TARGET_OS_IPHONE
830
831 SCPrint(TRUE, stdout, CFSTR("VPN enabled\n"));
832 }
833 success = TRUE;
834
835done:
836 return success;
837}
838
839/* Turns a service ID or name into a vendor type, or preserves type */
840static CFStringRef
841nc_copy_vendor_type (CFStringRef input)
842{
843 SCNetworkInterfaceRef child;
844 SCNetworkInterfaceRef interface;
845 CFStringRef output_name = input;
846 SCNetworkServiceRef service = NULL;
847 CFStringRef type;
848
849 if (input == NULL) {
850 goto done;
851 }
852
853 service = nc_copy_service(NULL, input);
854 if (service != NULL) {
855 interface = SCNetworkServiceGetInterface(service);
856 child = SCNetworkInterfaceGetInterface(interface);
857 type = SCNetworkInterfaceGetInterfaceType(interface);
858
859 /* Must be of type VPN */
860 if (!CFEqual(type, kSCNetworkInterfaceTypeVPN)) {
861 output_name = NULL;
862 goto done;
863 }
864 output_name = SCNetworkInterfaceGetInterfaceType(child);
865 goto done;
866 }
867
868done :
869 if (output_name != NULL) CFRetain(output_name);
870 my_CFRelease(&service);
871 return output_name;
872}
873
874/* -----------------------------------------------------------------------------
875 ----------------------------------------------------------------------------- */
876#if !TARGET_OS_IPHONE
877static const CFStringRef PREF_PREFIX = CFSTR("VPN-");
878static const CFStringRef PREF_SUFFIX = CFSTR(".plist");
879static void
880nc_set_application_url(CFStringRef subtype, CFStringRef directory)
881{
882 CFURLRef directory_url = NULL;
883 CFDataRef directory_url_data = NULL;
884 CFStringRef vpnprefpath = NULL;
885 char *path = NULL;
886 CFIndex path_len = 0;
887
888 if (subtype == NULL || directory == NULL) {
889 goto done;
890 }
891
892 directory_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
893 directory,
894 kCFURLPOSIXPathStyle,
895 FALSE);
896 if (directory_url == NULL) {
897 SCPrint(TRUE, stderr, CFSTR("CFURLCreateWithFileSystemPath failed\n"));
898 goto done;
899 }
900
901 directory_url_data = CFURLCreateBookmarkData(NULL, directory_url, 0, 0, 0, 0);
902 if (directory_url_data == NULL) {
903 SCPrint(TRUE, stderr, CFSTR("CFURLCreateBookmarkData failed\n"));
904 goto done;
905 }
906
907 vpnprefpath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"), PREF_PREFIX, subtype, PREF_SUFFIX );
908 if (vpnprefpath == NULL) {
909 SCPrint(TRUE, stderr, CFSTR("CFStringCreateWithFormat failed\n"));
910 goto done;
911 }
912
913 path_len = CFStringGetLength(vpnprefpath) + 1;
914 path = malloc(path_len);
915 if (path == NULL) {
916 goto done;
917 }
918
919 if (!CFStringGetCString(vpnprefpath, path, path_len, kCFStringEncodingASCII)) {
920 SCPrint(TRUE, stderr, CFSTR("CFStringGetCString failed\n"));
921 goto done;
922 }
923
924 do_prefs_init(); /* initialization */
925 do_prefs_open(1, &path); /* open prefs */
926
927 if (!SCPreferencesSetValue(prefs, CFSTR("ApplicationURL"), directory_url_data)) {
928 SCPrint(TRUE, stderr,
929 CFSTR("SCPreferencesSetValue ApplicationURL failed, %s\n"),
930 SCErrorString(SCError()));
931 goto done;
932 }
933
934 _prefs_save();
935
936done:
937 my_CFRelease(&directory_url);
938 my_CFRelease(&directory_url_data);
939 my_CFRelease(&vpnprefpath);
940 if (path) {
941 free(path);
942 }
943 _prefs_close();
944
945 exit(0);
946}
947#endif
948
949/* -----------------------------------------------------------------------------
950 ----------------------------------------------------------------------------- */
951static void
952nc_enablevpn(int argc, char **argv)
953{
954 CFStringRef argument = NULL;
955 CFStringRef vendorType = NULL;
956 int exit_code = 1;
957
958 if (argc == 0) {
959 SCPrint(TRUE, stderr, CFSTR("No service type or ID\n"));
960 } else {
961 argument = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
962 vendorType = nc_copy_vendor_type(argument);
963 my_CFRelease(&argument);
964
965 if (!nc_enable_vpntype(vendorType)) {
966 goto done;
967 }
968#if !TARGET_OS_IPHONE
969 if (argc >= 2) {
970 argument = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
971 nc_set_application_url(vendorType, argument);
972 my_CFRelease(&argument);
973 }
974#endif
975 }
976
977 exit_code = 0;
978
979done:
980 my_CFRelease(&vendorType);
981 exit(exit_code);
982}
983
984
985#if TARGET_OS_EMBEDDED
986static void
987nc_print_VPN_app_info(CFStringRef appInfo, CFDictionaryRef appInfoDict)
988{
989 CFStringRef appName = NULL;
990 Boolean isEnabled = FALSE;
991 CFStringRef paddedAppInfo = NULL;
992 CFStringRef paddedAppName = NULL;
993
994 if (appInfo == NULL) {
995 return;
996 }
997
998 isEnabled = VPNConfigurationIsVPNTypeEnabled(appInfo);
999
1000 CFDictionaryGetValueIfPresent(appInfoDict, CFSTR("CFBundleDisplayName"), (const void **)&appName);
1001 paddedAppName = copy_padded_string((appName == NULL) ? CFSTR("") : appName, 12, NULL, NULL);
1002 paddedAppInfo = copy_padded_string(appInfo, 30, NULL, NULL);
1003
1004 SCPrint(TRUE, stdout, CFSTR("%@ %@ [%@]\n"),
1005 isEnabled ? CFSTR("(Enabled) ") : CFSTR("(Disabled)"),
1006 paddedAppName,
1007 appInfo);
1008
1009 my_CFRelease(&paddedAppName);
1010 my_CFRelease(&paddedAppInfo);
1011}
1012#endif
1013
1014/* -----------------------------------------------------------------------------
1015 ----------------------------------------------------------------------------- */
1016#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
1017static void
1018nc_listvpn(int argc, char **argv)
1019{
1020
1021 CFDictionaryRef appDict = NULL;
1022 CFArrayRef appinfo = NULL;
1023 int i, j, count, subtypecount;
1024 const void * * keys = NULL;
1025 CFMutableDictionaryRef optionsDict = NULL;
1026 const void * * values = NULL;
1027 CFStringRef vpntype = NULL;
1028
1029 optionsDict = CFDictionaryCreateMutable(NULL, 0,
1030 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1031 CFDictionarySetValue(optionsDict, kLookupApplicationTypeKey, kApplicationTypeUser);
1032 CFDictionarySetValue(optionsDict, kLookupAttributeKey, CFSTR("UIVPNPlugin"));
1033
1034 appDict = MobileInstallationLookup(optionsDict);
1035 if (!isA_CFDictionary(appDict))
1036 goto done;
1037
1038 count = CFDictionaryGetCount(appDict);
1039 if (count > 0) {
1040 keys = (const void * *)malloc(sizeof(CFTypeRef) * count);
1041 values = (const void * *)malloc(sizeof(CFTypeRef) * count);
1042
1043 CFDictionaryGetKeysAndValues(appDict, keys, values);
1044 for (i=0; i<count; i++) {
1045 appinfo = CFDictionaryGetValue(values[i], CFSTR("UIVPNPlugin"));
1046 if (appinfo) {
1047
1048
1049
1050 if (isA_CFString(appinfo)) {
1051 nc_print_VPN_app_info((CFStringRef)appinfo, (CFDictionaryRef)values[i]);
1052 }
1053 else if (isA_CFArray(appinfo)) {
1054 subtypecount = CFArrayGetCount((CFArrayRef)appinfo);
1055 for(j=0; j<subtypecount; j++) {
1056 vpntype = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)appinfo, j);
1057 nc_print_VPN_app_info(vpntype, (CFDictionaryRef)values[i]);
1058 }
1059 }
1060 }
1061 }
1062 }
1063done:
1064 if (keys) free(keys);
1065 if (values) free(values);
1066 my_CFRelease(&optionsDict);
1067 my_CFRelease(&appDict);
1068
1069 exit(0);
1070}
1071#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
17d3ee29 1072
6bb65964
A
1073/* -----------------------------------------------------------------------------
1074----------------------------------------------------------------------------- */
1075static void
1076nc_show(int argc, char **argv)
1077{
5e9ce69e
A
1078 SCNetworkServiceRef service = NULL;
1079 SCDynamicStoreRef store = NULL;
1080 int exit_code = 1;
1081 CFStringRef serviceID = NULL;
1082 CFStringRef iftype = NULL;
1083 CFStringRef ifsubtype = NULL;
1084 CFStringRef type_entity_key = NULL;
1085 CFStringRef subtype_entity_key = NULL;
1086 CFDictionaryRef type_entity_dict = NULL;
1087 CFDictionaryRef subtype_entity_dict = NULL;
1088 CFStringRef vpnprefpath = NULL;
1089#if !TARGET_OS_IPHONE
1090 CFDataRef bookmarkData = NULL;
1091 CFURLRef directory = NULL;
1092 Boolean isStale = FALSE;
1093 char *path = NULL;
1094 CFIndex path_len = 0;
1095#endif
6bb65964 1096
17d3ee29
A
1097 service = nc_copy_service_from_arguments(argc, argv, NULL);
1098 if (service == NULL) {
1099 SCPrint(TRUE, stderr, CFSTR("No service\n"));
1100 exit(exit_code);
6bb65964
A
1101 }
1102
17d3ee29 1103 serviceID = SCNetworkServiceGetServiceID(service);
6bb65964 1104
17d3ee29 1105 nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
6bb65964
A
1106
1107 if (!CFEqual(iftype, kSCEntNetPPP) &&
17d3ee29
A
1108 !CFEqual(iftype, kSCEntNetIPSec) &&
1109 !CFEqual(iftype, kSCEntNetVPN)) {
1110 SCPrint(TRUE, stderr, CFSTR("Not a connection oriented service: %@\n"), serviceID);
6bb65964
A
1111 goto done;
1112 }
1113
17d3ee29
A
1114 type_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, iftype);
1115
1116 nc_print_VPN_service(service);
6bb65964 1117
5e9ce69e
A
1118#if !TARGET_OS_IPHONE
1119 vpnprefpath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"), PREF_PREFIX, ifsubtype, PREF_SUFFIX);
1120 if (vpnprefpath == NULL) {
1121 goto skipURL;
1122 }
1123
1124 path_len = CFStringGetLength(vpnprefpath) + 1;
1125 path = malloc(path_len);
1126 if (path == NULL) {
1127 goto skipURL;
1128 }
1129
1130 if (!CFStringGetCString(vpnprefpath, path, path_len, kCFStringEncodingASCII)) {
1131 SCPrint(TRUE, stderr, CFSTR("CFStringGetCString failed\n"));
1132 goto done;
1133 }
1134
1135 do_prefs_init(); /* initialization */
1136 do_prefs_open(1, &path); /* open prefs */
1137
1138 bookmarkData = SCPreferencesGetValue(prefs, CFSTR("ApplicationURL"));
1139 if (bookmarkData == NULL) {
1140 goto skipURL;
1141 }
1142
1143 directory = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, bookmarkData, 0, NULL, NULL, &isStale, NULL);
1144 if (directory == NULL) {
1145 goto skipURL;
1146 }
1147
1148 SCPrint(TRUE, stdout, CFSTR("ApplicationURL: %@\n"), directory);
1149skipURL:
1150#endif
1151
17d3ee29
A
1152 store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
1153 if (store == NULL) {
1154 SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
6bb65964
A
1155 goto done;
1156 }
1157 type_entity_dict = SCDynamicStoreCopyValue(store, type_entity_key);
17d3ee29 1158
6bb65964 1159 if (!type_entity_dict) {
17d3ee29 1160 SCPrint(TRUE, stderr, CFSTR("No \"%@\" configuration available\n"), iftype);
6bb65964
A
1161 } else {
1162 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), iftype, type_entity_dict);
1163 }
1164
1165 if (ifsubtype) {
17d3ee29 1166 subtype_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, ifsubtype);
6bb65964
A
1167 subtype_entity_dict = SCDynamicStoreCopyValue(store, subtype_entity_key);
1168 if (!subtype_entity_dict) {
1169 //
1170 }
1171 else {
1172 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), ifsubtype, subtype_entity_dict);
1173 }
1174 }
1175
1176 exit_code = 0;
1177
1178done:
6bb65964
A
1179 my_CFRelease(&type_entity_key);
1180 my_CFRelease(&type_entity_dict);
1181 my_CFRelease(&subtype_entity_key);
1182 my_CFRelease(&subtype_entity_dict);
6bb65964 1183 my_CFRelease(&store);
17d3ee29 1184 my_CFRelease(&service);
5e9ce69e
A
1185 my_CFRelease(&vpnprefpath);
1186 _prefs_close();
6bb65964
A
1187 exit(exit_code);
1188}
1189
1190/* -----------------------------------------------------------------------------
1191 ----------------------------------------------------------------------------- */
1192static void
1193nc_select(int argc, char **argv)
1194{
1195 SCNetworkSetRef current_set;
1196 int exit_code = 1;
1197 SCNetworkServiceRef service = NULL;
6bb65964
A
1198 Boolean status;
1199
6bb65964
A
1200 do_prefs_init(); /* initialization */
1201 do_prefs_open(0, NULL); /* open default prefs */
1202
1203 current_set = SCNetworkSetCopyCurrent(prefs);
1204 if (current_set == NULL) {
17d3ee29 1205 SCPrint(TRUE, stderr, CFSTR("No current location\n"), SCErrorString(SCError()));
6bb65964
A
1206 goto done;
1207 }
1208
17d3ee29 1209 service = nc_copy_service_from_arguments(argc, argv, current_set);
6bb65964 1210 if (service == NULL) {
17d3ee29 1211 SCPrint(TRUE, stderr, CFSTR("No service\n"));
6bb65964
A
1212 goto done;
1213 }
1214
1215#if !TARGET_OS_IPHONE
1216 status = SCNetworkServiceSetEnabled(service, TRUE);
1217 if (!status) {
17d3ee29 1218 SCPrint(TRUE, stderr, CFSTR("Unable to enable service: %s\n"), SCErrorString(SCError()));
6bb65964
A
1219 goto done;
1220 }
1221#else
1222 status = SCNetworkSetSetSelectedVPNService(current_set, service);
1223 if (!status) {
17d3ee29 1224 SCPrint(TRUE, stderr, CFSTR("Unable to select service: %s\n"), SCErrorString(SCError()));
6bb65964
A
1225 goto done;
1226 }
1227#endif
1228
1229 _prefs_save();
1230 exit_code = 0;
1231done:
17d3ee29 1232 my_CFRelease(&service);
6bb65964
A
1233 my_CFRelease(&current_set);
1234 _prefs_close();
1235 exit(exit_code);
1236}
1237
5e9ce69e
A
1238/* -----------------------------------------------------------------------------
1239 ----------------------------------------------------------------------------- */
1240static void
1241nc_help(int argc, char **argv)
1242{
1243 SCPrint(TRUE, stderr, CFSTR("Valid commands for scutil --nc (VPN connections)\n"));
1244 SCPrint(TRUE, stderr, CFSTR("Usage: scutil --nc [command]\n"));
1245 SCPrint(TRUE, stderr, CFSTR("\n"));
1246 SCPrint(TRUE, stderr, CFSTR("\tlist\n"));
1247 SCPrint(TRUE, stderr, CFSTR("\t\tList available network connection services in the current set\n"));
1248 SCPrint(TRUE, stderr, CFSTR("\n"));
1249 SCPrint(TRUE, stderr, CFSTR("\tstatus <service>\n"));
1250 SCPrint(TRUE, stderr, CFSTR("\t\tIndicate whether a given service is connected, as well as extended status information for the service\n"));
1251 SCPrint(TRUE, stderr, CFSTR("\n"));
1252 SCPrint(TRUE, stderr, CFSTR("\tshow <service>\n"));
1253 SCPrint(TRUE, stderr, CFSTR("\t\tDisplay configuration information for a given service\n"));
1254 SCPrint(TRUE, stderr, CFSTR("\n"));
1255 SCPrint(TRUE, stderr, CFSTR("\tstatistics <service>\n"));
1256 SCPrint(TRUE, stderr, CFSTR("\t\tProvide statistics on bytes, packets, and errors for a given service\n"));
1257 SCPrint(TRUE, stderr, CFSTR("\n"));
1258 SCPrint(TRUE, stderr, CFSTR("\tselect <service>\n"));
1259 SCPrint(TRUE, stderr, CFSTR("\t\tMake the given service active in the current set. This allows it to be started\n"));
1260 SCPrint(TRUE, stderr, CFSTR("\n"));
1261 SCPrint(TRUE, stderr, CFSTR("\tstart <service> [--user user] [--password password] [--secret secret]\n"));
1262 SCPrint(TRUE, stderr, CFSTR("\t\tStart a given service. Can take optional arguments for user, password, and secret\n"));
1263 SCPrint(TRUE, stderr, CFSTR("\n"));
1264 SCPrint(TRUE, stderr, CFSTR("\tstop <service>\n"));
1265 SCPrint(TRUE, stderr, CFSTR("\t\tStop a given service\n"));
1266 SCPrint(TRUE, stderr, CFSTR("\n"));
1267 SCPrint(TRUE, stderr, CFSTR("\tsuspend <service>\n"));
1268 SCPrint(TRUE, stderr, CFSTR("\t\tSuspend a given service (PPP, Modem on Hold)\n"));
1269 SCPrint(TRUE, stderr, CFSTR("\n"));
1270 SCPrint(TRUE, stderr, CFSTR("\tresume <service>\n"));
1271 SCPrint(TRUE, stderr, CFSTR("\t\tResume a given service (PPP, Modem on Hold)\n"));
1272 SCPrint(TRUE, stderr, CFSTR("\n"));
1273 SCPrint(TRUE, stderr, CFSTR("\tondemand [-W] [hostname]\n"));
1274 SCPrint(TRUE, stderr, CFSTR("\tondemand -- --refresh\n"));
1275 SCPrint(TRUE, stderr, CFSTR("\t\tDisplay VPN on-demand information\n"));
1276 SCPrint(TRUE, stderr, CFSTR("\n"));
1277 SCPrint(TRUE, stderr, CFSTR("\ttrigger <hostname> [background] [port]\n"));
1278 SCPrint(TRUE, stderr, CFSTR("\t\tTrigger VPN on-demand with specified hostname, and optional port and background flag\n"));
1279 SCPrint(TRUE, stderr, CFSTR("\n"));
1280#if TARGET_OS_EMBEDDED
1281 SCPrint(TRUE, stderr, CFSTR("\tlistvpn\n"));
1282 SCPrint(TRUE, stderr, CFSTR("\t\tDisplay the installed VPN applications\n"));
1283 SCPrint(TRUE, stderr, CFSTR("\n"));
1284#endif
1285#if !TARGET_OS_IPHONE
1286 SCPrint(TRUE, stderr, CFSTR("\tenablevpn <service or vpn type> [path]\n"));
1287 SCPrint(TRUE, stderr, CFSTR("\t\tEnables the given VPN application type. Takes either a service or VPN type. Pass a path to set ApplicationURL\n"));
1288 SCPrint(TRUE, stderr, CFSTR("\n"));
1289#else
1290 SCPrint(TRUE, stderr, CFSTR("\tenablevpn <service or vpn type>\n"));
1291 SCPrint(TRUE, stderr, CFSTR("\t\tEnables the given VPN application type. Takes either a service or VPN type\n"));
1292 SCPrint(TRUE, stderr, CFSTR("\n"));
1293#endif
1294 SCPrint(TRUE, stderr, CFSTR("\tdisablevpn <service or vpn type>\n"));
1295 SCPrint(TRUE, stderr, CFSTR("\t\tDisables the given VPN application type. Takes either a service or VPN type\n"));
1296 SCPrint(TRUE, stderr, CFSTR("\n"));
1297 SCPrint(TRUE, stderr, CFSTR("\thelp\n"));
1298 SCPrint(TRUE, stderr, CFSTR("\t\tDisplay available commands for --nc\n"));
1299 SCPrint(TRUE, stderr, CFSTR("\n"));
1300 exit(0);
1301}
1302
6bb65964
A
1303/* -----------------------------------------------------------------------------
1304----------------------------------------------------------------------------- */
1305typedef void (*nc_func) (int argc, char **argv);
1306
1307static const struct {
1308 char *cmd;
1309 nc_func func;
1310} nc_cmds[] = {
5e9ce69e
A
1311 { "enablevpn", nc_enablevpn },
1312 { "help", nc_help },
6bb65964 1313 { "list", nc_list },
5e9ce69e
A
1314#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
1315 { "listvpn", nc_listvpn },
1316#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
6bb65964
A
1317 { "ondemand", nc_ondemand },
1318 { "resume", nc_resume },
1319 { "select", nc_select },
1320 { "show", nc_show },
1321 { "start", nc_start },
1322 { "statistics", nc_statistics },
1323 { "status", nc_status },
1324 { "stop", nc_stop },
1325 { "suspend", nc_suspend },
5e9ce69e 1326 { "trigger", nc_trigger },
6bb65964
A
1327};
1328#define N_NC_CMNDS (sizeof(nc_cmds) / sizeof(nc_cmds[0]))
1329
1330
1331/* -----------------------------------------------------------------------------
1332----------------------------------------------------------------------------- */
1333int
1334find_nc_cmd(char *cmd)
1335{
1336 int i;
1337
1338 for (i = 0; i < (int)N_NC_CMNDS; i++) {
1339 if (strcmp(cmd, nc_cmds[i].cmd) == 0) {
1340 return i;
1341 }
1342 }
1343
1344 return -1;
1345}
1346
1347
1348/* -----------------------------------------------------------------------------
1349----------------------------------------------------------------------------- */
1350void
1351do_nc_cmd(char *cmd, int argc, char **argv, Boolean watch)
1352{
1353 int i;
1354
1355 i = find_nc_cmd(cmd);
1356 if (i >= 0) {
1357 nc_func func;
1358
1359 func = nc_cmds[i].func;
5e9ce69e
A
1360 if (watch) {
1361 if (func == nc_status) {
1362 func = nc_watch;
1363 } else if (func == nc_ondemand) {
1364 ondemandwatch = TRUE;
1365 }
6bb65964
A
1366 }
1367 (*func)(argc, argv);
1368 }
1369 return;
1370}
1371