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