]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/net_protocol.c
configd-1109.101.1.tar.gz
[apple/configd.git] / scutil.tproj / net_protocol.c
CommitLineData
dbf6a266 1/*
c956c85e 2 * Copyright (c) 2004-2009, 2011, 2014, 2017, 2019, 2020 Apple Inc. All rights reserved.
dbf6a266
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
afb19109 5 *
dbf6a266
A
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.
afb19109 12 *
dbf6a266
A
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.
afb19109 20 *
dbf6a266
A
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_protocol.h"
edebe297 35#include "prefs.h"
dbf6a266
A
36
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <net/if.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42
43
44/* -------------------- */
45
46
dbf6a266
A
47static CFStringRef
48__copyIPv4Address(const char *arg)
49{
50 char buf[128];
51 struct sockaddr_in sin;
52
17d3ee29 53 if (_SC_string_to_sockaddr(arg, AF_INET, (void *)&sin, sizeof(sin)) == NULL) {
dbf6a266
A
54 return NULL;
55 }
56
57 _SC_sockaddr_to_string((struct sockaddr *)&sin, buf, sizeof(buf));
58 return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
59}
60
61
62static CFStringRef
63__copyIPv6Address(const char *arg)
64{
65 char buf[128];
dbf6a266
A
66 struct sockaddr_in6 sin6;
67
17d3ee29 68 if (_SC_string_to_sockaddr(arg, AF_INET6, (void *)&sin6, sizeof(sin6)) == NULL) {
dbf6a266
A
69 return NULL;
70 }
71
dbf6a266
A
72 _SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf));
73 return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
74}
75
76
77/* -------------------- */
78
79
80static SCNetworkProtocolRef
81_find_protocol(char *match)
82{
83 Boolean allowIndex = TRUE;
84 CFIndex i;
85 CFIndex n;
86 CFStringRef select_name = NULL;
87 SCNetworkProtocolRef selected = NULL;
88
89 if (protocols == NULL) {
90 if (net_service == NULL) {
91 SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
92 return NULL;
93 }
94
95 protocols = SCNetworkServiceCopyProtocols(net_service);
96 if (protocols == NULL) {
97 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
98 return NULL;
99 }
100
101 n = CFArrayGetCount(protocols);
102 if (n > 1) {
103 CFMutableArrayRef sorted;
104
105 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
106 CFArraySortValues(sorted,
107 CFRangeMake(0, n),
1ef45fa4 108 _SCNetworkProtocolCompare,
dbf6a266
A
109 NULL);
110 CFRelease(protocols);
111 protocols = sorted;
112 }
113
114 allowIndex = FALSE;
115 }
116
117 // try to select the protocol by its protocol type
118
119 select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
120
121 n = CFArrayGetCount(protocols);
122 for (i = 0; i < n; i++) {
123 SCNetworkProtocolRef protocol;
124 CFStringRef type;
125
126 protocol = CFArrayGetValueAtIndex(protocols, i);
127 type = SCNetworkProtocolGetProtocolType(protocol);
128 if (CFStringCompare(select_name, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
129 selected = protocol;
130 goto done;
131 }
132 }
133
134 if (allowIndex) {
135 char *end;
136 char *str = match;
137 long val;
138
139 // try to select the protocol by its index
140
141 errno = 0;
142 val = strtol(str, &end, 10);
143 if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
144 if ((val > 0) && (val <= n)) {
145 selected = CFArrayGetValueAtIndex(protocols, val - 1);
146 }
147 }
148 }
149
150 if (selected != NULL) {
151 goto done;
152 }
153
154 SCPrint(TRUE, stdout, CFSTR("no match, which protocol?\n"));
155
156 done :
157
158 if (select_name != NULL) CFRelease(select_name);
159 return selected;
160}
161
162
163/* -------------------- */
164
165
166__private_extern__
167void
168create_protocol(int argc, char **argv)
169{
170 SCNetworkInterfaceRef interface;
171 CFStringRef protocolType;
172
173 if ((argc < 1) || (strlen(argv[0]) == 0)) {
174 SCPrint(TRUE, stdout, CFSTR("what protocol type?\n"));
175 return;
176 }
177
178 if (net_service == NULL) {
179 SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
180 return;
181 }
182
183 protocolType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
184
185 interface = SCNetworkServiceGetInterface(net_service);
186 if (interface != NULL) {
187 CFArrayRef supported;
188 CFIndex i;
189 CFIndex n;
190
191 supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
192 n = (supported != NULL) ? CFArrayGetCount(supported) : 0;
193 for (i = 0; i < n; i++) {
194 CFStringRef supportedType;
195
196 supportedType = CFArrayGetValueAtIndex(supported, i);
197 if (CFStringCompare(protocolType,
198 supportedType,
199 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
200 CFRelease(protocolType);
201 protocolType = CFRetain(supportedType);
202 break;
203 }
204 }
205 }
206
207 if (!SCNetworkServiceAddProtocolType(net_service, protocolType)) {
208 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
209 goto done;
210 }
211
edebe297 212 _prefs_changed = TRUE;
dbf6a266
A
213
214 if (protocols != NULL) {
215 CFRelease(protocols);
216 protocols = NULL;
217 }
218
219 if (net_protocol != NULL) CFRelease(net_protocol);
220// net_protocol = NULL;
221
222 net_protocol = SCNetworkServiceCopyProtocol(net_service, protocolType);
223 if (net_protocol == NULL) {
224 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
225 goto done;
226 }
227
228 SCPrint(TRUE, stdout,
229 CFSTR("protocol \"%@\" selected\n"),
230 protocolType);
231
232 done :
233
234 CFRelease(protocolType);
235 return;
236}
237
238
239/* -------------------- */
240
241
242__private_extern__
243void
244disable_protocol(int argc, char **argv)
245{
246 SCNetworkProtocolRef protocol = NULL;
247
248 if (argc > 0) {
249 protocol = _find_protocol(argv[0]);
250 } else {
251 if (net_protocol != NULL) {
252 protocol = net_protocol;
253 } else {
254 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
255 return;
256 }
257 }
258
259 if (protocol == NULL) {
260 return;
261 }
262
263 if (!SCNetworkProtocolSetEnabled(protocol, FALSE)) {
264 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
265 return;
266 }
267
edebe297 268 _prefs_changed = TRUE;
dbf6a266
A
269
270 return;
271}
272
273
274/* -------------------- */
275
276
277__private_extern__
278void
279enable_protocol(int argc, char **argv)
280{
281 SCNetworkProtocolRef protocol = NULL;
282
283 if (argc > 0) {
284 protocol = _find_protocol(argv[0]);
285 } else {
286 if (net_protocol != NULL) {
287 protocol = net_protocol;
288 } else {
289 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
290 return;
291 }
292 }
293
294 if (protocol == NULL) {
295 return;
296 }
297
298 if (!SCNetworkProtocolSetEnabled(protocol, TRUE)) {
299 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
300 return;
301 }
302
edebe297 303 _prefs_changed = TRUE;
dbf6a266
A
304
305 return;
306}
307
308
309/* -------------------- */
310
311
312__private_extern__
313void
314remove_protocol(int argc, char **argv)
315{
316 SCNetworkProtocolRef protocol = NULL;
317 CFStringRef protocolType;
318
319 if (argc > 0) {
320 protocol = _find_protocol(argv[0]);
321 } else {
322 if (net_protocol != NULL) {
323 protocol = net_protocol;
324 } else {
325 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
326 return;
327 }
328 }
329
330 if (protocol == NULL) {
331 return;
332 }
333
334 CFRetain(protocol);
335
336 protocolType = SCNetworkProtocolGetProtocolType(protocol);
337 if (!SCNetworkServiceRemoveProtocolType(net_service, protocolType)) {
338 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
339 goto done;
340 }
341
edebe297 342 _prefs_changed = TRUE;
dbf6a266
A
343
344 SCPrint(TRUE, stdout,
345 CFSTR("protocol \"%@\" removed\n"),
346 protocolType);
347
348 if ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) {
349 CFRelease(net_protocol);
350 net_protocol = NULL;
351 SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
352 }
353
354 if (protocols != NULL) {
355 CFRelease(protocols);
356 protocols = NULL;
357 }
358
359 done :
360
361 CFRelease(protocol);
362 return;
363}
364
365
366/* -------------------- */
367
368
369__private_extern__
370void
371select_protocol(int argc, char **argv)
372{
1ef45fa4 373#pragma unused(argc)
dbf6a266
A
374 SCNetworkProtocolRef protocol;
375
376 protocol = _find_protocol(argv[0]);
377
378 if (protocol == NULL) {
379 return;
380 }
381
382 if (net_protocol != NULL) CFRelease(net_protocol);
383 net_protocol = CFRetain(protocol);
384
385 SCPrint(TRUE, stdout,
386 CFSTR("protocol \"%@\" selected\n"),
387 SCNetworkProtocolGetProtocolType(protocol));
388
389 return;
390}
391
392
edebe297
A
393#pragma mark -
394#pragma mark DNS
dbf6a266
A
395
396
17d3ee29 397static CF_RETURNS_RETAINED CFStringRef
dbf6a266
A
398__cleanupDomainName(CFStringRef domain)
399{
400 CFMutableStringRef newDomain;
401
402 newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
403 CFStringTrimWhitespace(newDomain);
404 CFStringTrim(newDomain, CFSTR("."));
405 if (CFStringGetLength(newDomain) == 0) {
406 CFRelease(newDomain);
407 newDomain = NULL;
408 }
409
410 return newDomain;
411}
412
413
414static int
415__doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
416{
1ef45fa4
A
417#pragma unused(description)
418#pragma unused(info)
dbf6a266
A
419 if (argc < 1) {
420 SCPrint(TRUE, stdout, CFSTR("DNS domain name not specified\n"));
421 return -1;
422 }
423
424 if (strlen(argv[0]) > 0) {
425 CFStringRef domain;
426 CFStringRef str;
427
428 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
429 domain = __cleanupDomainName(str);
430 CFRelease(str);
431
432 if (domain != NULL) {
433 CFDictionarySetValue(newConfiguration, key, domain);
434 CFRelease(domain);
435 } else {
436 SCPrint(TRUE, stdout, CFSTR("invalid DNS domain name\n"));
437 return -1;
438 }
439 } else {
440 CFDictionaryRemoveValue(newConfiguration, key);
441 }
442
443 return 1;
444}
445
446
447static int
448__doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
449{
1ef45fa4
A
450#pragma unused(description)
451#pragma unused(info)
dbf6a266
A
452 CFMutableArrayRef domains;
453
454 if (argc < 1) {
455 SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
456 return -1;
457 }
458
459 domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
460
461 if (strlen(argv[0]) > 0) {
462 CFArrayRef array;
463 CFStringRef str;
464
465 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
466 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
467 CFRelease(str);
468
469 if (array != NULL) {
470 CFIndex i;
471 CFIndex n = CFArrayGetCount(array);
472
473 for (i = 0; i < n; i++) {
474 CFStringRef domain;
475
476 domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
477 if (domain != NULL) {
478 CFArrayAppendValue(domains, domain);
479 CFRelease(domain);
480 } else {
481 CFRelease(array);
482 CFRelease(domains);
483 SCPrint(TRUE, stdout, CFSTR("invalid DNS search domain name\n"));
484 return -1;
485 }
486 }
487 CFRelease(array);
488 }
489 }
490
491 if (CFArrayGetCount(domains) > 0) {
492 CFDictionarySetValue(newConfiguration, key, domains);
493 } else {
494 CFDictionaryRemoveValue(newConfiguration, key);
495 }
496
497 CFRelease(domains);
498 return 1;
499}
500
501
502static int
503__doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
504{
1ef45fa4
A
505#pragma unused(description)
506#pragma unused(info)
dbf6a266
A
507 CFMutableArrayRef servers;
508
509 if (argc < 1) {
edebe297 510 SCPrint(TRUE, stdout, CFSTR("DNS name server address(es) not specified\n"));
dbf6a266
A
511 return -1;
512 }
513
514 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
515
516 if (strlen(argv[0]) > 0) {
517 CFArrayRef array;
518 CFIndex i;
519 CFIndex n;
520 CFStringRef str;
521
522 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
523 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
524 CFRelease(str);
525
526 n = (array != NULL) ? CFArrayGetCount(array) : 0;
527 for (i = 0; i < n; i++) {
528 char str[32];
529
530 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
531 str,
532 sizeof(str),
533 kCFStringEncodingUTF8) != NULL) {
534 CFStringRef server;
535
536 server = __copyIPv4Address(str);
537 if (server == NULL) {
538 server = __copyIPv6Address(str);
539 }
540 if (server != NULL) {
541 CFArrayAppendValue(servers, server);
542 CFRelease(server);
543 continue;
544 }
545 }
546
547 SCPrint(TRUE, stdout, CFSTR("invalid DNS name server address\n"));
548 CFRelease(array);
549 CFRelease(servers);
550 return -1;
551 }
552 if (array != NULL) CFRelease(array);
553 }
554
555 if (CFArrayGetCount(servers) > 0) {
556 CFDictionarySetValue(newConfiguration, key, servers);
557 } else {
558 CFDictionaryRemoveValue(newConfiguration, key);
559 }
560
561 CFRelease(servers);
562 return 1;
563}
564
565
566static options dnsOptions[] = {
567 { "DomainName" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
568 { "domain" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
569 { "SearchDomains" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
570 { "search" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
571 { "ServerAddresses", "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
572 { "nameserver" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
573 { "nameservers" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
6bb65964
A
574 { "SupplementalMatchDomains",
575 "domain",
576 isOther,
577 &kSCPropNetDNSSupplementalMatchDomains,
578 __doDNSDomainArray,
579 NULL },
dbf6a266
A
580
581 { "?" , NULL , isHelp , NULL , NULL,
582 "\nDNS configuration commands\n\n"
583 " set protocol search domain-name[,domain-name-2]\n"
a40a14f8 584 " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]\n"
dbf6a266
A
585 }
586};
587#define N_DNS_OPTIONS (sizeof(dnsOptions) / sizeof(dnsOptions[0]))
588
589
590static Boolean
591set_protocol_dns(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
592{
593 Boolean ok;
594
595 ok = _process_options(dnsOptions, N_DNS_OPTIONS, argc, argv, newConfiguration);
596 return ok;
597}
598
599
edebe297
A
600#pragma mark -
601#pragma mark IPv4
dbf6a266
A
602
603
604#define allowIPv4Address 1<<1 // allow address
605#define allowIPv4Netmask 1<<2 // allow subnet mask
606#define allowIPv4Router 1<<3 // allow router
607#define allowIPv4DHCPClientID 1<<4 // allow DCHP Client ID
608
609static selections ipv4ConfigMethods[] = {
610 { CFSTR("BOOTP") , &kSCValNetIPv4ConfigMethodBOOTP , 0 },
611 { CFSTR("DHCP") , &kSCValNetIPv4ConfigMethodDHCP , allowIPv4DHCPClientID },
612 { CFSTR("INFORM") , &kSCValNetIPv4ConfigMethodINFORM , allowIPv4Address },
613 { CFSTR("LinkLocal"), &kSCValNetIPv4ConfigMethodLinkLocal, 0 },
614 { CFSTR("Manual") , &kSCValNetIPv4ConfigMethodManual , allowIPv4Address|allowIPv4Netmask|allowIPv4Router },
615 { CFSTR("PPP") , &kSCValNetIPv4ConfigMethodPPP , allowIPv4Address|selectionNotAvailable },
616 { NULL , NULL , 0 }
617};
618
619
620static int
621__doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
622{
1ef45fa4
A
623#pragma unused(description)
624#pragma unused(info)
625#pragma unused(argc)
626#pragma unused(argv)
dbf6a266
A
627 unsigned int flags;
628 CFStringRef method;
629 CFIndex methodIndex;
630
631 method = CFDictionaryGetValue(newConfiguration, key);
632 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
633 if (methodIndex != kCFNotFound) {
634 if (!(flags & allowIPv4Address)) {
635 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Addresses);
636 }
637 if (!(flags & allowIPv4Netmask)) {
638 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4SubnetMasks);
639 }
640 if (!(flags & allowIPv4Router)) {
641 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Router);
642 }
643 if (!(flags & allowIPv4DHCPClientID)) {
644 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4DHCPClientID);
645 }
646 } else {
647 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
648 return -1;
649 }
650
651 return 0;
652}
653
654
655static int
656__doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
657{
1ef45fa4
A
658#pragma unused(description)
659#pragma unused(argc)
dbf6a266
A
660 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
661
662 if (strlen(argv[0]) > 0) {
663 CFStringRef address;
664
665 address = __copyIPv4Address(argv[0]);
666 if (address != NULL) {
667 if (useArray) {
668 CFArrayRef addresses;
669
670 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
671 CFDictionarySetValue(newConfiguration, key, addresses);
672 CFRelease(addresses);
673 } else {
674 CFDictionarySetValue(newConfiguration, key, address);
675 }
676 CFRelease(address);
677 } else {
678 return -1;
679 }
680 } else {
681 CFDictionaryRemoveValue(newConfiguration, key);
682 }
683
684 return 1;
685}
686
687
688static options ipv4Options[] = {
689 { "ConfigMethod", "configuration method"
690 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
691 { "config" , "configuration method"
692 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
693 { "Addresses" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
694 { "address" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
695 { "SubnetMasks" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
696 { "netmask" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
697 { "Router" , "address" , isOther , &kSCPropNetIPv4Router , __doIPv4Addresses , (void *)FALSE },
698 { "DHCPClientID", "client ID", isString , &kSCPropNetIPv4DHCPClientID, NULL , NULL },
699
700 { "?" , NULL , isHelp , NULL , NULL ,
701 "\nIPv4 configuration commands\n\n"
702 " set protocol config {BOOTP|DHCP|INFORM|MANUAL}\n"
703 "\n w/config=BOOTP\n"
704 " None\n"
705 "\n w/config=DHCP\n"
706 " set protocol dhcpclientid identifier\n"
707 "\n w/config=INFORM\n"
708 " set protocol address x.x.x.x\n"
709 "\n w/config=MANUAL\n"
710 " set protocol address x.x.x.x\n"
711 " set protocol netmask x.x.x.x\n"
712 " set protocol router x.x.x.x\n"
713 }
714};
715#define N_IPV4_OPTIONS (sizeof(ipv4Options) / sizeof(ipv4Options[0]))
716
717
718static Boolean
719set_protocol_ipv4(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
720{
721 Boolean ok;
722
723 ok = _process_options(ipv4Options, N_IPV4_OPTIONS, argc, argv, newConfiguration);
724 if (ok) {
725 unsigned int flags;
726 CFStringRef method;
727 CFIndex methodIndex;
728
729 // validate configuration
730 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv4ConfigMethod);
731 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
732 if (methodIndex == kCFNotFound) {
733 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
734 return FALSE;
735 }
736
737 if (!(flags & allowIPv4Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Addresses)) {
738 SCPrint(TRUE, stdout,
739 CFSTR("IP address not allowed with %@ configuration\n"),
740 ipv4ConfigMethods[methodIndex].selection);
741 return FALSE;
742 }
743
744 if (!(flags & allowIPv4Netmask) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4SubnetMasks)) {
745 SCPrint(TRUE, stdout,
746 CFSTR("Subnet mask not allowed with %@ configuration\n"),
747 ipv4ConfigMethods[methodIndex].selection);
748 return FALSE;
749 }
750
751 if (!(flags & allowIPv4Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Router)) {
752 SCPrint(TRUE, stdout,
753 CFSTR("Default route not allowed with %@ configuration\n"),
754 ipv4ConfigMethods[methodIndex].selection);
755 return FALSE;
756 }
757
758 if (!(flags & allowIPv4DHCPClientID) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4DHCPClientID)) {
759 SCPrint(TRUE, stdout,
760 CFSTR("DHCP client ID not allowed with %@ configuration\n"),
761 ipv4ConfigMethods[methodIndex].selection);
762 return FALSE;
763 }
764 }
765
766 return ok;
767}
768
769
edebe297
A
770#pragma mark -
771#pragma mark IPv6
dbf6a266
A
772
773
774#define allowIPv6Address 1<<1 // allow address
775#define allowIPv6PrefixLength 1<<2 // allow prefix length
776#define allowIPv6Router 1<<3 // allow router
777
778static selections ipv6ConfigMethods[] = {
779 { CFSTR("Automatic") , & kSCValNetIPv6ConfigMethodAutomatic , 0 },
780 { CFSTR("Manual") , & kSCValNetIPv6ConfigMethodManual , allowIPv6Address|allowIPv6PrefixLength|allowIPv6Router },
781 { CFSTR("RouterAdvertisement"), & kSCValNetIPv6ConfigMethodRouterAdvertisement, allowIPv6Address },
782 { CFSTR("6to4") , & kSCValNetIPv6ConfigMethod6to4 , 0 },
783 { NULL , NULL , 0 }
784};
785
786
787static int
788__doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
789{
1ef45fa4
A
790#pragma unused(description)
791#pragma unused(info)
792#pragma unused(argc)
793#pragma unused(argv)
dbf6a266
A
794 unsigned int flags;
795 CFStringRef method;
796 CFIndex methodIndex;
797
798 method = CFDictionaryGetValue(newConfiguration, key);
799 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
800 if (methodIndex != kCFNotFound) {
801 if (!(flags & allowIPv6Address)) {
802 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Addresses);
803 }
804 if (!(flags & allowIPv6PrefixLength)) {
805 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6PrefixLength);
806 }
807 if (!(flags & allowIPv6Router)) {
808 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Router);
809 }
810 } else {
811 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
812 return -1;
813 }
814
815 return 0;
816}
817
818
819static int
820__doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
821{
1ef45fa4
A
822#pragma unused(description)
823#pragma unused(argc)
dbf6a266
A
824 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
825
826 if (strlen(argv[0]) > 0) {
827 CFStringRef address;
828
829 address = __copyIPv6Address(argv[0]);
830 if (address != NULL) {
831 if (useArray) {
832 CFArrayRef addresses;
833
834 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
835 CFDictionarySetValue(newConfiguration, key, addresses);
836 CFRelease(addresses);
837 } else {
838 CFDictionarySetValue(newConfiguration, key, address);
839 }
840 CFRelease(address);
841 } else {
842 return -1;
843 }
844 } else {
845 CFDictionaryRemoveValue(newConfiguration, key);
846 }
847
848 return 1;
849}
850
c956c85e
A
851static int
852__doIPv6PrefixLength(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
853{
854#pragma unused(description)
855#pragma unused(argc)
856#pragma unused(info)
857 char * prefix = argv[0];
858 if (*prefix != '\0') {
859 char *end;
860 int prefixLength;
861
862 prefixLength = (int)strtol(prefix, &end, 10);
863 errno = 0;
864 if (*end == '\0' && errno == 0 && prefixLength > 0 && prefixLength <= 128) {
865 CFArrayRef prefixes;
866 CFNumberRef num;
867
868 num = CFNumberCreate(NULL, kCFNumberIntType, &prefixLength);
869 prefixes = CFArrayCreate(NULL, (const void **)&num, 1, &kCFTypeArrayCallBacks);
870 CFRelease(num);
871 CFDictionarySetValue(newConfiguration, key, prefixes);
872 CFRelease(prefixes);
873 } else {
874 SCPrint(TRUE, stdout, CFSTR("Invalid prefix length '%s' (valid range 1..128)\n"), prefix);
875 return -1;
876 }
877 } else {
878 CFDictionaryRemoveValue(newConfiguration, key);
879 }
880
881 return 1;
882}
883
dbf6a266 884
dbf6a266
A
885static options ipv6Options[] = {
886 { "ConfigMethod", "configuration method"
887 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
888 { "config" , "configuration method"
889 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
890 { "Addresses" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
891 { "address" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
afb19109 892 { "EnableCGA" , NULL , isBoolean , &kSCPropNetIPv6EnableCGA , NULL , NULL },
c956c85e 893 { "PrefixLength", "prefix length", isOther , &kSCPropNetIPv6PrefixLength, __doIPv6PrefixLength, NULL },
dbf6a266
A
894 { "Router" , "address" , isOther , &kSCPropNetIPv6Router , __doIPv6Addresses , (void *)FALSE },
895
896 { "?" , NULL , isHelp , NULL , NULL ,
897 "\nIPv6 configuration commands\n\n"
898 " set protocol config {Automatic|MANUAL}\n"
899 "\n w/config=Automatic\n"
900 " None\n"
901 "\n w/config=MANUAL\n"
902 " set protocol address x:x:x:x:x:x\n"
903 " set protocol router x:x:x:x:x:x\n"
904 " set protocol prefixlength n\n"
905 }
906};
907#define N_IPV6_OPTIONS (sizeof(ipv6Options) / sizeof(ipv6Options[0]))
908
909
910static Boolean
911set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
912{
913 Boolean ok;
914
915 ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration);
916 if (ok) {
917 unsigned int flags;
918 CFStringRef method;
919 CFIndex methodIndex;
920
921 // validate configuration
922 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod);
923 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
924 if (methodIndex == kCFNotFound) {
925 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
926 return FALSE;
927 }
928
929 if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) {
930 SCPrint(TRUE, stdout,
931 CFSTR("IP address not allowed with %@ configuration\n"),
932 ipv6ConfigMethods[methodIndex].selection);
933 return FALSE;
934 }
935
936 if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) {
937 SCPrint(TRUE, stdout,
938 CFSTR("Prefix length not allowed with %@ configuration\n"),
939 ipv6ConfigMethods[methodIndex].selection);
940 return FALSE;
941 }
942
943 if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) {
944 SCPrint(TRUE, stdout,
945 CFSTR("Router not allowed with %@ configuration\n"),
946 ipv6ConfigMethods[methodIndex].selection);
947 return FALSE;
948 }
949 }
950
951 return ok;
952}
953
954
edebe297
A
955#pragma mark -
956#pragma mark Proxies
dbf6a266
A
957
958
959typedef const struct {
960 const char *proxy;
961 const CFStringRef *keyEnable;
962 const CFStringRef *keyProxy;
963 const CFStringRef *keyPort;
964 const CFStringRef *keyURL;
2d62756f 965 const Boolean multiple_proxies;
dbf6a266
A
966} proxyKeys;
967
2d62756f
A
968static proxyKeys proxyKeys_FTP = { "FTP",
969 &kSCPropNetProxiesFTPEnable,
970 &kSCPropNetProxiesFTPProxy,
971 &kSCPropNetProxiesFTPPort,
972 NULL,
973 FALSE
974 };
975static proxyKeys proxyKeys_Gopher = { "Gopher",
976 &kSCPropNetProxiesGopherEnable,
977 &kSCPropNetProxiesGopherProxy,
978 &kSCPropNetProxiesGopherPort,
979 NULL,
980 FALSE
981 };
982static proxyKeys proxyKeys_HTTP = { "HTTP",
983 &kSCPropNetProxiesHTTPEnable,
984 &kSCPropNetProxiesHTTPProxy,
985 &kSCPropNetProxiesHTTPPort,
986 NULL,
987 FALSE
988 };
989static proxyKeys proxyKeys_HTTPS = { "HTTPS",
990 &kSCPropNetProxiesHTTPSEnable,
991 &kSCPropNetProxiesHTTPSProxy,
992 &kSCPropNetProxiesHTTPSPort,
993 NULL,
994 FALSE
995 };
996static proxyKeys proxyKeys_RTSP = { "RTSP",
997 &kSCPropNetProxiesRTSPEnable,
998 &kSCPropNetProxiesRTSPProxy,
999 &kSCPropNetProxiesRTSPPort,
1000 NULL,
1001 FALSE
1002 };
1003static proxyKeys proxyKeys_SOCKS = { "SOCKS",
1004 &kSCPropNetProxiesSOCKSEnable,
1005 &kSCPropNetProxiesSOCKSProxy,
1006 &kSCPropNetProxiesSOCKSPort,
1007 NULL,
1008 FALSE
1009 };
1010static proxyKeys proxyKeys_TransportConverter =
1011 { "TransportConverter",
1012 &kSCPropNetProxiesTransportConverterEnable,
1013 &kSCPropNetProxiesTransportConverterProxy,
1014 &kSCPropNetProxiesTransportConverterPort,
1015 NULL,
1016 TRUE
1017 };
1018static proxyKeys proxyKeys_PAC = { ".pac",
1019 &kSCPropNetProxiesProxyAutoConfigEnable,
1020 NULL,
1021 NULL,
1022 &kSCPropNetProxiesProxyAutoConfigURLString,
1023 FALSE};
1024static proxyKeys proxyKeys_WPAD = { "WPAD",
1025 &kSCPropNetProxiesProxyAutoDiscoveryEnable,
1026 NULL,
1027 NULL,
1028 NULL,
1029 FALSE};
dbf6a266
A
1030
1031static proxyKeys *currentProxy = NULL;
1032
1033
1034static int __doProxySelect (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1035static int __doProxyEnable (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1036static int __doProxyHost (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1037static int __doProxyPort (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1038static int __doProxyURL (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1039static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1040
1041
1042static options proxyOptions[] = {
1043 // general options
1044 { "ExceptionsList" , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList , NULL , NULL },
1045 { "ExcludeSimpleHostnames", NULL , isBoolean , &kSCPropNetProxiesExcludeSimpleHostnames, NULL , NULL },
1046 // proxy selection
1047 { "FTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_FTP },
1048 { "Gopher" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_Gopher },
1049 { "HTTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTP },
1050 { "HTTPS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTPS },
1051 { "RTSP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_RTSP },
1052 { "SOCKS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_SOCKS },
2d62756f 1053 { "TransportConverter" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_TransportConverter },
dbf6a266
A
1054 { "ProxyAutoConfig" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
1055 { ".pac" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
1056 { "ProxyAutoDiscovery" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
1057 { "WPAD" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
1058 // proxy modifiers
1059 { "disable" , NULL , isOther , NULL , __doProxyEnable , (void *)FALSE },
1060 { "enable" , NULL , isOther , NULL , __doProxyEnable , (void *)TRUE },
1061 { "proxy" , NULL , isOther , NULL , __doProxyHost , NULL },
1062 { "host" , NULL , isOther , NULL , __doProxyHost , NULL },
2d62756f
A
1063 { "proxies" , NULL , isOther , NULL , __doProxyHost , NULL },
1064 { "hosts" , NULL , isOther , NULL , __doProxyHost , NULL },
dbf6a266
A
1065 { "port" , NULL , isOther , NULL , __doProxyPort , NULL },
1066 { "url" , NULL , isOther , NULL , __doProxyURL , NULL },
1067 // (ftp) proxy modifiers
1068 { "FTPPassive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
1069 { "passive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
1070 // help
1071 { "?" , NULL , isHelp , NULL , NULL ,
1072 "\nProxy configuration commands\n\n"
1073 " set protocol ExceptionsList exception[,exception-2]\n"
1074 " set protocol ExcludeSimpleHostnames {enable|disable}\n"
1075 "\n"
1076 " set protocol ftp {enable|disable}\n"
1077 " set protocol ftp host proxy-host\n"
1078 " set protocol ftp port proxy-port\n"
1079 " set protocol ftp passive {enable|disable}\n"
1080 "\n"
1081 " set protocol http {enable|disable}\n"
1082 " set protocol http host proxy-host\n"
1083 " set protocol http port proxy-port\n"
1084 "\n"
1085 " set protocol https {enable|disable}\n"
1086 " set protocol https host proxy-host\n"
1087 " set protocol https port proxy-port\n"
1088 "\n"
1089 " set protocol rtsp {enable|disable}\n"
1090 " set protocol rtsp host proxy-host\n"
1091 " set protocol rtsp port proxy-port\n"
1092 "\n"
1093 " set protocol socks {enable|disable}\n"
1094 " set protocol socks host proxy-host\n"
1095 " set protocol socks port proxy-port\n"
1096 "\n"
2d62756f
A
1097 " set protocol transportconverter {enable|disable}\n"
1098 " set protocol transportconverter host[s] proxy-host[,proxy-host-2]\n"
1099 " set protocol transportconverter port proxy-port\n"
1100 "\n"
dbf6a266
A
1101 " set protocol .pac {enable|disable}\n"
1102 " set protocol .pac url .pac-url\n"
1103 "\n"
1104 " set protocol wpad {enable|disable}\n"
1105 }
1106};
1107#define N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0]))
1108
1109
1110static int
1111__doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1112{
1ef45fa4
A
1113#pragma unused(key)
1114#pragma unused(description)
1115#pragma unused(newConfiguration)
dbf6a266
A
1116 CFIndex nextOption;
1117
1118 if (argc < 1) {
1119 SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n"));
1120 return -1;
1121 }
1122
1123 currentProxy = (proxyKeys *)info;
1124
1125 nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS);
1126 if ((nextOption == kCFNotFound) ||
1127 (proxyOptions[nextOption].handler == __doProxySelect)) {
1128 SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy);
1129 return -1;
1130 }
1131
1132 return 0;
1133}
1134
1135
1136static int
1137__doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1138{
1ef45fa4
A
1139#pragma unused(key)
1140#pragma unused(description)
1141#pragma unused(argc)
1142#pragma unused(argv)
dbf6a266
A
1143 Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE;
1144
1145 if (currentProxy == NULL) {
1146 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1147 return -1;
1148 }
1149
1150 if (currentProxy->keyEnable == NULL) {
1151 SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"),
1152 currentProxy->proxy,
1153 enabled ? "enabled" : "disabled");
1154 return -1;
1155 }
1156
1157
1158 if (enabled) {
1159 CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1);
1160 } else {
a40a14f8 1161 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyEnable));
dbf6a266
A
1162
1163 if (currentProxy->keyProxy != NULL) {
1164 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1165 }
1166
1167 if (currentProxy->keyPort != NULL) {
1168 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1169 }
1170
1171 if (currentProxy->keyURL != NULL) {
1172 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1173 }
1174 }
1175
1176 return 0;
1177}
1178
1179
1180static Boolean
1181__proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey)
1182{
1183 CFNumberRef num;
1184 int val;
1185
1186 if (enableKey == NULL) {
1187 return TRUE; // if proxy does not need to be enabled
1188 }
1189
1190 num = CFDictionaryGetValue(configuration, *enableKey);
1191 if (!isA_CFNumber(num) ||
1192 !CFNumberGetValue(num, kCFNumberIntType, &val) ||
1193 (val == 0)) {
1194 return FALSE; // if not enabled
1195 }
1196
1197 return TRUE;
1198}
1199
1200
1201static int
1202__doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1203{
1ef45fa4
A
1204#pragma unused(key)
1205#pragma unused(description)
1206#pragma unused(info)
dbf6a266
A
1207 if (currentProxy == NULL) {
1208 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1209 return -1;
1210 }
1211
1212 if (currentProxy->keyProxy == NULL) {
1213 SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy);
1214 return -1;
1215 }
1216
1217 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1218 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1219 return -1;
1220 }
1221
1222 if (argc < 1) {
1223 SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy);
1224 return -1;
1225 }
1226
1227 if (strlen(argv[0]) > 0) {
2d62756f
A
1228 if (!currentProxy->multiple_proxies) {
1229 CFStringRef host;
dbf6a266 1230
2d62756f
A
1231 host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1232 CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host);
1233 CFRelease(host);
1234 } else {
1235 CFArrayRef hosts;
1236 CFStringRef hosts_str;
1237
1238 hosts_str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1239 hosts = CFStringCreateArrayBySeparatingStrings(NULL, hosts_str, CFSTR(","));
1240 CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), hosts);
1241 CFRelease(hosts);
1242 CFRelease(hosts_str);
1243 }
dbf6a266
A
1244 } else {
1245 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1246 }
1247
1248 return 1;
1249}
1250
1251
1252static int
1253__doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1254{
1ef45fa4
A
1255#pragma unused(key)
1256#pragma unused(description)
1257#pragma unused(info)
dbf6a266
A
1258 if (currentProxy == NULL) {
1259 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1260 return -1;
1261 }
1262
1263 if (currentProxy->keyPort == NULL) {
1264 SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy);
1265 return -1;
1266 }
1267
1268 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1269 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1270 return -1;
1271 }
1272
1273 if (argc < 1) {
1274 SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy);
1275 return -1;
1276 }
1277
1278 if (strlen(argv[0]) > 0) {
1279 CFNumberRef num;
1280 int port;
1281
1282 num = _copy_number(argv[0]);
1283 if (!isA_CFNumber(num) ||
1284 !CFNumberGetValue(num, kCFNumberIntType, &port) ||
1285 (port < 0) || (port > 65535)) {
1286 SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
17d3ee29 1287 if (num != NULL) CFRelease(num);
dbf6a266
A
1288 return -1;
1289 }
1290
1291 CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num);
1292 CFRelease(num);
1293 } else {
1294 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1295 }
1296
1297 return 1;
1298}
1299
1300
1301static int
1302__doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1303{
1ef45fa4
A
1304#pragma unused(key)
1305#pragma unused(description)
1306#pragma unused(info)
dbf6a266
A
1307 if (currentProxy == NULL) {
1308 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1309 return -1;
1310 }
1311
1312 if (currentProxy->keyURL == NULL) {
1313 SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy);
1314 return -1;
1315 }
1316
1317 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1318 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1319 return -1;
1320 }
1321
1322 if (argc < 1) {
1323 SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy);
1324 return -1;
1325 }
1326
1327 if (strlen(argv[0]) > 0) {
1328 CFStringRef url;
1329
1330 url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1331 CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url);
1332 CFRelease(url);
1333 } else {
1334 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1335 }
1336
1337 return 1;
1338}
1339
1340
1341static int
1342__doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1343{
1ef45fa4
A
1344#pragma unused(key)
1345#pragma unused(description)
1346#pragma unused(info)
1347#pragma unused(argc)
1348#pragma unused(argv)
1349#pragma unused(newConfiguration)
dbf6a266
A
1350 if (currentProxy == NULL) {
1351 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1352 return -1;
1353 }
1354
1355 if (currentProxy != &proxyKeys_FTP) {
1356 SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n"));
1357 return -1;
1358 }
1359
1360 return 0;
1361}
1362
1363
1364static Boolean
1365set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1366{
1367 Boolean ok;
1368
1369 ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration);
1370 return ok;
1371}
1372
1373
edebe297
A
1374#pragma mark -
1375#pragma mark SMB
1376
1377
a40a14f8
A
1378#if !TARGET_OS_IPHONE
1379
1380
17d3ee29 1381static CF_RETURNS_RETAINED CFStringRef
edebe297
A
1382__cleanupName(CFStringRef name)
1383{
1384 CFMutableStringRef newName;
1385
1386 newName = CFStringCreateMutableCopy(NULL, 0, name);
1387 CFStringTrimWhitespace(newName);
1388 if (CFStringGetLength(newName) == 0) {
1389 CFRelease(newName);
1390 newName = NULL;
1391 }
1392
1393 return newName;
1394}
1395
1396
1397static int
1398__doSMBName(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1399{
1ef45fa4
A
1400#pragma unused(description)
1401#pragma unused(info)
edebe297
A
1402 if (argc < 1) {
1403 SCPrint(TRUE, stdout, CFSTR("NetBIOS name not specified\n"));
1404 return -1;
1405 }
1406
1407 if (strlen(argv[0]) > 0) {
1408 CFStringRef name;
1409 CFStringRef str;
1410
1411 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1412 name = __cleanupName(str);
1413 CFRelease(str);
1414
1415 if (name != NULL) {
1416 CFDictionarySetValue(newConfiguration, key, name);
1417 CFRelease(name);
1418 } else {
1419 SCPrint(TRUE, stdout, CFSTR("invalid NetBIOS name\n"));
1420 return -1;
1421 }
1422 } else {
1423 CFDictionaryRemoveValue(newConfiguration, key);
1424 }
1425
1426 return 1;
1427}
1428
1429
1430static int
1431__doSMBWorkgroup(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1432{
1ef45fa4
A
1433#pragma unused(description)
1434#pragma unused(info)
edebe297
A
1435 if (argc < 1) {
1436 SCPrint(TRUE, stdout, CFSTR("Workgroup not specified\n"));
1437 return -1;
1438 }
1439
1440 if (strlen(argv[0]) > 0) {
1441 CFStringRef name;
1442 CFStringRef str;
1443
1444 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1445 name = __cleanupName(str);
1446 CFRelease(str);
1447
1448 if (name != NULL) {
1449 CFDictionarySetValue(newConfiguration, key, name);
1450 CFRelease(name);
1451 } else {
1452 SCPrint(TRUE, stdout, CFSTR("invalid Workgroup\n"));
1453 return -1;
1454 }
1455 } else {
1456 CFDictionaryRemoveValue(newConfiguration, key);
1457 }
1458
1459 return 1;
1460}
1461
1462
1463static int
1464__doSMBWINSAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1465{
1ef45fa4
A
1466#pragma unused(description)
1467#pragma unused(info)
edebe297
A
1468 CFMutableArrayRef servers;
1469
1470 if (argc < 1) {
1471 SCPrint(TRUE, stdout, CFSTR("WINS address(es) not specified\n"));
1472 return -1;
1473 }
1474
1475 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1476
1477 if (strlen(argv[0]) > 0) {
1478 CFArrayRef array;
1479 CFIndex i;
1480 CFIndex n;
1481 CFStringRef str;
1482
1483 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1484 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
1485 CFRelease(str);
1486
1487 n = (array != NULL) ? CFArrayGetCount(array) : 0;
1488 for (i = 0; i < n; i++) {
1489 char str[32];
1490
1491 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
1492 str,
1493 sizeof(str),
1494 kCFStringEncodingUTF8) != NULL) {
1495 CFStringRef server;
1496
1497 server = __copyIPv4Address(str);
1498 //if (server == NULL) {
1499 // server = __copyIPv6Address(str);
1500 //}
1501 if (server != NULL) {
1502 CFArrayAppendValue(servers, server);
1503 CFRelease(server);
1504 continue;
1505 }
1506 }
1507
1508 SCPrint(TRUE, stdout, CFSTR("invalid WINS address\n"));
1509 CFRelease(array);
1510 CFRelease(servers);
1511 return -1;
1512 }
1513 if (array != NULL) CFRelease(array);
1514 }
1515
1516 if (CFArrayGetCount(servers) > 0) {
1517 CFDictionarySetValue(newConfiguration, key, servers);
1518 } else {
1519 CFDictionaryRemoveValue(newConfiguration, key);
1520 }
1521
1522 CFRelease(servers);
1523 return 1;
1524}
1525
1526
1527static selections smbNodeTypes[] = {
1528 { CFSTR("Broadcast"), &kSCValNetSMBNetBIOSNodeTypeBroadcast, 0 },
1529 { CFSTR("Peer") , &kSCValNetSMBNetBIOSNodeTypePeer , 0 },
1530 { CFSTR("Mixed") , &kSCValNetSMBNetBIOSNodeTypeMixed , 0 },
1531 { CFSTR("Hybrid") , &kSCValNetSMBNetBIOSNodeTypeHybrid , 0 },
1532 { NULL , NULL , 0 }
1533};
1534
1535
1536static options smbOptions[] = {
1537 { "NetBIOSName" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
1538 { "name" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
1539 { "NetBIOSNodeType", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
1540 { "type", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
1541 { "Workgroup" , "workgroup", isOther , &kSCPropNetSMBWorkgroup , __doSMBWorkgroup , NULL },
1542 { "WINSAddresses" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
1543 { "wins" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
1544
1545 { "?" , NULL , isHelp , NULL , NULL,
1546 "\nSMB configuration commands\n\n"
1547 " set protocol name NetBIOS-name\n"
1548 " set protocol type (Broadcast|Peer|Mixed|Hybrid)\n"
1549 " set protocol workgroup SMB-workgroup\n"
a40a14f8 1550 " set protocol wins x1.x1.x1.x1[,x2.x2.x2.x2]\n"
edebe297
A
1551 }
1552};
1553#define N_SMB_OPTIONS (sizeof(smbOptions) / sizeof(smbOptions[0]))
1554
1555
1556static Boolean
1557set_protocol_smb(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1558{
1559 Boolean ok;
1560
1561 ok = _process_options(smbOptions, N_SMB_OPTIONS, argc, argv, newConfiguration);
1562 return ok;
1563}
1564
1565
a40a14f8
A
1566#endif // !TARGET_OS_IPHONE
1567
1568
edebe297
A
1569#pragma mark -
1570#pragma mark *Protocol*
dbf6a266
A
1571
1572
1573__private_extern__
1574void
1575set_protocol(int argc, char **argv)
1576{
1577 CFDictionaryRef configuration;
1578 CFMutableDictionaryRef newConfiguration = NULL;
1579 Boolean ok = FALSE;
1580 CFStringRef protocolType;
1581
1582 if (net_protocol == NULL) {
1583 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1584 return;
1585 }
1586
1587 if (argc < 1) {
1588 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1589 return;
1590 }
1591
1592 configuration = SCNetworkProtocolGetConfiguration(net_protocol);
1593 if (configuration == NULL) {
1594 newConfiguration = CFDictionaryCreateMutable(NULL,
1595 0,
1596 &kCFTypeDictionaryKeyCallBacks,
1597 &kCFTypeDictionaryValueCallBacks);
1598 } else {
1599 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
1600 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
1601 }
1602
1603 protocolType = SCNetworkProtocolGetProtocolType(net_protocol);
a40a14f8 1604 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
dbf6a266
A
1605 ok = set_protocol_dns(argc, argv, newConfiguration);
1606 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1607 ok = set_protocol_ipv4(argc, argv, newConfiguration);
1608 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1609 ok = set_protocol_ipv6(argc, argv, newConfiguration);
1610 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
1611 ok = set_protocol_proxies(argc, argv, newConfiguration);
a40a14f8 1612#if !TARGET_OS_IPHONE
edebe297
A
1613 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) {
1614 ok = set_protocol_smb(argc, argv, newConfiguration);
a40a14f8 1615#endif // !TARGET_OS_IPHONE
dbf6a266
A
1616 } else {
1617 SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n"));
1618 }
1619
1620 if (!ok) {
1621 goto done;
1622 }
1623
1624 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
1625 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
1626 if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) {
1627 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1628 goto done;
1629 }
1630
edebe297 1631 _prefs_changed = TRUE;
dbf6a266
A
1632 }
1633
1634 done :
1635
1636 if (newConfiguration != NULL) CFRelease(newConfiguration);
1637 return;
1638}
1639
1640
1641/* -------------------- */
1642
1643
1644__private_extern__
1645void
1646show_protocol(int argc, char **argv)
1647{
1648 CFDictionaryRef configuration;
1649 SCNetworkProtocolRef protocol = NULL;
1650 CFStringRef protocolType;
1651
1652 if (argc > 0) {
1653 protocol = _find_protocol(argv[0]);
1654 } else {
1655 if (net_protocol != NULL) {
1656 protocol = net_protocol;
1657 } else {
1658 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1659 return;
1660 }
1661 }
1662
1663 if (protocol == NULL) {
1664 return;
1665 }
1666
1667 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1668 SCPrint(TRUE, stdout, CFSTR("protocol type = %@\n"), protocolType);
1669
1670 configuration = SCNetworkProtocolGetConfiguration(protocol);
1671 if (configuration != NULL) {
1672 SCPrint(TRUE, stdout, CFSTR("\n protocol configuration\n"));
1673 _show_entity(configuration, CFSTR(""));
1674 }
1675
1676 if (_sc_debug) {
1677 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol);
1678 }
1679
1680 return;
1681}
1682
1683
1684/* -------------------- */
1685
1686
1687__private_extern__
1688void
1689show_protocols(int argc, char **argv)
1690{
1ef45fa4
A
1691#pragma unused(argc)
1692#pragma unused(argv)
dbf6a266
A
1693 CFIndex i;
1694 CFIndex n;
1695
1696 if (prefs == NULL) {
1697 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1698 return;
1699 }
1700
1701 if (net_service == NULL) {
1702 SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
1703 return;
1704 }
1705
1706 if (protocols != NULL) CFRelease(protocols);
1707 protocols = SCNetworkServiceCopyProtocols(net_service);
1708 if (protocols == NULL) {
1709 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1710 return;
1711 }
1712
1713 n = CFArrayGetCount(protocols);
1714 if (n > 1) {
1715 CFMutableArrayRef sorted;
1716
1717 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
1718 CFArraySortValues(sorted,
1719 CFRangeMake(0, n),
1ef45fa4 1720 _SCNetworkProtocolCompare,
dbf6a266
A
1721 NULL);
1722 CFRelease(protocols);
1723 protocols = sorted;
1724 }
1725
1726 for (i = 0; i < n; i++) {
1727 SCNetworkProtocolRef protocol;
1728 CFStringRef protocolType;
1729
1730 protocol = CFArrayGetValueAtIndex(protocols, i);
1731 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1732
78403150 1733 SCPrint(TRUE, stdout, CFSTR("%c%2ld: %@%*s :"),
dbf6a266
A
1734 ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ',
1735 i + 1,
1736 protocolType,
942cecd7 1737 (int)(sizeof("Proxies") - CFStringGetLength(protocolType) - 1),
dbf6a266
A
1738 "");
1739
1740 if (SCNetworkProtocolGetEnabled(protocol)) {
1741 CFStringRef description;
1742
1743 description = _protocol_description(protocol, FALSE);
1744 SCPrint(TRUE, stdout, CFSTR(" %@"), description);
1745 CFRelease(description);
1746 } else {
1747 SCPrint(TRUE, stdout, CFSTR(" *DISABLED*"));
1748 }
1749 SCPrint(TRUE, stdout, CFSTR("\n"));
1750 }
1751
1752 return;
1753}
1754
1755
1756/* -------------------- */
1757
1758
1759__private_extern__
17d3ee29 1760CF_RETURNS_RETAINED CFStringRef
dbf6a266
A
1761_protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
1762{
1763 CFDictionaryRef configuration;
1764 CFMutableStringRef description = NULL;
1765 CFStringRef protocolType;
1766
1767 description = CFStringCreateMutable(NULL, 0);
1768
1769 if (!SCNetworkProtocolGetEnabled(protocol)) {
1770 goto done;
1771 }
1772
1773 configuration = SCNetworkProtocolGetConfiguration(protocol);
1774 if (configuration == NULL) {
1775 goto done;
1776 }
1777
1778 protocolType = SCNetworkProtocolGetProtocolType(protocol);
a40a14f8 1779 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
dbf6a266
A
1780 CFStringRef domain;
1781 CFArrayRef search;
1782 CFArrayRef servers;
1783
1784 domain = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName);
1785 if (isA_CFString(domain)) {
1786 CFStringAppendFormat(description,
1787 NULL,
1788 CFSTR("domain=%@"),
1789 domain);
1790 }
1791
1792 search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains);
1793 if (isA_CFArray(search)) {
1794 CFStringRef str;
1795
1796 str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(","));
1797 CFStringAppendFormat(description,
1798 NULL,
1799 CFSTR("%ssearch=%@"),
1800 CFStringGetLength(description) > 0 ? ", " : "",
1801 str);
1802 CFRelease(str);
1803 }
1804
1805 servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses);
1806 if (isA_CFArray(servers)) {
1807 CFStringRef str;
1808
1809 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
1810 CFStringAppendFormat(description,
1811 NULL,
1812 CFSTR("%sservers=%@"),
1813 CFStringGetLength(description) > 0 ? ", " : "",
1814 str);
1815 CFRelease(str);
1816 }
1817 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1818 CFStringRef method;
1819
1820 method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod);
1821 if (isA_CFString(method)) {
1822 CFArrayRef addresses;
1823
1824 addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses);
1825 if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) &&
1826 isA_CFArray(addresses)) {
1827 CFStringAppendFormat(description,
1828 NULL,
1829 CFSTR("%@, address=%@"),
1830 method,
1831 CFArrayGetValueAtIndex(addresses, 0));
1832 } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) &&
1833 isA_CFArray(addresses)) {
afb19109 1834 CFArrayRef masks;
1ef45fa4
A
1835 CFStringRef router;
1836
dbf6a266
A
1837 CFStringAppendFormat(description,
1838 NULL,
1839 CFSTR("%@, address=%@"),
1840 method,
1841 CFArrayGetValueAtIndex(addresses, 0));
1ef45fa4 1842
afb19109
A
1843 if (CFDictionaryGetValueIfPresent(configuration,
1844 kSCPropNetIPv4SubnetMasks,
1845 (const void **)&masks) &&
1846 isA_CFArray(masks)) {
1847 CFStringAppendFormat(description,
1848 NULL,
1849 CFSTR(", mask=%@"),
1850 CFArrayGetValueAtIndex(masks, 0));
1851 }
1852
1ef45fa4
A
1853 if (CFDictionaryGetValueIfPresent(configuration,
1854 kSCPropNetIPv4Router,
1855 (const void **)&router) &&
1856 isA_CFString(router)) {
1857 CFStringAppendFormat(description,
1858 NULL,
1859 CFSTR(", router=%@"),
1860 router);
1861 }
dbf6a266
A
1862 } else {
1863 CFStringAppendFormat(description,
1864 NULL,
1865 CFSTR("%@"),
1866 method);
1867 }
1868 }
1869 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1870 CFStringRef method;
1871
1872 method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod);
1873 if (isA_CFString(method)) {
1874 CFStringAppendFormat(description,
1875 NULL,
1876 CFSTR("%@"),
1877 method);
1878 }
1879 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
dbf6a266
A
1880 static proxyKeys *keys[] = { &proxyKeys_FTP, &proxyKeys_Gopher, &proxyKeys_HTTP, &proxyKeys_HTTPS,
1881 &proxyKeys_RTSP, &proxyKeys_SOCKS, &proxyKeys_PAC, &proxyKeys_WPAD };
1882
1ef45fa4 1883 for (size_t i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
dbf6a266
A
1884 proxyKeys *currentProxy = keys[i];
1885
1886 if (!__proxy_enabled(configuration, currentProxy->keyEnable)) {
1887 continue;
1888 }
1889
1890 if (((currentProxy->keyProxy != NULL) &&
1891 !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) ||
1892 ((currentProxy->keyURL != NULL) &&
1893 !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) {
1894 continue;
1895 }
1896
1897 CFStringAppendFormat(description,
1898 NULL,
1899 CFSTR("%s%s"),
1900 CFStringGetLength(description) > 0 ? ", " : "",
1901 currentProxy->proxy);
1902 }
a40a14f8 1903#if !TARGET_OS_IPHONE
edebe297
A
1904 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) {
1905 CFStringRef name;
1906 CFArrayRef servers;
1907 CFStringRef workgroup;
1908
1909 name = CFDictionaryGetValue(configuration, kSCPropNetSMBNetBIOSName);
1910 if (isA_CFString(name)) {
1911 CFStringAppendFormat(description,
1912 NULL,
1913 CFSTR("NetBIOS name=%@"),
1914 name);
1915 }
1916
1917 workgroup = CFDictionaryGetValue(configuration, kSCPropNetSMBWorkgroup);
1918 if (isA_CFString(workgroup)) {
1919 CFStringAppendFormat(description,
1920 NULL,
1921 CFSTR("Workgroup=%@"),
1922 workgroup);
1923 }
1924
1925 servers = CFDictionaryGetValue(configuration, kSCPropNetSMBWINSAddresses);
1926 if (isA_CFArray(servers)) {
1927 CFStringRef str;
1928
1929 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
1930 CFStringAppendFormat(description,
1931 NULL,
1932 CFSTR("%sWINS servers=%@"),
1933 CFStringGetLength(description) > 0 ? ", " : "",
1934 str);
1935 CFRelease(str);
1936 }
a40a14f8 1937#endif // !TARGET_OS_IPHONE
dbf6a266
A
1938 }
1939
1940 done :
1941
1942 if (skipEmpty && CFStringGetLength(description) == 0) {
1943 CFRelease(description);
1944 description = NULL;
1945 }
1946
1947 return description;
1948}