]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/net_protocol.c
configd-963.30.1.tar.gz
[apple/configd.git] / scutil.tproj / net_protocol.c
1 /*
2 * Copyright (c) 2004-2009, 2011, 2014, 2017 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_protocol.h"
35 #include "prefs.h"
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
47 static CFStringRef
48 __copyIPv4Address(const char *arg)
49 {
50 char buf[128];
51 struct sockaddr_in sin;
52
53 if (_SC_string_to_sockaddr(arg, AF_INET, (void *)&sin, sizeof(sin)) == NULL) {
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
62 static CFStringRef
63 __copyIPv6Address(const char *arg)
64 {
65 char buf[128];
66 struct sockaddr_in6 sin6;
67
68 if (_SC_string_to_sockaddr(arg, AF_INET6, (void *)&sin6, sizeof(sin6)) == NULL) {
69 return NULL;
70 }
71
72 _SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf));
73 return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
74 }
75
76
77 /* -------------------- */
78
79
80 static 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),
108 _SCNetworkProtocolCompare,
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__
167 void
168 create_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
212 _prefs_changed = TRUE;
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__
243 void
244 disable_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
268 _prefs_changed = TRUE;
269
270 return;
271 }
272
273
274 /* -------------------- */
275
276
277 __private_extern__
278 void
279 enable_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
303 _prefs_changed = TRUE;
304
305 return;
306 }
307
308
309 /* -------------------- */
310
311
312 __private_extern__
313 void
314 remove_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
342 _prefs_changed = TRUE;
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__
370 void
371 select_protocol(int argc, char **argv)
372 {
373 #pragma unused(argc)
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
393 #pragma mark -
394 #pragma mark DNS
395
396
397 static CF_RETURNS_RETAINED CFStringRef
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
414 static int
415 __doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
416 {
417 #pragma unused(description)
418 #pragma unused(info)
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
447 static int
448 __doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
449 {
450 #pragma unused(description)
451 #pragma unused(info)
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
502 static int
503 __doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
504 {
505 #pragma unused(description)
506 #pragma unused(info)
507 CFMutableArrayRef servers;
508
509 if (argc < 1) {
510 SCPrint(TRUE, stdout, CFSTR("DNS name server address(es) not specified\n"));
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
566 static 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 },
574 { "SupplementalMatchDomains",
575 "domain",
576 isOther,
577 &kSCPropNetDNSSupplementalMatchDomains,
578 __doDNSDomainArray,
579 NULL },
580
581 { "?" , NULL , isHelp , NULL , NULL,
582 "\nDNS configuration commands\n\n"
583 " set protocol search domain-name[,domain-name-2]\n"
584 " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]\n"
585 }
586 };
587 #define N_DNS_OPTIONS (sizeof(dnsOptions) / sizeof(dnsOptions[0]))
588
589
590 static Boolean
591 set_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
600 #pragma mark -
601 #pragma mark IPv4
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
609 static 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
620 static int
621 __doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
622 {
623 #pragma unused(description)
624 #pragma unused(info)
625 #pragma unused(argc)
626 #pragma unused(argv)
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
655 static int
656 __doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
657 {
658 #pragma unused(description)
659 #pragma unused(argc)
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
688 static 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
718 static Boolean
719 set_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
770 #pragma mark -
771 #pragma mark IPv6
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
778 static 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
787 static int
788 __doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
789 {
790 #pragma unused(description)
791 #pragma unused(info)
792 #pragma unused(argc)
793 #pragma unused(argv)
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
819 static int
820 __doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
821 {
822 #pragma unused(description)
823 #pragma unused(argc)
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
851
852 static options ipv6Options[] = {
853 { "ConfigMethod", "configuration method"
854 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
855 { "config" , "configuration method"
856 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
857 { "Addresses" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
858 { "address" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
859 { "PrefixLength", "prefix length", isNumber , &kSCPropNetIPv6PrefixLength, NULL , NULL },
860 { "Router" , "address" , isOther , &kSCPropNetIPv6Router , __doIPv6Addresses , (void *)FALSE },
861
862 { "?" , NULL , isHelp , NULL , NULL ,
863 "\nIPv6 configuration commands\n\n"
864 " set protocol config {Automatic|MANUAL}\n"
865 "\n w/config=Automatic\n"
866 " None\n"
867 "\n w/config=MANUAL\n"
868 " set protocol address x:x:x:x:x:x\n"
869 " set protocol router x:x:x:x:x:x\n"
870 " set protocol prefixlength n\n"
871 }
872 };
873 #define N_IPV6_OPTIONS (sizeof(ipv6Options) / sizeof(ipv6Options[0]))
874
875
876 static Boolean
877 set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
878 {
879 Boolean ok;
880
881 ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration);
882 if (ok) {
883 unsigned int flags;
884 CFStringRef method;
885 CFIndex methodIndex;
886
887 // validate configuration
888 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod);
889 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
890 if (methodIndex == kCFNotFound) {
891 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
892 return FALSE;
893 }
894
895 if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) {
896 SCPrint(TRUE, stdout,
897 CFSTR("IP address not allowed with %@ configuration\n"),
898 ipv6ConfigMethods[methodIndex].selection);
899 return FALSE;
900 }
901
902 if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) {
903 SCPrint(TRUE, stdout,
904 CFSTR("Prefix length not allowed with %@ configuration\n"),
905 ipv6ConfigMethods[methodIndex].selection);
906 return FALSE;
907 }
908
909 if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) {
910 SCPrint(TRUE, stdout,
911 CFSTR("Router not allowed with %@ configuration\n"),
912 ipv6ConfigMethods[methodIndex].selection);
913 return FALSE;
914 }
915 }
916
917 return ok;
918 }
919
920
921 #pragma mark -
922 #pragma mark Proxies
923
924
925 typedef const struct {
926 const char *proxy;
927 const CFStringRef *keyEnable;
928 const CFStringRef *keyProxy;
929 const CFStringRef *keyPort;
930 const CFStringRef *keyURL;
931 } proxyKeys;
932
933 static proxyKeys proxyKeys_FTP = { "FTP" , &kSCPropNetProxiesFTPEnable , &kSCPropNetProxiesFTPProxy , &kSCPropNetProxiesFTPPort , NULL };
934 static proxyKeys proxyKeys_Gopher = { "Gopher", &kSCPropNetProxiesGopherEnable , &kSCPropNetProxiesGopherProxy, &kSCPropNetProxiesGopherPort, NULL };
935 static proxyKeys proxyKeys_HTTP = { "HTTP" , &kSCPropNetProxiesHTTPEnable , &kSCPropNetProxiesHTTPProxy , &kSCPropNetProxiesHTTPPort , NULL };
936 static proxyKeys proxyKeys_HTTPS = { "HTTPS" , &kSCPropNetProxiesHTTPSEnable , &kSCPropNetProxiesHTTPSProxy , &kSCPropNetProxiesHTTPSPort , NULL };
937 static proxyKeys proxyKeys_RTSP = { "RTSP" , &kSCPropNetProxiesRTSPEnable , &kSCPropNetProxiesRTSPProxy , &kSCPropNetProxiesRTSPPort , NULL };
938 static proxyKeys proxyKeys_SOCKS = { "SOCKS" , &kSCPropNetProxiesSOCKSEnable , &kSCPropNetProxiesSOCKSProxy , &kSCPropNetProxiesSOCKSPort , NULL };
939 static proxyKeys proxyKeys_PAC = { ".pac" , &kSCPropNetProxiesProxyAutoConfigEnable , NULL , NULL , &kSCPropNetProxiesProxyAutoConfigURLString };
940 static proxyKeys proxyKeys_WPAD = { "WPAD" , &kSCPropNetProxiesProxyAutoDiscoveryEnable, NULL , NULL , NULL };
941
942 static proxyKeys *currentProxy = NULL;
943
944
945 static int __doProxySelect (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
946 static int __doProxyEnable (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
947 static int __doProxyHost (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
948 static int __doProxyPort (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
949 static int __doProxyURL (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
950 static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
951
952
953 static options proxyOptions[] = {
954 // general options
955 { "ExceptionsList" , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList , NULL , NULL },
956 { "ExcludeSimpleHostnames", NULL , isBoolean , &kSCPropNetProxiesExcludeSimpleHostnames, NULL , NULL },
957 // proxy selection
958 { "FTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_FTP },
959 { "Gopher" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_Gopher },
960 { "HTTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTP },
961 { "HTTPS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTPS },
962 { "RTSP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_RTSP },
963 { "SOCKS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_SOCKS },
964 { "ProxyAutoConfig" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
965 { ".pac" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
966 { "ProxyAutoDiscovery" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
967 { "WPAD" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
968 // proxy modifiers
969 { "disable" , NULL , isOther , NULL , __doProxyEnable , (void *)FALSE },
970 { "enable" , NULL , isOther , NULL , __doProxyEnable , (void *)TRUE },
971 { "proxy" , NULL , isOther , NULL , __doProxyHost , NULL },
972 { "host" , NULL , isOther , NULL , __doProxyHost , NULL },
973 { "port" , NULL , isOther , NULL , __doProxyPort , NULL },
974 { "url" , NULL , isOther , NULL , __doProxyURL , NULL },
975 // (ftp) proxy modifiers
976 { "FTPPassive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
977 { "passive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
978 // help
979 { "?" , NULL , isHelp , NULL , NULL ,
980 "\nProxy configuration commands\n\n"
981 " set protocol ExceptionsList exception[,exception-2]\n"
982 " set protocol ExcludeSimpleHostnames {enable|disable}\n"
983 "\n"
984 " set protocol ftp {enable|disable}\n"
985 " set protocol ftp host proxy-host\n"
986 " set protocol ftp port proxy-port\n"
987 " set protocol ftp passive {enable|disable}\n"
988 "\n"
989 " set protocol http {enable|disable}\n"
990 " set protocol http host proxy-host\n"
991 " set protocol http port proxy-port\n"
992 "\n"
993 " set protocol https {enable|disable}\n"
994 " set protocol https host proxy-host\n"
995 " set protocol https port proxy-port\n"
996 "\n"
997 " set protocol rtsp {enable|disable}\n"
998 " set protocol rtsp host proxy-host\n"
999 " set protocol rtsp port proxy-port\n"
1000 "\n"
1001 " set protocol socks {enable|disable}\n"
1002 " set protocol socks host proxy-host\n"
1003 " set protocol socks port proxy-port\n"
1004 "\n"
1005 " set protocol .pac {enable|disable}\n"
1006 " set protocol .pac url .pac-url\n"
1007 "\n"
1008 " set protocol wpad {enable|disable}\n"
1009 }
1010 };
1011 #define N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0]))
1012
1013
1014 static int
1015 __doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1016 {
1017 #pragma unused(key)
1018 #pragma unused(description)
1019 #pragma unused(newConfiguration)
1020 CFIndex nextOption;
1021
1022 if (argc < 1) {
1023 SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n"));
1024 return -1;
1025 }
1026
1027 currentProxy = (proxyKeys *)info;
1028
1029 nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS);
1030 if ((nextOption == kCFNotFound) ||
1031 (proxyOptions[nextOption].handler == __doProxySelect)) {
1032 SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy);
1033 return -1;
1034 }
1035
1036 return 0;
1037 }
1038
1039
1040 static int
1041 __doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1042 {
1043 #pragma unused(key)
1044 #pragma unused(description)
1045 #pragma unused(argc)
1046 #pragma unused(argv)
1047 Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE;
1048
1049 if (currentProxy == NULL) {
1050 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1051 return -1;
1052 }
1053
1054 if (currentProxy->keyEnable == NULL) {
1055 SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"),
1056 currentProxy->proxy,
1057 enabled ? "enabled" : "disabled");
1058 return -1;
1059 }
1060
1061
1062 if (enabled) {
1063 CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1);
1064 } else {
1065 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyEnable));
1066
1067 if (currentProxy->keyProxy != NULL) {
1068 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1069 }
1070
1071 if (currentProxy->keyPort != NULL) {
1072 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1073 }
1074
1075 if (currentProxy->keyURL != NULL) {
1076 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1077 }
1078 }
1079
1080 return 0;
1081 }
1082
1083
1084 static Boolean
1085 __proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey)
1086 {
1087 CFNumberRef num;
1088 int val;
1089
1090 if (enableKey == NULL) {
1091 return TRUE; // if proxy does not need to be enabled
1092 }
1093
1094 num = CFDictionaryGetValue(configuration, *enableKey);
1095 if (!isA_CFNumber(num) ||
1096 !CFNumberGetValue(num, kCFNumberIntType, &val) ||
1097 (val == 0)) {
1098 return FALSE; // if not enabled
1099 }
1100
1101 return TRUE;
1102 }
1103
1104
1105 static int
1106 __doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1107 {
1108 #pragma unused(key)
1109 #pragma unused(description)
1110 #pragma unused(info)
1111 if (currentProxy == NULL) {
1112 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1113 return -1;
1114 }
1115
1116 if (currentProxy->keyProxy == NULL) {
1117 SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy);
1118 return -1;
1119 }
1120
1121 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1122 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1123 return -1;
1124 }
1125
1126 if (argc < 1) {
1127 SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy);
1128 return -1;
1129 }
1130
1131 if (strlen(argv[0]) > 0) {
1132 CFStringRef host;
1133
1134 host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1135 CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host);
1136 CFRelease(host);
1137 } else {
1138 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1139 }
1140
1141 return 1;
1142 }
1143
1144
1145 static int
1146 __doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1147 {
1148 #pragma unused(key)
1149 #pragma unused(description)
1150 #pragma unused(info)
1151 if (currentProxy == NULL) {
1152 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1153 return -1;
1154 }
1155
1156 if (currentProxy->keyPort == NULL) {
1157 SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy);
1158 return -1;
1159 }
1160
1161 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1162 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1163 return -1;
1164 }
1165
1166 if (argc < 1) {
1167 SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy);
1168 return -1;
1169 }
1170
1171 if (strlen(argv[0]) > 0) {
1172 CFNumberRef num;
1173 int port;
1174
1175 num = _copy_number(argv[0]);
1176 if (!isA_CFNumber(num) ||
1177 !CFNumberGetValue(num, kCFNumberIntType, &port) ||
1178 (port < 0) || (port > 65535)) {
1179 SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
1180 if (num != NULL) CFRelease(num);
1181 return -1;
1182 }
1183
1184 CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num);
1185 CFRelease(num);
1186 } else {
1187 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1188 }
1189
1190 return 1;
1191 }
1192
1193
1194 static int
1195 __doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1196 {
1197 #pragma unused(key)
1198 #pragma unused(description)
1199 #pragma unused(info)
1200 if (currentProxy == NULL) {
1201 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1202 return -1;
1203 }
1204
1205 if (currentProxy->keyURL == NULL) {
1206 SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy);
1207 return -1;
1208 }
1209
1210 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1211 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1212 return -1;
1213 }
1214
1215 if (argc < 1) {
1216 SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy);
1217 return -1;
1218 }
1219
1220 if (strlen(argv[0]) > 0) {
1221 CFStringRef url;
1222
1223 url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1224 CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url);
1225 CFRelease(url);
1226 } else {
1227 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1228 }
1229
1230 return 1;
1231 }
1232
1233
1234 static int
1235 __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1236 {
1237 #pragma unused(key)
1238 #pragma unused(description)
1239 #pragma unused(info)
1240 #pragma unused(argc)
1241 #pragma unused(argv)
1242 #pragma unused(newConfiguration)
1243 if (currentProxy == NULL) {
1244 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1245 return -1;
1246 }
1247
1248 if (currentProxy != &proxyKeys_FTP) {
1249 SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n"));
1250 return -1;
1251 }
1252
1253 return 0;
1254 }
1255
1256
1257 static Boolean
1258 set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1259 {
1260 Boolean ok;
1261
1262 ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration);
1263 return ok;
1264 }
1265
1266
1267 #pragma mark -
1268 #pragma mark SMB
1269
1270
1271 #if !TARGET_OS_IPHONE
1272
1273
1274 static CF_RETURNS_RETAINED CFStringRef
1275 __cleanupName(CFStringRef name)
1276 {
1277 CFMutableStringRef newName;
1278
1279 newName = CFStringCreateMutableCopy(NULL, 0, name);
1280 CFStringTrimWhitespace(newName);
1281 if (CFStringGetLength(newName) == 0) {
1282 CFRelease(newName);
1283 newName = NULL;
1284 }
1285
1286 return newName;
1287 }
1288
1289
1290 static int
1291 __doSMBName(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1292 {
1293 #pragma unused(description)
1294 #pragma unused(info)
1295 if (argc < 1) {
1296 SCPrint(TRUE, stdout, CFSTR("NetBIOS name not specified\n"));
1297 return -1;
1298 }
1299
1300 if (strlen(argv[0]) > 0) {
1301 CFStringRef name;
1302 CFStringRef str;
1303
1304 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1305 name = __cleanupName(str);
1306 CFRelease(str);
1307
1308 if (name != NULL) {
1309 CFDictionarySetValue(newConfiguration, key, name);
1310 CFRelease(name);
1311 } else {
1312 SCPrint(TRUE, stdout, CFSTR("invalid NetBIOS name\n"));
1313 return -1;
1314 }
1315 } else {
1316 CFDictionaryRemoveValue(newConfiguration, key);
1317 }
1318
1319 return 1;
1320 }
1321
1322
1323 static int
1324 __doSMBWorkgroup(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1325 {
1326 #pragma unused(description)
1327 #pragma unused(info)
1328 if (argc < 1) {
1329 SCPrint(TRUE, stdout, CFSTR("Workgroup not specified\n"));
1330 return -1;
1331 }
1332
1333 if (strlen(argv[0]) > 0) {
1334 CFStringRef name;
1335 CFStringRef str;
1336
1337 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1338 name = __cleanupName(str);
1339 CFRelease(str);
1340
1341 if (name != NULL) {
1342 CFDictionarySetValue(newConfiguration, key, name);
1343 CFRelease(name);
1344 } else {
1345 SCPrint(TRUE, stdout, CFSTR("invalid Workgroup\n"));
1346 return -1;
1347 }
1348 } else {
1349 CFDictionaryRemoveValue(newConfiguration, key);
1350 }
1351
1352 return 1;
1353 }
1354
1355
1356 static int
1357 __doSMBWINSAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1358 {
1359 #pragma unused(description)
1360 #pragma unused(info)
1361 CFMutableArrayRef servers;
1362
1363 if (argc < 1) {
1364 SCPrint(TRUE, stdout, CFSTR("WINS address(es) not specified\n"));
1365 return -1;
1366 }
1367
1368 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1369
1370 if (strlen(argv[0]) > 0) {
1371 CFArrayRef array;
1372 CFIndex i;
1373 CFIndex n;
1374 CFStringRef str;
1375
1376 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1377 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
1378 CFRelease(str);
1379
1380 n = (array != NULL) ? CFArrayGetCount(array) : 0;
1381 for (i = 0; i < n; i++) {
1382 char str[32];
1383
1384 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
1385 str,
1386 sizeof(str),
1387 kCFStringEncodingUTF8) != NULL) {
1388 CFStringRef server;
1389
1390 server = __copyIPv4Address(str);
1391 //if (server == NULL) {
1392 // server = __copyIPv6Address(str);
1393 //}
1394 if (server != NULL) {
1395 CFArrayAppendValue(servers, server);
1396 CFRelease(server);
1397 continue;
1398 }
1399 }
1400
1401 SCPrint(TRUE, stdout, CFSTR("invalid WINS address\n"));
1402 CFRelease(array);
1403 CFRelease(servers);
1404 return -1;
1405 }
1406 if (array != NULL) CFRelease(array);
1407 }
1408
1409 if (CFArrayGetCount(servers) > 0) {
1410 CFDictionarySetValue(newConfiguration, key, servers);
1411 } else {
1412 CFDictionaryRemoveValue(newConfiguration, key);
1413 }
1414
1415 CFRelease(servers);
1416 return 1;
1417 }
1418
1419
1420 static selections smbNodeTypes[] = {
1421 { CFSTR("Broadcast"), &kSCValNetSMBNetBIOSNodeTypeBroadcast, 0 },
1422 { CFSTR("Peer") , &kSCValNetSMBNetBIOSNodeTypePeer , 0 },
1423 { CFSTR("Mixed") , &kSCValNetSMBNetBIOSNodeTypeMixed , 0 },
1424 { CFSTR("Hybrid") , &kSCValNetSMBNetBIOSNodeTypeHybrid , 0 },
1425 { NULL , NULL , 0 }
1426 };
1427
1428
1429 static options smbOptions[] = {
1430 { "NetBIOSName" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
1431 { "name" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
1432 { "NetBIOSNodeType", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
1433 { "type", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
1434 { "Workgroup" , "workgroup", isOther , &kSCPropNetSMBWorkgroup , __doSMBWorkgroup , NULL },
1435 { "WINSAddresses" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
1436 { "wins" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
1437
1438 { "?" , NULL , isHelp , NULL , NULL,
1439 "\nSMB configuration commands\n\n"
1440 " set protocol name NetBIOS-name\n"
1441 " set protocol type (Broadcast|Peer|Mixed|Hybrid)\n"
1442 " set protocol workgroup SMB-workgroup\n"
1443 " set protocol wins x1.x1.x1.x1[,x2.x2.x2.x2]\n"
1444 }
1445 };
1446 #define N_SMB_OPTIONS (sizeof(smbOptions) / sizeof(smbOptions[0]))
1447
1448
1449 static Boolean
1450 set_protocol_smb(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1451 {
1452 Boolean ok;
1453
1454 ok = _process_options(smbOptions, N_SMB_OPTIONS, argc, argv, newConfiguration);
1455 return ok;
1456 }
1457
1458
1459 #endif // !TARGET_OS_IPHONE
1460
1461
1462 #pragma mark -
1463 #pragma mark *Protocol*
1464
1465
1466 __private_extern__
1467 void
1468 set_protocol(int argc, char **argv)
1469 {
1470 CFDictionaryRef configuration;
1471 CFMutableDictionaryRef newConfiguration = NULL;
1472 Boolean ok = FALSE;
1473 CFStringRef protocolType;
1474
1475 if (net_protocol == NULL) {
1476 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1477 return;
1478 }
1479
1480 if (argc < 1) {
1481 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1482 return;
1483 }
1484
1485 configuration = SCNetworkProtocolGetConfiguration(net_protocol);
1486 if (configuration == NULL) {
1487 newConfiguration = CFDictionaryCreateMutable(NULL,
1488 0,
1489 &kCFTypeDictionaryKeyCallBacks,
1490 &kCFTypeDictionaryValueCallBacks);
1491 } else {
1492 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
1493 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
1494 }
1495
1496 protocolType = SCNetworkProtocolGetProtocolType(net_protocol);
1497 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
1498 ok = set_protocol_dns(argc, argv, newConfiguration);
1499 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1500 ok = set_protocol_ipv4(argc, argv, newConfiguration);
1501 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1502 ok = set_protocol_ipv6(argc, argv, newConfiguration);
1503 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
1504 ok = set_protocol_proxies(argc, argv, newConfiguration);
1505 #if !TARGET_OS_IPHONE
1506 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) {
1507 ok = set_protocol_smb(argc, argv, newConfiguration);
1508 #endif // !TARGET_OS_IPHONE
1509 } else {
1510 SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n"));
1511 }
1512
1513 if (!ok) {
1514 goto done;
1515 }
1516
1517 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
1518 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
1519 if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) {
1520 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1521 goto done;
1522 }
1523
1524 _prefs_changed = TRUE;
1525 }
1526
1527 done :
1528
1529 if (newConfiguration != NULL) CFRelease(newConfiguration);
1530 return;
1531 }
1532
1533
1534 /* -------------------- */
1535
1536
1537 __private_extern__
1538 void
1539 show_protocol(int argc, char **argv)
1540 {
1541 CFDictionaryRef configuration;
1542 SCNetworkProtocolRef protocol = NULL;
1543 CFStringRef protocolType;
1544
1545 if (argc > 0) {
1546 protocol = _find_protocol(argv[0]);
1547 } else {
1548 if (net_protocol != NULL) {
1549 protocol = net_protocol;
1550 } else {
1551 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1552 return;
1553 }
1554 }
1555
1556 if (protocol == NULL) {
1557 return;
1558 }
1559
1560 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1561 SCPrint(TRUE, stdout, CFSTR("protocol type = %@\n"), protocolType);
1562
1563 configuration = SCNetworkProtocolGetConfiguration(protocol);
1564 if (configuration != NULL) {
1565 SCPrint(TRUE, stdout, CFSTR("\n protocol configuration\n"));
1566 _show_entity(configuration, CFSTR(""));
1567 }
1568
1569 if (_sc_debug) {
1570 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol);
1571 }
1572
1573 return;
1574 }
1575
1576
1577 /* -------------------- */
1578
1579
1580 __private_extern__
1581 void
1582 show_protocols(int argc, char **argv)
1583 {
1584 #pragma unused(argc)
1585 #pragma unused(argv)
1586 CFIndex i;
1587 CFIndex n;
1588
1589 if (prefs == NULL) {
1590 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1591 return;
1592 }
1593
1594 if (net_service == NULL) {
1595 SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
1596 return;
1597 }
1598
1599 if (protocols != NULL) CFRelease(protocols);
1600 protocols = SCNetworkServiceCopyProtocols(net_service);
1601 if (protocols == NULL) {
1602 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1603 return;
1604 }
1605
1606 n = CFArrayGetCount(protocols);
1607 if (n > 1) {
1608 CFMutableArrayRef sorted;
1609
1610 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
1611 CFArraySortValues(sorted,
1612 CFRangeMake(0, n),
1613 _SCNetworkProtocolCompare,
1614 NULL);
1615 CFRelease(protocols);
1616 protocols = sorted;
1617 }
1618
1619 for (i = 0; i < n; i++) {
1620 SCNetworkProtocolRef protocol;
1621 CFStringRef protocolType;
1622
1623 protocol = CFArrayGetValueAtIndex(protocols, i);
1624 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1625
1626 SCPrint(TRUE, stdout, CFSTR("%c%2ld: %@%*s :"),
1627 ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ',
1628 i + 1,
1629 protocolType,
1630 (int)(sizeof("Proxies") - CFStringGetLength(protocolType) - 1),
1631 "");
1632
1633 if (SCNetworkProtocolGetEnabled(protocol)) {
1634 CFStringRef description;
1635
1636 description = _protocol_description(protocol, FALSE);
1637 SCPrint(TRUE, stdout, CFSTR(" %@"), description);
1638 CFRelease(description);
1639 } else {
1640 SCPrint(TRUE, stdout, CFSTR(" *DISABLED*"));
1641 }
1642 SCPrint(TRUE, stdout, CFSTR("\n"));
1643 }
1644
1645 return;
1646 }
1647
1648
1649 /* -------------------- */
1650
1651
1652 __private_extern__
1653 CF_RETURNS_RETAINED CFStringRef
1654 _protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
1655 {
1656 CFDictionaryRef configuration;
1657 CFMutableStringRef description = NULL;
1658 CFStringRef protocolType;
1659
1660 description = CFStringCreateMutable(NULL, 0);
1661
1662 if (!SCNetworkProtocolGetEnabled(protocol)) {
1663 goto done;
1664 }
1665
1666 configuration = SCNetworkProtocolGetConfiguration(protocol);
1667 if (configuration == NULL) {
1668 goto done;
1669 }
1670
1671 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1672 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
1673 CFStringRef domain;
1674 CFArrayRef search;
1675 CFArrayRef servers;
1676
1677 domain = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName);
1678 if (isA_CFString(domain)) {
1679 CFStringAppendFormat(description,
1680 NULL,
1681 CFSTR("domain=%@"),
1682 domain);
1683 }
1684
1685 search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains);
1686 if (isA_CFArray(search)) {
1687 CFStringRef str;
1688
1689 str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(","));
1690 CFStringAppendFormat(description,
1691 NULL,
1692 CFSTR("%ssearch=%@"),
1693 CFStringGetLength(description) > 0 ? ", " : "",
1694 str);
1695 CFRelease(str);
1696 }
1697
1698 servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses);
1699 if (isA_CFArray(servers)) {
1700 CFStringRef str;
1701
1702 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
1703 CFStringAppendFormat(description,
1704 NULL,
1705 CFSTR("%sservers=%@"),
1706 CFStringGetLength(description) > 0 ? ", " : "",
1707 str);
1708 CFRelease(str);
1709 }
1710 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1711 CFStringRef method;
1712
1713 method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod);
1714 if (isA_CFString(method)) {
1715 CFArrayRef addresses;
1716
1717 addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses);
1718 if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) &&
1719 isA_CFArray(addresses)) {
1720 CFStringAppendFormat(description,
1721 NULL,
1722 CFSTR("%@, address=%@"),
1723 method,
1724 CFArrayGetValueAtIndex(addresses, 0));
1725 } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) &&
1726 isA_CFArray(addresses)) {
1727 CFStringRef router;
1728
1729 CFStringAppendFormat(description,
1730 NULL,
1731 CFSTR("%@, address=%@"),
1732 method,
1733 CFArrayGetValueAtIndex(addresses, 0));
1734
1735 if (CFDictionaryGetValueIfPresent(configuration,
1736 kSCPropNetIPv4Router,
1737 (const void **)&router) &&
1738 isA_CFString(router)) {
1739 CFStringAppendFormat(description,
1740 NULL,
1741 CFSTR(", router=%@"),
1742 router);
1743 }
1744 } else {
1745 CFStringAppendFormat(description,
1746 NULL,
1747 CFSTR("%@"),
1748 method);
1749 }
1750 }
1751 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1752 CFStringRef method;
1753
1754 method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod);
1755 if (isA_CFString(method)) {
1756 CFStringAppendFormat(description,
1757 NULL,
1758 CFSTR("%@"),
1759 method);
1760 }
1761 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
1762 static proxyKeys *keys[] = { &proxyKeys_FTP, &proxyKeys_Gopher, &proxyKeys_HTTP, &proxyKeys_HTTPS,
1763 &proxyKeys_RTSP, &proxyKeys_SOCKS, &proxyKeys_PAC, &proxyKeys_WPAD };
1764
1765 for (size_t i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
1766 proxyKeys *currentProxy = keys[i];
1767
1768 if (!__proxy_enabled(configuration, currentProxy->keyEnable)) {
1769 continue;
1770 }
1771
1772 if (((currentProxy->keyProxy != NULL) &&
1773 !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) ||
1774 ((currentProxy->keyURL != NULL) &&
1775 !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) {
1776 continue;
1777 }
1778
1779 CFStringAppendFormat(description,
1780 NULL,
1781 CFSTR("%s%s"),
1782 CFStringGetLength(description) > 0 ? ", " : "",
1783 currentProxy->proxy);
1784 }
1785 #if !TARGET_OS_IPHONE
1786 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) {
1787 CFStringRef name;
1788 CFArrayRef servers;
1789 CFStringRef workgroup;
1790
1791 name = CFDictionaryGetValue(configuration, kSCPropNetSMBNetBIOSName);
1792 if (isA_CFString(name)) {
1793 CFStringAppendFormat(description,
1794 NULL,
1795 CFSTR("NetBIOS name=%@"),
1796 name);
1797 }
1798
1799 workgroup = CFDictionaryGetValue(configuration, kSCPropNetSMBWorkgroup);
1800 if (isA_CFString(workgroup)) {
1801 CFStringAppendFormat(description,
1802 NULL,
1803 CFSTR("Workgroup=%@"),
1804 workgroup);
1805 }
1806
1807 servers = CFDictionaryGetValue(configuration, kSCPropNetSMBWINSAddresses);
1808 if (isA_CFArray(servers)) {
1809 CFStringRef str;
1810
1811 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
1812 CFStringAppendFormat(description,
1813 NULL,
1814 CFSTR("%sWINS servers=%@"),
1815 CFStringGetLength(description) > 0 ? ", " : "",
1816 str);
1817 CFRelease(str);
1818 }
1819 #endif // !TARGET_OS_IPHONE
1820 }
1821
1822 done :
1823
1824 if (skipEmpty && CFStringGetLength(description) == 0) {
1825 CFRelease(description);
1826 description = NULL;
1827 }
1828
1829 return description;
1830 }