1/*
2 * Copyright (c) 2004-2010 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 * August 5, 2004			Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32#include "scutil.h"
33#include "net.h"
34#include "net_service.h"
35#include "net_interface.h"
36#include "net_protocol.h"
37#include "prefs.h"
38
39
40/* -------------------- */
41
42
43static SCNetworkServiceRef
44_find_service(char *match)
45{
46	Boolean			allowIndex	= TRUE;
47	CFIndex			i;
48	CFIndex			n;
49	CFStringRef		select_name	= NULL;
50	SCNetworkServiceRef	selected	= NULL;
51
52	if (services == NULL) {
53		if (net_set == NULL) {
54			SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
55			return NULL;
56		}
57
58		services = SCNetworkSetCopyServices(net_set);
59		if (services == NULL) {
60			SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
61			return NULL;
62		}
63
64		allowIndex = FALSE;
65	}
66
67	// try to select the service by its serviceID
68
69	select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
70
71	n = CFArrayGetCount(services);
72	for (i = 0; i < n; i++) {
73		SCNetworkServiceRef	service;
74		CFStringRef		serviceID;
75
76		service   = CFArrayGetValueAtIndex(services, i);
77		serviceID = SCNetworkServiceGetServiceID(service);
78		if (CFEqual(select_name, serviceID)) {
79			selected = service;
80			goto done;
81		}
82	}
83
84	// try to select the service by its name
85
86	for (i = 0; i < n; i++) {
87		SCNetworkServiceRef	service;
88		CFStringRef		serviceName;
89
90		service     = CFArrayGetValueAtIndex(services, i);
91		serviceName = SCNetworkServiceGetName(service);
92		if ((serviceName != NULL) && CFEqual(select_name, serviceName)) {
93			if (selected == NULL) {
94				selected = service;
95			} else {
96				// if multiple services match
97				selected = NULL;
98				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
99				goto done;
100			}
101		}
102	}
103
104	if (selected != NULL) {
105		goto done;
106	}
107
108	// try to select the service by its name (case insensitive)
109
110	for (i = 0; i < n; i++) {
111		SCNetworkServiceRef	service;
112		CFStringRef		serviceName;
113
114		service     = CFArrayGetValueAtIndex(services, i);
115		serviceName = SCNetworkServiceGetName(service);
116		if ((serviceName != NULL) &&
117		    CFStringCompare(select_name,
118				    serviceName,
119				    kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
120			if (selected == NULL) {
121				selected = service;
122			} else {
123				// if multiple services match
124				selected = NULL;
125				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
126				goto done;
127			}
128		}
129	}
130
131	if (selected != NULL) {
132		goto done;
133	}
134
135	// try to select the service by its [BSD] interface name
136
137	for (i = 0; i < n; i++) {
138		SCNetworkInterfaceRef	interface;
139		CFStringRef		interfaceName	= NULL;
140		SCNetworkServiceRef	service;
141
142		service     = CFArrayGetValueAtIndex(services, i);
143
144		interface = SCNetworkServiceGetInterface(service);
145		while ((interface != NULL) && (interfaceName == NULL)) {
146			interfaceName = SCNetworkInterfaceGetBSDName(interface);
147			if (interfaceName == NULL) {
148				interface = SCNetworkInterfaceGetInterface(interface);
149			}
150		}
151
152		if (interfaceName == NULL) {
153			continue;
154		}
155
156		if (CFStringCompare(select_name,
157				    interfaceName,
158				    kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
159			if (selected == NULL) {
160				selected = service;
161			} else {
162				// if multiple services match
163				selected = NULL;
164				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
165				goto done;
166			}
167		}
168	}
169
170	if (selected != NULL) {
171		goto done;
172	}
173
174	// try to select the service by its index
175
176	if (allowIndex) {
177		char	*end;
178		char	*str	= match;
179		long	val;
180
181		errno = 0;
182		val = strtol(str, &end, 10);
183		if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
184			if ((val > 0) && (val <= n)) {
185				selected = CFArrayGetValueAtIndex(services, val - 1);
186			}
187		}
188	}
189
190	if (selected != NULL) {
191		goto done;
192	}
193
194	SCPrint(TRUE, stdout, CFSTR("no match, which service?\n"));
195
196    done :
197
198	if (select_name != NULL) CFRelease(select_name);
199	return selected;
200}
201
202
203/* -------------------- */
204
205
206__private_extern__
207void
208create_service(int argc, char **argv)
209{
210	SCNetworkInterfaceRef	interface;
211	CFStringRef		interfaceName;
212	Boolean			ok;
213	SCNetworkServiceRef	service		= NULL;
214	CFStringRef		serviceName;
215	CFStringRef		setName;
216	CFArrayRef		supported;
217
218	if (prefs == NULL) {
219		SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
220		return;
221	}
222
223	if (net_set == NULL) {
224		SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
225		return;
226	}
227
228	if (argc < 1) {
229		if (net_interface == NULL) {
230			SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
231			return;
232		}
233
234		interface = net_interface;
235	} else {
236		int	nArgs;
237
238		interface = _find_interface(argc, argv, &nArgs);
239		argv += nArgs;
240		argc -= nArgs;
241	}
242
243	if (interface == NULL) {
244		return;
245	}
246
247	supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
248	if (supported == NULL) {
249		SCPrint(TRUE, stdout, CFSTR("no network protocols are supported over this interface\n"));
250		return;
251	}
252
253	service = SCNetworkServiceCreate(prefs, interface);
254	if (service == NULL) {
255		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
256		goto done;
257	}
258
259	if ((argc > 0) && (strlen(argv[0]) > 0)) {
260		Boolean         ok;
261
262		serviceName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
263//		argv++;
264//		argc--;
265
266		ok = SCNetworkServiceSetName(service, serviceName);
267		CFRelease(serviceName);
268		if (!ok) {
269			SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
270			(void)SCNetworkServiceRemove(service);
271			goto done;
272		}
273	}
274
275	ok = SCNetworkServiceEstablishDefaultConfiguration(service);
276	if (!ok) {
277		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
278		(void)SCNetworkServiceRemove(service);
279		goto done;
280	}
281
282	ok = SCNetworkSetAddService(net_set, service);
283	if (!ok) {
284		SCPrint(TRUE, stdout, CFSTR("service not created: %s\n"), SCErrorString(SCError()));
285		(void)SCNetworkServiceRemove(service);
286		goto done;
287	}
288
289	_prefs_changed = TRUE;
290
291	if (net_service != NULL) CFRelease(net_service);
292	net_service = CFRetain(service);
293
294	serviceName = SCNetworkServiceGetName(service);
295	if (serviceName != NULL) {
296		SCPrint(TRUE, stdout,
297			CFSTR("service \"%@\" (%@) created and selected\n"),
298			serviceName,
299			SCNetworkServiceGetServiceID(service));
300	} else {
301		SCPrint(TRUE, stdout,
302			CFSTR("service ID \"%@\" created and selected\n"),
303			SCNetworkServiceGetServiceID(service));
304	}
305
306	setName = SCNetworkSetGetName(net_set);
307	if (setName != NULL) {
308		SCPrint(TRUE, stdout, CFSTR("& added to set \"%@\"\n"), setName);
309	} else {
310		SCPrint(TRUE, stdout, CFSTR("& added to set ID \"%@\"\n"),
311			SCNetworkSetGetSetID(net_set));
312	}
313
314	if (net_interface != NULL) CFRelease(net_interface);
315	net_interface = SCNetworkServiceGetInterface(net_service);
316	if (net_interface != NULL) {
317		CFRetain(net_interface);
318	}
319
320	interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
321	if (interfaceName == NULL) {
322		interfaceName = SCNetworkInterfaceGetBSDName(interface);
323	}
324	if (interfaceName == NULL) {
325		interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
326	}
327
328	SCPrint(TRUE, stdout,
329		CFSTR("& interface \"%@\" selected\n"),
330		interfaceName);
331
332	if (protocols != NULL) {
333		CFRelease(protocols);
334		protocols = NULL;
335	}
336
337	if (net_protocol != NULL) {
338		CFRelease(net_protocol);
339		net_protocol = NULL;
340		SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
341	}
342
343	if (services != NULL) {
344		CFRelease(services);
345		services = NULL;
346	}
347
348    done :
349
350	if (service != NULL) CFRelease(service);
351	return;
352}
353
354
355__private_extern__
356void
357disable_service(int argc, char **argv)
358{
359	SCNetworkServiceRef	service;
360
361	if (argc == 1) {
362		service = _find_service(argv[0]);
363	} else {
364		if (net_service != NULL) {
365			service = net_service;
366		} else {
367			SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
368			return;
369		}
370	}
371
372	if (service == NULL) {
373		return;
374	}
375
376	if (!SCNetworkServiceSetEnabled(service, FALSE)) {
377		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
378		return;
379	}
380
381	_prefs_changed = TRUE;
382	return;
383}
384
385
386__private_extern__
387void
388enable_service(int argc, char **argv)
389{
390	SCNetworkServiceRef	service;
391
392	if (argc == 1) {
393		service = _find_service(argv[0]);
394	} else {
395		if (net_service != NULL) {
396			service = net_service;
397		} else {
398			SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
399			return;
400		}
401	}
402
403	if (service == NULL) {
404		return;
405	}
406
407	if (!SCNetworkServiceSetEnabled(service, TRUE)) {
408		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
409		return;
410	}
411
412	_prefs_changed = TRUE;
413	return;
414}
415
416
417__private_extern__
418void
419remove_service(int argc, char **argv)
420{
421	SCNetworkServiceRef	service		= NULL;
422	CFStringRef		serviceName;
423
424	if (argc == 1) {
425		service = _find_service(argv[0]);
426	} else {
427		if (net_service != NULL) {
428			service = net_service;
429		}
430	}
431
432	if (service == NULL) {
433		return;
434	}
435
436	CFRetain(service);
437
438	if (!SCNetworkServiceRemove(service)) {
439		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
440		goto done;
441	}
442
443	_prefs_changed = TRUE;
444
445	serviceName = SCNetworkServiceGetName(service);
446	if (serviceName != NULL) {
447		SCPrint(TRUE, stdout, CFSTR("service \"%@\" removed\n"), serviceName);
448	} else {
449		SCPrint(TRUE, stdout,
450			CFSTR("service ID \"%@\" removed\n"),
451			SCNetworkServiceGetServiceID(service));
452	}
453
454	if ((net_service != NULL) && CFEqual(service, net_service)) {
455		CFRelease(net_service);
456		net_service = NULL;
457		SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
458
459		if (protocols != NULL) {
460			CFRelease(protocols);
461			protocols = NULL;
462		}
463
464		if (net_protocol != NULL) {
465			CFRelease(net_protocol);
466			net_protocol = NULL;
467			SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
468		}
469
470		if (net_interface != NULL) {
471			CFRelease(net_interface);
472			net_interface = NULL;
473			SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
474		}
475	}
476
477	if (services != NULL) {
478		CFRelease(services);
479		services = NULL;
480	}
481
482    done :
483
484	CFRelease(service);
485	return;
486}
487
488
489__private_extern__
490void
491select_service(int argc, char **argv)
492{
493	SCNetworkInterfaceRef	interface;
494	SCNetworkServiceRef	service;
495	CFStringRef		serviceName;
496
497	service = _find_service(argv[0]);
498
499	if (service == NULL) {
500		return;
501	}
502
503	if (net_service != NULL) CFRelease(net_service);
504	net_service = CFRetain(service);
505
506	serviceName = SCNetworkServiceGetName(service);
507	if (serviceName != NULL) {
508		SCPrint(TRUE, stdout, CFSTR("service \"%@\" selected\n"), serviceName);
509	} else {
510		SCPrint(TRUE, stdout,
511			CFSTR("service ID \"%@\" selected\n"),
512			SCNetworkServiceGetServiceID(service));
513	}
514
515	interface = SCNetworkServiceGetInterface(service);
516	if (interface != NULL) {
517		CFStringRef	interfaceName;
518
519		if (net_interface != NULL) CFRelease(net_interface);
520		net_interface = CFRetain(interface);
521
522		interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
523		if (interfaceName == NULL) {
524			interfaceName = SCNetworkInterfaceGetBSDName(interface);
525		}
526		if (interfaceName == NULL) {
527			interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
528		}
529
530		SCPrint(TRUE, stdout,
531			CFSTR("& interface \"%@\" selected\n"),
532			interfaceName);
533	} else {
534		if (net_interface != NULL) {
535			CFRelease(net_interface);
536			net_interface = NULL;
537			SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
538		}
539	}
540
541	if (protocols != NULL) {
542		CFRelease(protocols);
543		protocols = NULL;
544	}
545
546	if (net_protocol != NULL) {
547		CFRelease(net_protocol);
548		net_protocol = NULL;
549		SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
550	}
551
552	return;
553}
554
555
556__private_extern__
557void
558set_service(int argc, char **argv)
559{
560	Boolean	ok;
561
562	if (net_service == NULL) {
563		SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
564		return;
565	}
566
567	if (argc < 1) {
568		SCPrint(TRUE, stdout, CFSTR("set what?\n"));
569		return;
570	}
571
572	while (argc > 0) {
573		char	*command;
574
575		command = argv[0];
576		argv++;
577		argc--;
578
579		if (strcmp(command, "name") == 0) {
580			CFStringRef	serviceName;
581
582			if (argc < 1) {
583				SCPrint(TRUE, stdout, CFSTR("name not specified\n"));
584				return;
585			}
586
587			serviceName = (strlen(argv[0]) > 0)
588					? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8)
589					: NULL;
590			argv++;
591			argc--;
592
593			ok = SCNetworkServiceSetName(net_service, serviceName);
594			if (serviceName != NULL) CFRelease(serviceName);
595			if (!ok) {
596				SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
597				return;
598			}
599
600			_prefs_changed = TRUE;
601		} else if (strcmp(command, "order") == 0) {
602
603			char		*end;
604			long		newIndex;
605			CFIndex		nServices;
606			char		*str;
607			CFArrayRef	services;
608
609			services = SCNetworkSetCopyServices(net_set);
610			nServices = CFArrayGetCount(services);
611			CFRelease(services);
612
613			if (argc < 1) {
614				SCPrint(TRUE, stdout, CFSTR("order not specified\n"));
615				return;
616			}
617
618			if (net_set == NULL) {
619				SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
620				return;
621			}
622
623			str = argv[0];
624			argv++;
625			argc--;
626
627			errno = 0;
628			newIndex = strtol(str, &end, 10);
629			if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
630				if ((newIndex > 0) && (newIndex <= nServices)) {
631					CFIndex			curIndex;
632					CFMutableArrayRef	newOrder;
633					CFArrayRef		order;
634					CFStringRef		serviceID	= SCNetworkServiceGetServiceID(net_service);
635
636					order = SCNetworkSetGetServiceOrder(net_set);
637					if (order == NULL) {
638						newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
639					} else {
640						newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
641					}
642
643					curIndex = CFArrayGetFirstIndexOfValue(newOrder,
644									       CFRangeMake(0, CFArrayGetCount(newOrder)),
645									       serviceID);
646					if (curIndex != kCFNotFound) {
647						CFArrayRemoveValueAtIndex(newOrder, curIndex);
648					}
649
650					if (newIndex <= CFArrayGetCount(newOrder)) {
651						CFArrayInsertValueAtIndex(newOrder, newIndex - 1, serviceID);
652					} else {
653						CFArrayAppendValue(newOrder, serviceID);
654					}
655
656					ok = SCNetworkSetSetServiceOrder(net_set, newOrder);
657					CFRelease(newOrder);
658					if (!ok) {
659						SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
660						return;
661					}
662
663					_prefs_changed = TRUE;
664				} else {
665					SCPrint(TRUE, stdout, CFSTR("set order to what?\n"));
666					return;
667				}
668			} else {
669				SCPrint(TRUE, stdout, CFSTR("set what?\n"));
670				return;
671			}
672		} else if (strcmp(command, "rank") == 0) {
673			SCNetworkServicePrimaryRank	rank	= kSCNetworkServicePrimaryRankDefault;
674			SCNetworkServiceRef		service	= (argc < 2) ? net_service : NULL;
675
676			if (argc < 1) {
677				SCPrint(TRUE, stdout, CFSTR("rank not specified\n"));
678				return;
679			}
680
681			if (strlen(argv[0]) > 0) {
682				if (strcasecmp(argv[0], "Never") == 0) {
683					rank = kSCNetworkServicePrimaryRankNever;
684				} else if ((service != net_service) && (strcasecmp(argv[0], "First") == 0)) {
685					rank = kSCNetworkServicePrimaryRankFirst;
686				} else if ((service != net_service) && (strcasecmp(argv[0], "Last") == 0)) {
687					rank = kSCNetworkServicePrimaryRankLast;
688				} else {
689					SCPrint(TRUE, stdout, CFSTR("rank not valid\n"));
690					return;
691				}
692			}
693			argv++;
694			argc--;
695
696			if (service == NULL) {
697				CFStringRef		serviceID;
698				SCDynamicStoreRef	store;
699
700				store = SCDynamicStoreCreate(NULL,
701							     CFSTR("scutil (set primary rank)"),
702							     NULL,
703							     NULL);
704				serviceID = SCNetworkServiceGetServiceID(net_service);
705				service = _SCNetworkServiceCopyActive(store, serviceID);
706				CFRelease(store);
707
708				argv++;
709				argc--;
710			}
711
712			ok = SCNetworkServiceSetPrimaryRank(service, rank);
713			if (service != net_service) CFRelease(service);
714			if (ok) {
715				if (service == net_service) _prefs_changed = TRUE;
716			} else {
717				SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
718				return;
719			}
720		} else {
721			SCPrint(TRUE, stdout, CFSTR("set what?\n"));
722		}
723	}
724
725	return;
726}
727
728
729static void
730__show_service_interface(SCNetworkServiceRef service, const char *prefix)
731{
732	CFStringRef		description;
733	SCNetworkInterfaceRef	interface;
734
735	interface = SCNetworkServiceGetInterface(service);
736	if (interface == NULL) {
737		return;
738	}
739
740	description = _interface_description(interface);
741	SCPrint(TRUE, stdout, CFSTR("%s%@\n"), prefix, description);
742	CFRelease(description);
743
744	return;
745}
746
747static void
748__show_service_protocols(SCNetworkServiceRef service, const char *prefix, Boolean skipEmpty)
749{
750	CFIndex		i;
751	CFIndex		n;
752	CFArrayRef	protocols;
753
754	protocols = SCNetworkServiceCopyProtocols(service);
755	if (protocols == NULL) {
756		return;
757	}
758
759	n = CFArrayGetCount(protocols);
760	if (n > 1) {
761		CFMutableArrayRef	sorted;
762
763		sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
764		CFArraySortValues(sorted,
765				  CFRangeMake(0, n),
766				  _compare_protocols,
767				  NULL);
768		CFRelease(protocols);
769		protocols = sorted;
770	}
771
772	for (i = 0; i < n; i++) {
773		CFStringRef		description;
774		SCNetworkProtocolRef	protocol;
775
776		protocol = CFArrayGetValueAtIndex(protocols, i);
777		description = _protocol_description(protocol, skipEmpty);
778		if (description != NULL) {
779			CFStringRef	protocolType;
780
781			protocolType = SCNetworkProtocolGetProtocolType(protocol);
782			SCPrint(TRUE, stdout,
783				CFSTR("%s%@%*s : %@\n"),
784				prefix,
785				protocolType,
786				sizeof("Interface") - CFStringGetLength(protocolType) - 1,
787				"",
788				description);
789			CFRelease(description);
790		}
791	}
792
793	CFRelease(protocols);
794	return;
795}
796
797
798__private_extern__
799void
800show_service(int argc, char **argv)
801{
802	SCNetworkInterfaceRef		interface;
803	CFArrayRef			protocols;
804	SCNetworkServiceRef		service;
805	CFStringRef			serviceName;
806	SCNetworkServicePrimaryRank	serviceRank;
807
808	if (argc == 1) {
809		service = _find_service(argv[0]);
810	} else {
811		if (net_service != NULL) {
812			service = net_service;
813		} else {
814			SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
815			return;
816		}
817	}
818
819	if (service == NULL) {
820		return;
821	}
822
823	SCPrint(TRUE, stdout, CFSTR("service id           = %@\n"), SCNetworkServiceGetServiceID(service));
824
825	serviceName = SCNetworkServiceGetName(service);
826	SCPrint(TRUE, stdout, CFSTR("name                 = %@\n"),
827		(serviceName != NULL) ? serviceName : CFSTR(""));
828
829	serviceRank = SCNetworkServiceGetPrimaryRank(service);
830	switch (serviceRank) {
831		case kSCNetworkServicePrimaryRankDefault :
832			// nothing to report
833			break;
834		case kSCNetworkServicePrimaryRankFirst :
835			SCPrint(TRUE, stdout, CFSTR("primary rank         = FIRST\n"));
836			break;
837		case kSCNetworkServicePrimaryRankLast :
838			SCPrint(TRUE, stdout, CFSTR("primary rank         = LAST\n"));
839			break;
840		case kSCNetworkServicePrimaryRankNever :
841			SCPrint(TRUE, stdout, CFSTR("primary rank         = NEVER\n"));
842			break;
843		default :
844			SCPrint(TRUE, stdout, CFSTR("primary rank         = %d\n"), serviceRank);
845			break;
846	}
847
848	interface = SCNetworkServiceGetInterface(service);
849	if (interface != NULL) {
850		CFStringRef	interfaceName;
851
852		interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
853		if (interfaceName != NULL) {
854			CFRetain(interfaceName);
855		} else {
856			interfaceName = _interface_description(interface);
857		}
858		if (interfaceName != NULL) {
859			SCPrint(TRUE, stdout, CFSTR("interface            = %@\n"), interfaceName);
860			CFRelease(interfaceName);
861		}
862	} else {
863		SCPrint(TRUE, stdout, CFSTR("\n  No interface!\n\n"));
864	}
865
866	protocols = SCNetworkServiceCopyProtocols(service);
867	if (protocols != NULL) {
868		CFIndex	n;
869
870		n = CFArrayGetCount(protocols);
871		if (n > 1) {
872			CFMutableArrayRef	sorted;
873
874			sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
875			CFArraySortValues(sorted,
876					  CFRangeMake(0, n),
877					  _compare_protocols,
878					  NULL);
879			CFRelease(protocols);
880			protocols = sorted;
881		}
882
883		if (n > 0) {
884			CFIndex	i;
885
886			SCPrint(TRUE, stdout, CFSTR("configured protocols = "));
887			for (i = 0; i < n; i++) {
888				SCNetworkProtocolRef	protocol;
889
890				protocol = CFArrayGetValueAtIndex(protocols, i);
891				SCPrint(TRUE, stdout, CFSTR("%s%@"),
892					(i == 0) ? "" : ", ",
893					SCNetworkProtocolGetProtocolType(protocol));
894			}
895			SCPrint(TRUE, stdout, CFSTR("\n"));
896
897			__show_service_protocols(service, "  ", FALSE);
898		} else {
899			SCPrint(TRUE, stdout, CFSTR("no configured protocols\n"));
900		}
901
902		CFRelease(protocols);
903	}
904
905	if (_sc_debug) {
906		SCPrint(TRUE, stdout, CFSTR("\n%@\n"), service);
907	}
908
909	return;
910}
911
912
913__private_extern__
914void
915show_services(int argc, char **argv)
916{
917	CFIndex	i;
918	CFIndex	n;
919
920	if (prefs == NULL) {
921		SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
922		return;
923	}
924
925	if (argc == 1) {
926		if (services != NULL) CFRelease(services);
927		services = SCNetworkServiceCopyAll(prefs);
928	} else {
929		if (net_set == NULL) {
930			SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
931			return;
932		}
933
934		if (services != NULL) CFRelease(services);
935		services = SCNetworkSetCopyServices(net_set);
936		n = (services != NULL) ? CFArrayGetCount(services) : 0;
937		if (n > 1) {
938			CFArrayRef		order;
939			CFMutableArrayRef	sorted;
940
941			order  = SCNetworkSetGetServiceOrder(net_set);
942			sorted = CFArrayCreateMutableCopy(NULL, 0, services);
943			CFArraySortValues(sorted,
944					  CFRangeMake(0, CFArrayGetCount(sorted)),
945					  _SCNetworkServiceCompare,
946					  (void *)order);
947			CFRelease(services);
948			services = sorted;
949		}
950	}
951
952	if (services == NULL) {
953		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
954		return;
955	}
956
957	n = CFArrayGetCount(services);
958	for (i = 0; i < n; i++) {
959		SCNetworkServiceRef	service;
960		CFStringRef		serviceName;
961		CFStringRef		serviceID;
962
963		service     = CFArrayGetValueAtIndex(services, i);
964		serviceID   = SCNetworkServiceGetServiceID(service);
965		serviceName = SCNetworkServiceGetName(service);
966		if (serviceName == NULL) serviceName = CFSTR("");
967
968		SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)%s\n"),
969			((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
970			i + 1,
971			serviceName,
972			30 - CFStringGetLength(serviceName),
973			" ",
974			serviceID,
975			SCNetworkServiceGetEnabled(service) ? "" : " *DISABLED*");
976
977		__show_service_interface(service, "       Interface : ");
978		__show_service_protocols(service, "       ", TRUE);
979	}
980
981	return;
982}
983