]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/nc.c
configd-453.16.tar.gz
[apple/configd.git] / scutil.tproj / nc.c
1 /*
2 * Copyright (c) 2010-2012 Apple Inc. All rights reserved.
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
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
37 */
38
39
40 #include "scutil.h"
41 #include "nc.h"
42 #include "prefs.h"
43
44 #include <sys/time.h>
45
46 CFStringRef username = NULL;
47 CFStringRef password = NULL;
48 CFStringRef sharedsecret = NULL;
49
50 static SCNetworkConnectionRef connection = NULL;
51 static int n_callback = 0;
52
53
54 /* -----------------------------------------------------------------------------
55 ----------------------------------------------------------------------------- */
56 static void
57 my_CFRelease(void *t)
58 {
59 void * * obj = (void * *)t;
60 if (obj && *obj) {
61 CFRelease(*obj);
62 *obj = NULL;
63 }
64 return;
65 }
66
67 /* -----------------------------------------------------------------------------
68 ----------------------------------------------------------------------------- */
69 static void
70 nc_get_service_type_and_subtype(SCNetworkServiceRef service, CFStringRef *iftype, CFStringRef *ifsubtype) {
71 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
72 SCNetworkInterfaceRef child = SCNetworkInterfaceGetInterface(interface);
73
74 *iftype = SCNetworkInterfaceGetInterfaceType(interface);
75 *ifsubtype = NULL;
76 if (CFEqual(*iftype, kSCNetworkInterfaceTypePPP) ||
77 CFEqual(*iftype, kSCNetworkInterfaceTypeVPN)) {
78 *ifsubtype = (child != NULL) ? SCNetworkInterfaceGetInterfaceType(child) : NULL;
79 }
80 }
81
82 /* -----------------------------------------------------------------------------
83 ----------------------------------------------------------------------------- */
84 static SCNetworkServiceRef
85 nc_copy_service(SCNetworkSetRef set, CFStringRef identifier)
86 {
87 CFIndex i;
88 CFIndex n;
89 SCNetworkServiceRef selected = NULL;
90 CFArrayRef services;
91
92 services = SCNetworkConnectionCopyAvailableServices(set);
93 if (services == NULL) {
94 goto done;
95 }
96
97 n = CFArrayGetCount(services);
98
99 // try to select the service by its serviceID
100 for (i = 0; i < n; i++) {
101 SCNetworkServiceRef service = NULL;
102 CFStringRef serviceID;
103
104 service = CFArrayGetValueAtIndex(services, i);
105 serviceID = SCNetworkServiceGetServiceID(service);
106 if (CFEqual(identifier, serviceID)) {
107 selected = service;
108 goto done;
109 }
110 }
111
112 // try to select the service by service name
113 for (i = 0; i < n; i++) {
114 SCNetworkServiceRef service = NULL;
115 CFStringRef serviceName;
116
117 service = CFArrayGetValueAtIndex(services, i);
118 serviceName = SCNetworkServiceGetName(service);
119 if ((serviceName != NULL) && CFEqual(identifier, serviceName)) {
120 if (selected == NULL) {
121 selected = service;
122 } else {
123 // if multiple services match
124 selected = NULL;
125 SCPrint(TRUE, stderr, CFSTR("Multiple services match\n"));
126 goto done;
127 }
128 }
129 }
130
131 done :
132
133 if (selected != NULL) CFRetain(selected);
134 if (services != NULL) CFRelease(services);
135 return selected;
136 }
137
138 /* -----------------------------------------------------------------------------
139 ----------------------------------------------------------------------------- */
140 static SCNetworkServiceRef
141 nc_copy_service_from_arguments(int argc, char **argv, SCNetworkSetRef set) {
142 CFStringRef serviceID = NULL;
143 SCNetworkServiceRef service = NULL;
144
145 if (argc == 0) {
146 serviceID = _copyStringFromSTDIN();
147 } else {
148 serviceID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
149 }
150 if (serviceID == NULL) {
151 SCPrint(TRUE, stderr, CFSTR("No service ID specified\n"));
152 return NULL;
153 }
154 service = nc_copy_service(set, serviceID);
155 my_CFRelease(&serviceID);
156 return service;
157 }
158
159
160 /* -----------------------------------------------------------------------------
161 ----------------------------------------------------------------------------- */
162 static char *
163 nc_status_string(SCNetworkConnectionStatus status)
164 {
165 switch (status) {
166 case kSCNetworkConnectionInvalid:
167 return "Invalid";
168 case kSCNetworkConnectionDisconnected:
169 return "Disconnected";
170 case kSCNetworkConnectionConnecting:
171 return "Connecting";
172 case kSCNetworkConnectionConnected:
173 return "Connected";
174 case kSCNetworkConnectionDisconnecting:
175 return "Disconnecting";
176 }
177 return "Unknown";
178 }
179
180 static void
181 nc_callback(SCNetworkConnectionRef connection, SCNetworkConnectionStatus status, void *info)
182 {
183 int *n = (int *)info;
184 CFDictionaryRef status_dict;
185
186 // report status
187 if (n != NULL) {
188 if (*n == 0) {
189 SCPrint(TRUE, stdout, CFSTR("Current status = "));
190 } else {
191 struct tm tm_now;
192 struct timeval tv_now;
193
194 (void)gettimeofday(&tv_now, NULL);
195 (void)localtime_r(&tv_now.tv_sec, &tm_now);
196
197 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
198 tm_now.tm_hour,
199 tm_now.tm_min,
200 tm_now.tm_sec,
201 tv_now.tv_usec / 1000);
202 SCPrint(TRUE, stdout, CFSTR("Callback (%d) status = "), *n);
203 }
204 *n = *n + 1;
205 }
206 SCPrint(TRUE, stdout, CFSTR("%s%s%s\n"),
207 nc_status_string(status),
208 (status == kSCNetworkConnectionInvalid) ? ": " : "",
209 (status == kSCNetworkConnectionInvalid) ? SCErrorString(SCError()) : "");
210
211 // report extended status
212 status_dict = SCNetworkConnectionCopyExtendedStatus(connection);
213 if (status_dict) {
214 SCPrint(TRUE, stdout, CFSTR("Extended Status %@\n"), status_dict);
215 CFRelease(status_dict);
216 }
217
218 return;
219 }
220
221 static void
222 nc_create_connection(int argc, char **argv, Boolean exit_on_failure)
223 {
224 SCNetworkConnectionContext context = { 0, &n_callback, NULL, NULL, NULL };
225 SCNetworkServiceRef service;
226
227 service = nc_copy_service_from_arguments(argc, argv, NULL);
228 if (service == NULL) {
229 SCPrint(TRUE, stderr, CFSTR("No service\n"));
230 if (exit_on_failure)
231 exit(1);
232 return;
233 }
234
235 connection = SCNetworkConnectionCreateWithService(NULL, service, nc_callback, &context);
236 CFRelease(service);
237 if (connection == NULL) {
238 SCPrint(TRUE, stderr, CFSTR("Could not create connection: %s\n"), SCErrorString(SCError()));
239 if (exit_on_failure)
240 exit(1);
241 return;
242 }
243 }
244
245 /* -----------------------------------------------------------------------------
246 ----------------------------------------------------------------------------- */
247 static void
248 nc_release_connection()
249 {
250 my_CFRelease(&connection);
251 }
252
253 /* -----------------------------------------------------------------------------
254 ----------------------------------------------------------------------------- */
255 static void
256 nc_start(int argc, char **argv)
257 {
258 CFMutableDictionaryRef userOptions = NULL;
259 CFStringRef iftype = NULL;
260 CFStringRef ifsubtype = NULL;
261 SCNetworkServiceRef service = NULL;
262
263 nc_create_connection(argc, argv, TRUE);
264
265 service = SCNetworkConnectionGetService(connection);
266 nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
267
268 userOptions = CFDictionaryCreateMutable(NULL, 0,
269 &kCFTypeDictionaryKeyCallBacks,
270 &kCFTypeDictionaryValueCallBacks);
271
272 Boolean isL2TP = (CFEqual(iftype, kSCEntNetPPP) &&
273 (ifsubtype != NULL) && CFEqual(ifsubtype, kSCValNetInterfaceSubTypeL2TP));
274
275 if (CFEqual(iftype, kSCEntNetPPP)) {
276 CFMutableDictionaryRef pppEntity = CFDictionaryCreateMutable(NULL, 0,
277 &kCFTypeDictionaryKeyCallBacks,
278 &kCFTypeDictionaryValueCallBacks);
279
280 if (username != NULL) {
281 CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthName, username);
282 }
283 if (password != NULL) {
284 CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthPassword, password);
285 }
286 CFDictionarySetValue(userOptions, kSCEntNetPPP, pppEntity);
287 my_CFRelease(&pppEntity);
288 }
289 if (CFEqual(iftype, kSCEntNetIPSec) || isL2TP) {
290 CFMutableDictionaryRef ipsecEntity = CFDictionaryCreateMutable(NULL, 0,
291 &kCFTypeDictionaryKeyCallBacks,
292 &kCFTypeDictionaryValueCallBacks);
293 if (!isL2TP) {
294 if (username != NULL) {
295 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthName, username);
296 }
297 if (password != NULL) {
298 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthPassword, password);
299 }
300 }
301 if (sharedsecret != NULL) {
302 CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecSharedSecret, sharedsecret);
303 }
304 CFDictionarySetValue(userOptions, kSCEntNetIPSec, ipsecEntity);
305 my_CFRelease(&ipsecEntity);
306 }
307 if (CFEqual(iftype, kSCEntNetVPN)) {
308 CFMutableDictionaryRef vpnEntity = CFDictionaryCreateMutable(NULL, 0,
309 &kCFTypeDictionaryKeyCallBacks,
310 &kCFTypeDictionaryValueCallBacks);
311 if (username != NULL) {
312 CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthName, username);
313 }
314 if (password != NULL) {
315 CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthPassword, password);
316 }
317 CFDictionarySetValue(userOptions, kSCEntNetVPN, vpnEntity);
318 my_CFRelease(&vpnEntity);
319 }
320 // If it doesn't match any VPN type, fail silently
321
322 if (!SCNetworkConnectionStart(connection, userOptions, TRUE)) {
323 SCPrint(TRUE, stderr, CFSTR("Could not start connection: %s\n"), SCErrorString(SCError()));
324 exit(1);
325 };
326
327 CFRelease(userOptions);
328 nc_release_connection();
329 exit(0);
330 }
331
332 /* -----------------------------------------------------------------------------
333 ----------------------------------------------------------------------------- */
334 static void
335 nc_stop(int argc, char **argv)
336 {
337 nc_create_connection(argc, argv, TRUE);
338
339 if (!SCNetworkConnectionStop(connection, TRUE)) {
340 SCPrint(TRUE, stderr, CFSTR("Could not stop connection: %s\n"), SCErrorString(SCError()));
341 exit(1);
342 };
343
344 nc_release_connection();
345 exit(0);
346 }
347
348 /* -----------------------------------------------------------------------------
349 ----------------------------------------------------------------------------- */
350 static void
351 nc_suspend(int argc, char **argv)
352 {
353 nc_create_connection(argc, argv, TRUE);
354
355 SCNetworkConnectionSuspend(connection);
356
357 nc_release_connection();
358 exit(0);
359 }
360
361 /* -----------------------------------------------------------------------------
362 ----------------------------------------------------------------------------- */
363 static void
364 nc_resume(int argc, char **argv)
365 {
366 nc_create_connection(argc, argv, TRUE);
367
368 SCNetworkConnectionResume(connection);
369
370 nc_release_connection();
371 exit(0);
372 }
373
374 /* -----------------------------------------------------------------------------
375 ----------------------------------------------------------------------------- */
376 static void
377 nc_status(int argc, char **argv)
378 {
379 SCNetworkConnectionStatus status;
380
381 nc_create_connection(argc, argv, TRUE);
382
383 status = SCNetworkConnectionGetStatus(connection);
384 nc_callback(connection, status, NULL);
385
386 nc_release_connection();
387 exit(0);
388 }
389
390 static void
391 nc_watch(int argc, char **argv)
392 {
393 SCNetworkConnectionStatus status;
394
395 nc_create_connection(argc, argv, TRUE);
396
397 status = SCNetworkConnectionGetStatus(connection);
398
399 // report initial status
400 n_callback = 0;
401 nc_callback(connection, status, &n_callback);
402
403 // setup watcher
404 if (doDispatch) {
405 if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_current_queue())) {
406 SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
407 exit(1);
408 }
409 } else {
410 if (!SCNetworkConnectionScheduleWithRunLoop(connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
411 SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
412 exit(1);
413 }
414 }
415
416 // wait for changes
417 CFRunLoopRun();
418
419 nc_release_connection();
420 exit(0);
421 }
422
423 /* -----------------------------------------------------------------------------
424 ----------------------------------------------------------------------------- */
425 static void
426 nc_statistics(int argc, char **argv)
427 {
428 CFDictionaryRef stats_dict;
429
430 nc_create_connection(argc, argv, TRUE);
431
432 stats_dict = SCNetworkConnectionCopyStatistics(connection);
433
434 if (stats_dict) {
435 SCPrint(TRUE, stdout, CFSTR("%@\n"), stats_dict);
436 } else {
437 SCPrint(TRUE, stdout, CFSTR("No statistics available\n"));
438 }
439
440 my_CFRelease(&stats_dict);
441
442 nc_release_connection();
443 exit(0);
444 }
445
446 /* -----------------------------------------------------------------------------
447 ----------------------------------------------------------------------------- */
448 static void
449 checkOnDemandHost(SCDynamicStoreRef store, CFStringRef nodeName, Boolean retry)
450 {
451 Boolean ok;
452 CFStringRef connectionServiceID = NULL;
453 SCNetworkConnectionStatus connectionStatus = 0;
454 CFStringRef vpnRemoteAddress = NULL;
455
456 SCPrint(TRUE, stdout, CFSTR("OnDemand host/domain check (%sretry)\n"), retry ? "" : "no ");
457
458 ok = __SCNetworkConnectionCopyOnDemandInfoWithName(&store,
459 nodeName,
460 retry,
461 &connectionServiceID,
462 &connectionStatus,
463 &vpnRemoteAddress);
464
465 if (ok) {
466 SCPrint(TRUE, stdout, CFSTR(" serviceID = %@\n"), connectionServiceID);
467 SCPrint(TRUE, stdout, CFSTR(" remote address = %@\n"), vpnRemoteAddress);
468 } else if (SCError() != kSCStatusOK) {
469 SCPrint(TRUE, stdout, CFSTR("%sretry\n"), retry ? "" : "no ");
470 SCPrint(TRUE, stdout,
471 CFSTR(" Unable to copy OnDemand information for connection: %s\n"),
472 SCErrorString(SCError()));
473 } else {
474 SCPrint(TRUE, stdout, CFSTR(" no match\n"));
475 }
476
477 if (connectionServiceID != NULL) {
478 CFRelease(connectionServiceID);
479 connectionServiceID = NULL;
480 }
481 if (vpnRemoteAddress != NULL) {
482 CFRelease(vpnRemoteAddress);
483 vpnRemoteAddress = NULL;
484 }
485
486 return;
487 }
488
489 static void
490 nc_ondemand(int argc, char **argv)
491 {
492 int exit_code = 1;
493 CFStringRef key = NULL;
494 CFDictionaryRef ondemand_dict = NULL;
495 SCDynamicStoreRef store;
496
497 store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
498 if (store == NULL) {
499 SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
500 goto done;
501 }
502
503 if (argc > 0) {
504 CFStringRef nodeName;
505
506 nodeName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
507 checkOnDemandHost(store, nodeName, FALSE);
508 checkOnDemandHost(store, nodeName, TRUE);
509 goto done;
510 }
511
512 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
513
514 ondemand_dict = SCDynamicStoreCopyValue(store, key);
515 if (ondemand_dict) {
516 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
517 } else {
518 SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
519 }
520
521 exit_code = 0;
522 done:
523 my_CFRelease(&ondemand_dict);
524 my_CFRelease(&key);
525 my_CFRelease(&store);
526 exit(exit_code);
527 }
528
529
530 /* -----------------------------------------------------------------------------
531 ----------------------------------------------------------------------------- */
532 #define MAX(a, b) ((a) > (b) ? (a) : (b))
533
534 CFStringRef
535 copy_padded_string(CFStringRef original, int width)
536 {
537 CFMutableStringRef padded;
538
539 padded = CFStringCreateMutableCopy(NULL, 0, original);
540 CFStringPad(padded, CFSTR(" "), MAX(CFStringGetLength(original), width), 0);
541 return padded;
542 }
543
544
545 static void
546 nc_print_VPN_service(SCNetworkServiceRef service)
547 {
548 CFStringRef type = NULL;
549 CFStringRef sub_type = NULL;
550
551 nc_get_service_type_and_subtype(service, &type, &sub_type);
552
553 CFStringRef service_name = SCNetworkServiceGetName(service);
554 if (service_name == NULL)
555 service_name = CFSTR("");
556 CFStringRef service_name_quoted = CFStringCreateWithFormat(NULL, NULL, CFSTR("\"%@\""), service_name);
557 if (service_name_quoted == NULL) {
558 service_name_quoted = CFRetain(CFSTR(""));
559 }
560 CFStringRef service_name_padded = copy_padded_string(service_name, 30);
561
562 CFStringRef service_id = SCNetworkServiceGetServiceID(service);
563 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
564 CFStringRef display_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
565 if (display_name == NULL)
566 display_name = CFSTR("");
567 CFStringRef display_name_padded = copy_padded_string(display_name, 18);
568
569
570 SCPrint(TRUE,
571 stdout,
572 CFSTR("%@ %@ %@ %@ [%@%@%@]\n"),
573 SCNetworkServiceGetEnabled(service) ? CFSTR("*") : CFSTR(" "),
574 service_id,
575 display_name_padded,
576 service_name_padded,
577 type,
578 (sub_type == NULL) ? CFSTR("") : CFSTR(":"),
579 (sub_type == NULL) ? CFSTR("") : sub_type);
580 CFRelease(service_name_quoted);
581 CFRelease(display_name_padded);
582 CFRelease(service_name_padded);
583 }
584
585
586 /* -----------------------------------------------------------------------------
587 ----------------------------------------------------------------------------- */
588 static void
589 nc_list(int argc, char **argv)
590 {
591 int count;
592 int i;
593 CFArrayRef services = NULL;
594
595 SCPrint(TRUE, stdout, CFSTR("Available network connection services in the current set (*=enabled):\n"));
596 services = SCNetworkConnectionCopyAvailableServices(NULL);
597 if (services != NULL) {
598 count = CFArrayGetCount(services);
599
600 for (i = 0; i < count; i++) {
601 SCNetworkServiceRef service;
602
603 service = CFArrayGetValueAtIndex(services, i);
604 nc_print_VPN_service(service);
605 }
606
607 }
608 my_CFRelease(&services);
609 exit(0);
610 }
611
612
613 /* -----------------------------------------------------------------------------
614 ----------------------------------------------------------------------------- */
615 static void
616 nc_show(int argc, char **argv)
617 {
618 SCNetworkServiceRef service = NULL;
619 SCDynamicStoreRef store = NULL;
620 int exit_code = 1;
621 CFStringRef serviceID = NULL;
622 CFStringRef iftype = NULL;
623 CFStringRef ifsubtype = NULL;
624 CFStringRef type_entity_key = NULL;
625 CFStringRef subtype_entity_key = NULL;
626 CFDictionaryRef type_entity_dict = NULL;
627 CFDictionaryRef subtype_entity_dict = NULL;
628
629 service = nc_copy_service_from_arguments(argc, argv, NULL);
630 if (service == NULL) {
631 SCPrint(TRUE, stderr, CFSTR("No service\n"));
632 exit(exit_code);
633 }
634
635 serviceID = SCNetworkServiceGetServiceID(service);
636
637 nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
638
639 if (!CFEqual(iftype, kSCEntNetPPP) &&
640 !CFEqual(iftype, kSCEntNetIPSec) &&
641 !CFEqual(iftype, kSCEntNetVPN)) {
642 SCPrint(TRUE, stderr, CFSTR("Not a connection oriented service: %@\n"), serviceID);
643 goto done;
644 }
645
646 type_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, iftype);
647
648 nc_print_VPN_service(service);
649
650 store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
651 if (store == NULL) {
652 SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
653 goto done;
654 }
655 type_entity_dict = SCDynamicStoreCopyValue(store, type_entity_key);
656
657 if (!type_entity_dict) {
658 SCPrint(TRUE, stderr, CFSTR("No \"%@\" configuration available\n"), iftype);
659 } else {
660 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), iftype, type_entity_dict);
661 }
662
663 if (ifsubtype) {
664 subtype_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, ifsubtype);
665 subtype_entity_dict = SCDynamicStoreCopyValue(store, subtype_entity_key);
666 if (!subtype_entity_dict) {
667 //
668 }
669 else {
670 SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), ifsubtype, subtype_entity_dict);
671 }
672 }
673
674 exit_code = 0;
675
676 done:
677 my_CFRelease(&type_entity_key);
678 my_CFRelease(&type_entity_dict);
679 my_CFRelease(&subtype_entity_key);
680 my_CFRelease(&subtype_entity_dict);
681 my_CFRelease(&store);
682 my_CFRelease(&service);
683 exit(exit_code);
684 }
685
686 /* -----------------------------------------------------------------------------
687 ----------------------------------------------------------------------------- */
688 static void
689 nc_select(int argc, char **argv)
690 {
691 SCNetworkSetRef current_set;
692 int exit_code = 1;
693 SCNetworkServiceRef service = NULL;
694 Boolean status;
695
696 do_prefs_init(); /* initialization */
697 do_prefs_open(0, NULL); /* open default prefs */
698
699 current_set = SCNetworkSetCopyCurrent(prefs);
700 if (current_set == NULL) {
701 SCPrint(TRUE, stderr, CFSTR("No current location\n"), SCErrorString(SCError()));
702 goto done;
703 }
704
705 service = nc_copy_service_from_arguments(argc, argv, current_set);
706 if (service == NULL) {
707 SCPrint(TRUE, stderr, CFSTR("No service\n"));
708 goto done;
709 }
710
711 #if !TARGET_OS_IPHONE
712 status = SCNetworkServiceSetEnabled(service, TRUE);
713 if (!status) {
714 SCPrint(TRUE, stderr, CFSTR("Unable to enable service: %s\n"), SCErrorString(SCError()));
715 goto done;
716 }
717 #else
718 status = SCNetworkSetSetSelectedVPNService(current_set, service);
719 if (!status) {
720 SCPrint(TRUE, stderr, CFSTR("Unable to select service: %s\n"), SCErrorString(SCError()));
721 goto done;
722 }
723 #endif
724
725 _prefs_save();
726 exit_code = 0;
727 done:
728 my_CFRelease(&service);
729 my_CFRelease(&current_set);
730 _prefs_close();
731 exit(exit_code);
732 }
733
734 /* -----------------------------------------------------------------------------
735 ----------------------------------------------------------------------------- */
736 typedef void (*nc_func) (int argc, char **argv);
737
738 static const struct {
739 char *cmd;
740 nc_func func;
741 } nc_cmds[] = {
742 { "list", nc_list },
743 { "ondemand", nc_ondemand },
744 { "resume", nc_resume },
745 { "select", nc_select },
746 { "show", nc_show },
747 { "start", nc_start },
748 { "statistics", nc_statistics },
749 { "status", nc_status },
750 { "stop", nc_stop },
751 { "suspend", nc_suspend },
752 };
753 #define N_NC_CMNDS (sizeof(nc_cmds) / sizeof(nc_cmds[0]))
754
755
756 /* -----------------------------------------------------------------------------
757 ----------------------------------------------------------------------------- */
758 int
759 find_nc_cmd(char *cmd)
760 {
761 int i;
762
763 for (i = 0; i < (int)N_NC_CMNDS; i++) {
764 if (strcmp(cmd, nc_cmds[i].cmd) == 0) {
765 return i;
766 }
767 }
768
769 return -1;
770 }
771
772
773 /* -----------------------------------------------------------------------------
774 ----------------------------------------------------------------------------- */
775 void
776 do_nc_cmd(char *cmd, int argc, char **argv, Boolean watch)
777 {
778 int i;
779
780 i = find_nc_cmd(cmd);
781 if (i >= 0) {
782 nc_func func;
783
784 func = nc_cmds[i].func;
785 if (watch && (func == nc_status)) {
786 func = nc_watch;
787 }
788 (*func)(argc, argv);
789 }
790 return;
791 }
792