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