]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/net_protocol.c
configd-130.tar.gz
[apple/configd.git] / scutil.tproj / net_protocol.c
1 /*
2 * Copyright (c) 2004 Apple Computer, 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
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__
48 CFComparisonResult
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
63 static 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
81 static 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) {
97 sin6.sin6_scope_id = if_nametoindex(p+1);
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
108 static 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__
195 void
196 create_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
240 net_changed = TRUE;
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__
271 void
272 disable_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
296 net_changed = TRUE;
297
298 return;
299 }
300
301
302 /* -------------------- */
303
304
305 __private_extern__
306 void
307 enable_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
331 net_changed = TRUE;
332
333 return;
334 }
335
336
337 /* -------------------- */
338
339
340 __private_extern__
341 void
342 remove_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
370 net_changed = TRUE;
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__
398 void
399 select_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
420 /* -------------------- */
421
422
423 static selections appletalkConfigMethods[] = {
424 { CFSTR("node") , &kSCValNetAppleTalkConfigMethodNode , 0 },
425 { CFSTR("router") , &kSCValNetAppleTalkConfigMethodRouter , 0 },
426 { CFSTR("seedrouter"), &kSCValNetAppleTalkConfigMethodSeedRouter, 0 },
427 { NULL , NULL , 0 }
428 };
429
430
431 static int
432 __doAppleTalkConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
433 {
434 CFStringRef configMethod;
435
436 configMethod = CFDictionaryGetValue(newConfiguration, key);
437 if (!CFEqual(key, kSCValNetAppleTalkConfigMethodSeedRouter)) {
438 CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedZones);
439 CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedNetworkRange);
440 }
441
442 return 0;
443 }
444
445
446 static int
447 __doAppleTalkNetworkRange(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
448 {
449 if (argc < 1) {
450 SCPrint(TRUE, stdout, CFSTR("network range not specified\n"));
451 return -1;
452 }
453
454 if (strlen(argv[0]) > 0) {
455 CFArrayRef array;
456 char *cp;
457 CFNumberRef range[2];
458
459 range[0] = _copy_number(argv[0]);
460 if (range[0] == NULL) {
461 SCPrint(TRUE, stdout, CFSTR("invalid start of range\n"));
462 return -1;
463 }
464
465 cp = strchr(argv[0], '-');
466 if (cp == NULL) {
467 range[1] = _copy_number(cp);
468 if (range[1] == NULL) {
469 CFRelease(range[0]);
470 SCPrint(TRUE, stdout, CFSTR("invalid end of range\n"));
471 return -1;
472 }
473 } else {
474 range[1] = CFRetain(range[0]);
475 }
476
477 array = CFArrayCreate(NULL,
478 (const void **)range,
479 sizeof(range)/sizeof(range[0]),
480 &kCFTypeArrayCallBacks);
481 CFRelease(range[0]);
482 CFRelease(range[1]);
483
484 CFDictionarySetValue(newConfiguration, key, array);
485 CFRelease(array);
486 } else {
487 CFDictionaryRemoveValue(newConfiguration, key);
488 }
489
490 return 1;
491 }
492
493
494 static options appletalkOptions[] = {
495 { "ConfigMethod" , "configuration method"
496 , isChooseOne , &kSCPropNetAppleTalkConfigMethod , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
497 { "config" , "configuration method"
498 , isChooseOne , &kSCPropNetAppleTalkConfigMethod , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
499 { "DefaultZone" , "zone" , isString , &kSCPropNetAppleTalkDefaultZone , NULL , NULL },
500 { "NodeID" , "node" , isNumber , &kSCPropNetAppleTalkNodeID , NULL , NULL },
501 { "NetworkID" , "network", isNumber , &kSCPropNetAppleTalkNetworkID , NULL , NULL },
502 { "SeedNetworkRange", "range" , isOther , &kSCPropNetAppleTalkSeedNetworkRange, __doAppleTalkNetworkRange, NULL },
503 { "SeedZones" , "zone" , isStringArray, &kSCPropNetAppleTalkSeedZones , NULL , NULL },
504
505 { "?" , NULL , isHelp , NULL , NULL ,
506 "\nAppleTalk configuration commands\n\n"
507 " set protocol config {Node|Router|SeedRouter}\n"
508 " set protocol defaultzone zone\n"
509 " set protocol node id\n"
510 " set protocol network id\n"
511 "\n w/config=Node\n"
512 " None\n"
513 "\n w/config=Router\n"
514 " None\n"
515 "\n w/config=SeedRouter\n"
516 " set protocol seednetworkrange low[-high]\n"
517 " set protocol seedzones zone[,zone-2]\n"
518 }
519 };
520 #define N_APPLETALK_OPTIONS (sizeof(appletalkOptions) / sizeof(appletalkOptions[0]))
521
522
523 static Boolean
524 set_protocol_appletalk(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
525 {
526 Boolean ok;
527
528 ok = _process_options(appletalkOptions, N_APPLETALK_OPTIONS, argc, argv, newConfiguration);
529 return ok;
530 }
531
532
533 /* -------------------- */
534
535
536 static CFStringRef
537 __cleanupDomainName(CFStringRef domain)
538 {
539 CFMutableStringRef newDomain;
540
541 newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
542 CFStringTrimWhitespace(newDomain);
543 CFStringTrim(newDomain, CFSTR("."));
544 if (CFStringGetLength(newDomain) == 0) {
545 CFRelease(newDomain);
546 newDomain = NULL;
547 }
548
549 return newDomain;
550 }
551
552
553 static int
554 __doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
555 {
556 if (argc < 1) {
557 SCPrint(TRUE, stdout, CFSTR("DNS domain name not specified\n"));
558 return -1;
559 }
560
561 if (strlen(argv[0]) > 0) {
562 CFStringRef domain;
563 CFStringRef str;
564
565 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
566 domain = __cleanupDomainName(str);
567 CFRelease(str);
568
569 if (domain != NULL) {
570 CFDictionarySetValue(newConfiguration, key, domain);
571 CFRelease(domain);
572 } else {
573 SCPrint(TRUE, stdout, CFSTR("invalid DNS domain name\n"));
574 return -1;
575 }
576 } else {
577 CFDictionaryRemoveValue(newConfiguration, key);
578 }
579
580 return 1;
581 }
582
583
584 static int
585 __doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
586 {
587 CFMutableArrayRef domains;
588
589 if (argc < 1) {
590 SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
591 return -1;
592 }
593
594 domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
595
596 if (strlen(argv[0]) > 0) {
597 CFArrayRef array;
598 CFStringRef str;
599
600 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
601 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
602 CFRelease(str);
603
604 if (array != NULL) {
605 CFIndex i;
606 CFIndex n = CFArrayGetCount(array);
607
608 for (i = 0; i < n; i++) {
609 CFStringRef domain;
610
611 domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
612 if (domain != NULL) {
613 CFArrayAppendValue(domains, domain);
614 CFRelease(domain);
615 } else {
616 CFRelease(array);
617 CFRelease(domains);
618 SCPrint(TRUE, stdout, CFSTR("invalid DNS search domain name\n"));
619 return -1;
620 }
621 }
622 CFRelease(array);
623 }
624 }
625
626 if (CFArrayGetCount(domains) > 0) {
627 CFDictionarySetValue(newConfiguration, key, domains);
628 } else {
629 CFDictionaryRemoveValue(newConfiguration, key);
630 }
631
632 CFRelease(domains);
633 return 1;
634 }
635
636
637 static int
638 __doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
639 {
640 CFMutableArrayRef servers;
641
642 if (argc < 1) {
643 SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
644 return -1;
645 }
646
647 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
648
649 if (strlen(argv[0]) > 0) {
650 CFArrayRef array;
651 CFIndex i;
652 CFIndex n;
653 CFStringRef str;
654
655 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
656 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
657 CFRelease(str);
658
659 n = (array != NULL) ? CFArrayGetCount(array) : 0;
660 for (i = 0; i < n; i++) {
661 char str[32];
662
663 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
664 str,
665 sizeof(str),
666 kCFStringEncodingUTF8) != NULL) {
667 CFStringRef server;
668
669 server = __copyIPv4Address(str);
670 if (server == NULL) {
671 server = __copyIPv6Address(str);
672 }
673 if (server != NULL) {
674 CFArrayAppendValue(servers, server);
675 CFRelease(server);
676 continue;
677 }
678 }
679
680 SCPrint(TRUE, stdout, CFSTR("invalid DNS name server address\n"));
681 CFRelease(array);
682 CFRelease(servers);
683 return -1;
684 }
685 if (array != NULL) CFRelease(array);
686 }
687
688 if (CFArrayGetCount(servers) > 0) {
689 CFDictionarySetValue(newConfiguration, key, servers);
690 } else {
691 CFDictionaryRemoveValue(newConfiguration, key);
692 }
693
694 CFRelease(servers);
695 return 1;
696 }
697
698
699 static options dnsOptions[] = {
700 { "DomainName" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
701 { "domain" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
702 { "SearchDomains" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
703 { "search" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
704 { "ServerAddresses", "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
705 { "nameserver" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
706 { "nameservers" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
707
708 { "?" , NULL , isHelp , NULL , NULL,
709 "\nDNS configuration commands\n\n"
710 " set protocol search domain-name[,domain-name-2]\n"
711 " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]"
712 }
713 };
714 #define N_DNS_OPTIONS (sizeof(dnsOptions) / sizeof(dnsOptions[0]))
715
716
717 static Boolean
718 set_protocol_dns(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
719 {
720 Boolean ok;
721
722 ok = _process_options(dnsOptions, N_DNS_OPTIONS, argc, argv, newConfiguration);
723 return ok;
724 }
725
726
727 /* -------------------- */
728
729
730 #define allowIPv4Address 1<<1 // allow address
731 #define allowIPv4Netmask 1<<2 // allow subnet mask
732 #define allowIPv4Router 1<<3 // allow router
733 #define allowIPv4DHCPClientID 1<<4 // allow DCHP Client ID
734
735 static selections ipv4ConfigMethods[] = {
736 { CFSTR("BOOTP") , &kSCValNetIPv4ConfigMethodBOOTP , 0 },
737 { CFSTR("DHCP") , &kSCValNetIPv4ConfigMethodDHCP , allowIPv4DHCPClientID },
738 { CFSTR("INFORM") , &kSCValNetIPv4ConfigMethodINFORM , allowIPv4Address },
739 { CFSTR("LinkLocal"), &kSCValNetIPv4ConfigMethodLinkLocal, 0 },
740 { CFSTR("Manual") , &kSCValNetIPv4ConfigMethodManual , allowIPv4Address|allowIPv4Netmask|allowIPv4Router },
741 { CFSTR("PPP") , &kSCValNetIPv4ConfigMethodPPP , allowIPv4Address|selectionNotAvailable },
742 { NULL , NULL , 0 }
743 };
744
745
746 static int
747 __doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
748 {
749 unsigned int flags;
750 CFStringRef method;
751 CFIndex methodIndex;
752
753 method = CFDictionaryGetValue(newConfiguration, key);
754 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
755 if (methodIndex != kCFNotFound) {
756 if (!(flags & allowIPv4Address)) {
757 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Addresses);
758 }
759 if (!(flags & allowIPv4Netmask)) {
760 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4SubnetMasks);
761 }
762 if (!(flags & allowIPv4Router)) {
763 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Router);
764 }
765 if (!(flags & allowIPv4DHCPClientID)) {
766 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4DHCPClientID);
767 }
768 } else {
769 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
770 return -1;
771 }
772
773 return 0;
774 }
775
776
777 static int
778 __doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
779 {
780 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
781
782 if (strlen(argv[0]) > 0) {
783 CFStringRef address;
784
785 address = __copyIPv4Address(argv[0]);
786 if (address != NULL) {
787 if (useArray) {
788 CFArrayRef addresses;
789
790 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
791 CFDictionarySetValue(newConfiguration, key, addresses);
792 CFRelease(addresses);
793 } else {
794 CFDictionarySetValue(newConfiguration, key, address);
795 }
796 CFRelease(address);
797 } else {
798 return -1;
799 }
800 } else {
801 CFDictionaryRemoveValue(newConfiguration, key);
802 }
803
804 return 1;
805 }
806
807
808 static options ipv4Options[] = {
809 { "ConfigMethod", "configuration method"
810 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
811 { "config" , "configuration method"
812 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
813 { "Addresses" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
814 { "address" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
815 { "SubnetMasks" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
816 { "netmask" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
817 { "Router" , "address" , isOther , &kSCPropNetIPv4Router , __doIPv4Addresses , (void *)FALSE },
818 { "DHCPClientID", "client ID", isString , &kSCPropNetIPv4DHCPClientID, NULL , NULL },
819
820 { "?" , NULL , isHelp , NULL , NULL ,
821 "\nIPv4 configuration commands\n\n"
822 " set protocol config {BOOTP|DHCP|INFORM|MANUAL}\n"
823 "\n w/config=BOOTP\n"
824 " None\n"
825 "\n w/config=DHCP\n"
826 " set protocol dhcpclientid identifier\n"
827 "\n w/config=INFORM\n"
828 " set protocol address x.x.x.x\n"
829 "\n w/config=MANUAL\n"
830 " set protocol address x.x.x.x\n"
831 " set protocol netmask x.x.x.x\n"
832 " set protocol router x.x.x.x\n"
833 }
834 };
835 #define N_IPV4_OPTIONS (sizeof(ipv4Options) / sizeof(ipv4Options[0]))
836
837
838 static Boolean
839 set_protocol_ipv4(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
840 {
841 Boolean ok;
842
843 ok = _process_options(ipv4Options, N_IPV4_OPTIONS, argc, argv, newConfiguration);
844 if (ok) {
845 unsigned int flags;
846 CFStringRef method;
847 CFIndex methodIndex;
848
849 // validate configuration
850 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv4ConfigMethod);
851 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
852 if (methodIndex == kCFNotFound) {
853 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
854 return FALSE;
855 }
856
857 if (!(flags & allowIPv4Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Addresses)) {
858 SCPrint(TRUE, stdout,
859 CFSTR("IP address not allowed with %@ configuration\n"),
860 ipv4ConfigMethods[methodIndex].selection);
861 return FALSE;
862 }
863
864 if (!(flags & allowIPv4Netmask) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4SubnetMasks)) {
865 SCPrint(TRUE, stdout,
866 CFSTR("Subnet mask not allowed with %@ configuration\n"),
867 ipv4ConfigMethods[methodIndex].selection);
868 return FALSE;
869 }
870
871 if (!(flags & allowIPv4Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Router)) {
872 SCPrint(TRUE, stdout,
873 CFSTR("Default route not allowed with %@ configuration\n"),
874 ipv4ConfigMethods[methodIndex].selection);
875 return FALSE;
876 }
877
878 if (!(flags & allowIPv4DHCPClientID) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4DHCPClientID)) {
879 SCPrint(TRUE, stdout,
880 CFSTR("DHCP client ID not allowed with %@ configuration\n"),
881 ipv4ConfigMethods[methodIndex].selection);
882 return FALSE;
883 }
884 }
885
886 return ok;
887 }
888
889
890 /* -------------------- */
891
892
893 #define allowIPv6Address 1<<1 // allow address
894 #define allowIPv6PrefixLength 1<<2 // allow prefix length
895 #define allowIPv6Router 1<<3 // allow router
896
897 static selections ipv6ConfigMethods[] = {
898 { CFSTR("Automatic") , & kSCValNetIPv6ConfigMethodAutomatic , 0 },
899 { CFSTR("Manual") , & kSCValNetIPv6ConfigMethodManual , allowIPv6Address|allowIPv6PrefixLength|allowIPv6Router },
900 { CFSTR("RouterAdvertisement"), & kSCValNetIPv6ConfigMethodRouterAdvertisement, allowIPv6Address },
901 { CFSTR("6to4") , & kSCValNetIPv6ConfigMethod6to4 , 0 },
902 { NULL , NULL , 0 }
903 };
904
905
906 static int
907 __doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
908 {
909 unsigned int flags;
910 CFStringRef method;
911 CFIndex methodIndex;
912
913 method = CFDictionaryGetValue(newConfiguration, key);
914 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
915 if (methodIndex != kCFNotFound) {
916 if (!(flags & allowIPv6Address)) {
917 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Addresses);
918 }
919 if (!(flags & allowIPv6PrefixLength)) {
920 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6PrefixLength);
921 }
922 if (!(flags & allowIPv6Router)) {
923 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Router);
924 }
925 } else {
926 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
927 return -1;
928 }
929
930 return 0;
931 }
932
933
934 static int
935 __doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
936 {
937 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
938
939 if (strlen(argv[0]) > 0) {
940 CFStringRef address;
941
942 address = __copyIPv6Address(argv[0]);
943 if (address != NULL) {
944 if (useArray) {
945 CFArrayRef addresses;
946
947 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
948 CFDictionarySetValue(newConfiguration, key, addresses);
949 CFRelease(addresses);
950 } else {
951 CFDictionarySetValue(newConfiguration, key, address);
952 }
953 CFRelease(address);
954 } else {
955 return -1;
956 }
957 } else {
958 CFDictionaryRemoveValue(newConfiguration, key);
959 }
960
961 return 1;
962 }
963
964
965 static int
966 __doIPv6PrefixLength(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
967 {
968 CFNumberRef num;
969 int prefixLength;
970
971 num = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
972 if (isA_CFNumber(num) &&
973 CFNumberGetValue(num, kCFNumberIntType, &prefixLength) &&
974 (prefixLength >= 0) && (prefixLength <= (sizeof(struct in6_addr) * 8))) {
975 return 0;
976 }
977
978 return -1;
979 }
980
981
982 static options ipv6Options[] = {
983 { "ConfigMethod", "configuration method"
984 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
985 { "config" , "configuration method"
986 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
987 { "Addresses" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
988 { "address" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
989 { "PrefixLength", "prefix length", isNumber , &kSCPropNetIPv6PrefixLength, __doIPv6PrefixLength, NULL },
990 { "Router" , "address" , isOther , &kSCPropNetIPv6Router , __doIPv6Addresses , (void *)FALSE },
991
992 { "?" , NULL , isHelp , NULL , NULL ,
993 "\nIPv6 configuration commands\n\n"
994 " set protocol config {Automatic|MANUAL}\n"
995 "\n w/config=Automatic\n"
996 " None\n"
997 "\n w/config=MANUAL\n"
998 " set protocol address x:x:x:x:x:x\n"
999 " set protocol router x:x:x:x:x:x\n"
1000 " set protocol prefixlength n\n"
1001 }
1002 };
1003 #define N_IPV6_OPTIONS (sizeof(ipv6Options) / sizeof(ipv6Options[0]))
1004
1005
1006 static Boolean
1007 set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1008 {
1009 Boolean ok;
1010
1011 ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration);
1012 if (ok) {
1013 unsigned int flags;
1014 CFStringRef method;
1015 CFIndex methodIndex;
1016
1017 // validate configuration
1018 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod);
1019 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
1020 if (methodIndex == kCFNotFound) {
1021 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
1022 return FALSE;
1023 }
1024
1025 if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) {
1026 SCPrint(TRUE, stdout,
1027 CFSTR("IP address not allowed with %@ configuration\n"),
1028 ipv6ConfigMethods[methodIndex].selection);
1029 return FALSE;
1030 }
1031
1032 if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) {
1033 SCPrint(TRUE, stdout,
1034 CFSTR("Prefix length not allowed with %@ configuration\n"),
1035 ipv6ConfigMethods[methodIndex].selection);
1036 return FALSE;
1037 }
1038
1039 if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) {
1040 SCPrint(TRUE, stdout,
1041 CFSTR("Router not allowed with %@ configuration\n"),
1042 ipv6ConfigMethods[methodIndex].selection);
1043 return FALSE;
1044 }
1045 }
1046
1047 return ok;
1048 }
1049
1050
1051 /* -------------------- */
1052
1053
1054 typedef const struct {
1055 const char *proxy;
1056 const CFStringRef *keyEnable;
1057 const CFStringRef *keyProxy;
1058 const CFStringRef *keyPort;
1059 const CFStringRef *keyURL;
1060 } proxyKeys;
1061
1062 static proxyKeys proxyKeys_FTP = { "FTP" , &kSCPropNetProxiesFTPEnable , &kSCPropNetProxiesFTPProxy , &kSCPropNetProxiesFTPPort , NULL };
1063 static proxyKeys proxyKeys_Gopher = { "Gopher", &kSCPropNetProxiesGopherEnable , &kSCPropNetProxiesGopherProxy, &kSCPropNetProxiesGopherPort, NULL };
1064 static proxyKeys proxyKeys_HTTP = { "HTTP" , &kSCPropNetProxiesHTTPEnable , &kSCPropNetProxiesHTTPProxy , &kSCPropNetProxiesHTTPPort , NULL };
1065 static proxyKeys proxyKeys_HTTPS = { "HTTPS" , &kSCPropNetProxiesHTTPSEnable , &kSCPropNetProxiesHTTPSProxy , &kSCPropNetProxiesHTTPSPort , NULL };
1066 static proxyKeys proxyKeys_RTSP = { "RTSP" , &kSCPropNetProxiesRTSPEnable , &kSCPropNetProxiesRTSPProxy , &kSCPropNetProxiesRTSPPort , NULL };
1067 static proxyKeys proxyKeys_SOCKS = { "SOCKS" , &kSCPropNetProxiesSOCKSEnable , &kSCPropNetProxiesSOCKSProxy , &kSCPropNetProxiesSOCKSPort , NULL };
1068 static proxyKeys proxyKeys_PAC = { ".pac" , &kSCPropNetProxiesProxyAutoConfigEnable , NULL , NULL , &kSCPropNetProxiesProxyAutoConfigURLString };
1069 static proxyKeys proxyKeys_WPAD = { "WPAD" , &kSCPropNetProxiesProxyAutoDiscoveryEnable, NULL , NULL , NULL };
1070
1071 static proxyKeys *currentProxy = NULL;
1072
1073
1074 static int __doProxySelect (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1075 static int __doProxyEnable (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1076 static int __doProxyHost (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1077 static int __doProxyPort (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1078 static int __doProxyURL (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1079 static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
1080
1081
1082 static options proxyOptions[] = {
1083 // general options
1084 { "ExceptionsList" , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList , NULL , NULL },
1085 { "ExcludeSimpleHostnames", NULL , isBoolean , &kSCPropNetProxiesExcludeSimpleHostnames, NULL , NULL },
1086 // proxy selection
1087 { "FTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_FTP },
1088 { "Gopher" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_Gopher },
1089 { "HTTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTP },
1090 { "HTTPS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTPS },
1091 { "RTSP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_RTSP },
1092 { "SOCKS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_SOCKS },
1093 { "ProxyAutoConfig" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
1094 { ".pac" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
1095 { "ProxyAutoDiscovery" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
1096 { "WPAD" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
1097 // proxy modifiers
1098 { "disable" , NULL , isOther , NULL , __doProxyEnable , (void *)FALSE },
1099 { "enable" , NULL , isOther , NULL , __doProxyEnable , (void *)TRUE },
1100 { "proxy" , NULL , isOther , NULL , __doProxyHost , NULL },
1101 { "host" , NULL , isOther , NULL , __doProxyHost , NULL },
1102 { "port" , NULL , isOther , NULL , __doProxyPort , NULL },
1103 { "url" , NULL , isOther , NULL , __doProxyURL , NULL },
1104 // (ftp) proxy modifiers
1105 { "FTPPassive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
1106 { "passive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
1107 // help
1108 { "?" , NULL , isHelp , NULL , NULL ,
1109 "\nProxy configuration commands\n\n"
1110 " set protocol ExceptionsList exception[,exception-2]\n"
1111 " set protocol ExcludeSimpleHostnames {enable|disable}\n"
1112 "\n"
1113 " set protocol ftp {enable|disable}\n"
1114 " set protocol ftp host proxy-host\n"
1115 " set protocol ftp port proxy-port\n"
1116 " set protocol ftp passive {enable|disable}\n"
1117 "\n"
1118 " set protocol http {enable|disable}\n"
1119 " set protocol http host proxy-host\n"
1120 " set protocol http port proxy-port\n"
1121 "\n"
1122 " set protocol https {enable|disable}\n"
1123 " set protocol https host proxy-host\n"
1124 " set protocol https port proxy-port\n"
1125 "\n"
1126 " set protocol rtsp {enable|disable}\n"
1127 " set protocol rtsp host proxy-host\n"
1128 " set protocol rtsp port proxy-port\n"
1129 "\n"
1130 " set protocol socks {enable|disable}\n"
1131 " set protocol socks host proxy-host\n"
1132 " set protocol socks port proxy-port\n"
1133 "\n"
1134 " set protocol .pac {enable|disable}\n"
1135 " set protocol .pac url .pac-url\n"
1136 "\n"
1137 " set protocol wpad {enable|disable}\n"
1138 }
1139 };
1140 #define N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0]))
1141
1142
1143 static int
1144 __doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1145 {
1146 CFIndex nextOption;
1147
1148 if (argc < 1) {
1149 SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n"));
1150 return -1;
1151 }
1152
1153 currentProxy = (proxyKeys *)info;
1154
1155 nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS);
1156 if ((nextOption == kCFNotFound) ||
1157 (proxyOptions[nextOption].handler == __doProxySelect)) {
1158 SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy);
1159 return -1;
1160 }
1161
1162 return 0;
1163 }
1164
1165
1166 static int
1167 __doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1168 {
1169 Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE;
1170
1171 if (currentProxy == NULL) {
1172 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1173 return -1;
1174 }
1175
1176 if (currentProxy->keyEnable == NULL) {
1177 SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"),
1178 currentProxy->proxy,
1179 enabled ? "enabled" : "disabled");
1180 return -1;
1181 }
1182
1183
1184 if (enabled) {
1185 CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1);
1186 } else {
1187 CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_0);
1188
1189 if (currentProxy->keyProxy != NULL) {
1190 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1191 }
1192
1193 if (currentProxy->keyPort != NULL) {
1194 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1195 }
1196
1197 if (currentProxy->keyURL != NULL) {
1198 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1199 }
1200 }
1201
1202 return 0;
1203 }
1204
1205
1206 static Boolean
1207 __proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey)
1208 {
1209 CFNumberRef num;
1210 int val;
1211
1212 if (enableKey == NULL) {
1213 return TRUE; // if proxy does not need to be enabled
1214 }
1215
1216 num = CFDictionaryGetValue(configuration, *enableKey);
1217 if (!isA_CFNumber(num) ||
1218 !CFNumberGetValue(num, kCFNumberIntType, &val) ||
1219 (val == 0)) {
1220 return FALSE; // if not enabled
1221 }
1222
1223 return TRUE;
1224 }
1225
1226
1227 static int
1228 __doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1229 {
1230 if (currentProxy == NULL) {
1231 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1232 return -1;
1233 }
1234
1235 if (currentProxy->keyProxy == NULL) {
1236 SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy);
1237 return -1;
1238 }
1239
1240 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1241 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1242 return -1;
1243 }
1244
1245 if (argc < 1) {
1246 SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy);
1247 return -1;
1248 }
1249
1250 if (strlen(argv[0]) > 0) {
1251 CFStringRef host;
1252
1253 host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1254 CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host);
1255 CFRelease(host);
1256 } else {
1257 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
1258 }
1259
1260 return 1;
1261 }
1262
1263
1264 static int
1265 __doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1266 {
1267 if (currentProxy == NULL) {
1268 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1269 return -1;
1270 }
1271
1272 if (currentProxy->keyPort == NULL) {
1273 SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy);
1274 return -1;
1275 }
1276
1277 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1278 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1279 return -1;
1280 }
1281
1282 if (argc < 1) {
1283 SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy);
1284 return -1;
1285 }
1286
1287 if (strlen(argv[0]) > 0) {
1288 CFNumberRef num;
1289 int port;
1290
1291 num = _copy_number(argv[0]);
1292 if (!isA_CFNumber(num) ||
1293 !CFNumberGetValue(num, kCFNumberIntType, &port) ||
1294 (port < 0) || (port > 65535)) {
1295 SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
1296 return -1;
1297 }
1298
1299 CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num);
1300 CFRelease(num);
1301 } else {
1302 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
1303 }
1304
1305 return 1;
1306 }
1307
1308
1309 static int
1310 __doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1311 {
1312 if (currentProxy == NULL) {
1313 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1314 return -1;
1315 }
1316
1317 if (currentProxy->keyURL == NULL) {
1318 SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy);
1319 return -1;
1320 }
1321
1322 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
1323 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
1324 return -1;
1325 }
1326
1327 if (argc < 1) {
1328 SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy);
1329 return -1;
1330 }
1331
1332 if (strlen(argv[0]) > 0) {
1333 CFStringRef url;
1334
1335 url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1336 CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url);
1337 CFRelease(url);
1338 } else {
1339 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
1340 }
1341
1342 return 1;
1343 }
1344
1345
1346 static int
1347 __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1348 {
1349 if (currentProxy == NULL) {
1350 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
1351 return -1;
1352 }
1353
1354 if (currentProxy != &proxyKeys_FTP) {
1355 SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n"));
1356 return -1;
1357 }
1358
1359 return 0;
1360 }
1361
1362
1363 static Boolean
1364 set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1365 {
1366 Boolean ok;
1367
1368 ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration);
1369 return ok;
1370 }
1371
1372
1373 /* -------------------- */
1374
1375
1376 __private_extern__
1377 void
1378 set_protocol(int argc, char **argv)
1379 {
1380 CFDictionaryRef configuration;
1381 CFMutableDictionaryRef newConfiguration = NULL;
1382 Boolean ok = FALSE;
1383 CFStringRef protocolType;
1384
1385 if (net_protocol == NULL) {
1386 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1387 return;
1388 }
1389
1390 if (argc < 1) {
1391 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1392 return;
1393 }
1394
1395 configuration = SCNetworkProtocolGetConfiguration(net_protocol);
1396 if (configuration == NULL) {
1397 newConfiguration = CFDictionaryCreateMutable(NULL,
1398 0,
1399 &kCFTypeDictionaryKeyCallBacks,
1400 &kCFTypeDictionaryValueCallBacks);
1401 } else {
1402 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
1403 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
1404 }
1405
1406 protocolType = SCNetworkProtocolGetProtocolType(net_protocol);
1407 if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
1408 ok = set_protocol_appletalk(argc, argv, newConfiguration);
1409 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
1410 ok = set_protocol_dns(argc, argv, newConfiguration);
1411 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1412 ok = set_protocol_ipv4(argc, argv, newConfiguration);
1413 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1414 ok = set_protocol_ipv6(argc, argv, newConfiguration);
1415 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
1416 ok = set_protocol_proxies(argc, argv, newConfiguration);
1417 } else {
1418 SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n"));
1419 }
1420
1421 if (!ok) {
1422 goto done;
1423 }
1424
1425 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
1426 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
1427 if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) {
1428 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1429 goto done;
1430 }
1431
1432 net_changed = TRUE;
1433 }
1434
1435 done :
1436
1437 if (newConfiguration != NULL) CFRelease(newConfiguration);
1438 return;
1439 }
1440
1441
1442 /* -------------------- */
1443
1444
1445 __private_extern__
1446 void
1447 show_protocol(int argc, char **argv)
1448 {
1449 CFDictionaryRef configuration;
1450 SCNetworkProtocolRef protocol = NULL;
1451 CFStringRef protocolType;
1452
1453 if (argc > 0) {
1454 protocol = _find_protocol(argv[0]);
1455 } else {
1456 if (net_protocol != NULL) {
1457 protocol = net_protocol;
1458 } else {
1459 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
1460 return;
1461 }
1462 }
1463
1464 if (protocol == NULL) {
1465 return;
1466 }
1467
1468 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1469 SCPrint(TRUE, stdout, CFSTR("protocol type = %@\n"), protocolType);
1470
1471 configuration = SCNetworkProtocolGetConfiguration(protocol);
1472 if (configuration != NULL) {
1473 SCPrint(TRUE, stdout, CFSTR("\n protocol configuration\n"));
1474 _show_entity(configuration, CFSTR(""));
1475 }
1476
1477 if (_sc_debug) {
1478 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol);
1479 }
1480
1481 return;
1482 }
1483
1484
1485 /* -------------------- */
1486
1487
1488 __private_extern__
1489 void
1490 show_protocols(int argc, char **argv)
1491 {
1492 CFIndex i;
1493 CFIndex n;
1494
1495 if (prefs == NULL) {
1496 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1497 return;
1498 }
1499
1500 if (net_service == NULL) {
1501 SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
1502 return;
1503 }
1504
1505 if (protocols != NULL) CFRelease(protocols);
1506 protocols = SCNetworkServiceCopyProtocols(net_service);
1507 if (protocols == NULL) {
1508 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1509 return;
1510 }
1511
1512 n = CFArrayGetCount(protocols);
1513 if (n > 1) {
1514 CFMutableArrayRef sorted;
1515
1516 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
1517 CFArraySortValues(sorted,
1518 CFRangeMake(0, n),
1519 _compare_protocols,
1520 NULL);
1521 CFRelease(protocols);
1522 protocols = sorted;
1523 }
1524
1525 for (i = 0; i < n; i++) {
1526 SCNetworkProtocolRef protocol;
1527 CFStringRef protocolType;
1528
1529 protocol = CFArrayGetValueAtIndex(protocols, i);
1530 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1531
1532 SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%*s :"),
1533 ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ',
1534 i + 1,
1535 protocolType,
1536 sizeof("AppleTalk") - CFStringGetLength(protocolType) - 1,
1537 "");
1538
1539 if (SCNetworkProtocolGetEnabled(protocol)) {
1540 CFStringRef description;
1541
1542 description = _protocol_description(protocol, FALSE);
1543 SCPrint(TRUE, stdout, CFSTR(" %@"), description);
1544 CFRelease(description);
1545 } else {
1546 SCPrint(TRUE, stdout, CFSTR(" *DISABLED*"));
1547 }
1548 SCPrint(TRUE, stdout, CFSTR("\n"));
1549 }
1550
1551 return;
1552 }
1553
1554
1555 /* -------------------- */
1556
1557
1558 __private_extern__
1559 CFStringRef
1560 _protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
1561 {
1562 CFDictionaryRef configuration;
1563 CFMutableStringRef description = NULL;
1564 CFStringRef protocolType;
1565
1566 description = CFStringCreateMutable(NULL, 0);
1567
1568 if (!SCNetworkProtocolGetEnabled(protocol)) {
1569 goto done;
1570 }
1571
1572 configuration = SCNetworkProtocolGetConfiguration(protocol);
1573 if (configuration == NULL) {
1574 goto done;
1575 }
1576
1577 protocolType = SCNetworkProtocolGetProtocolType(protocol);
1578 if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
1579 CFStringRef method;
1580
1581 method = CFDictionaryGetValue(configuration, kSCPropNetAppleTalkConfigMethod);
1582 if (isA_CFString(method)) {
1583 CFStringAppendFormat(description,
1584 NULL,
1585 CFSTR("%@"),
1586 method);
1587 }
1588 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
1589 CFStringRef domain;
1590 CFArrayRef search;
1591 CFArrayRef servers;
1592
1593 domain = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName);
1594 if (isA_CFString(domain)) {
1595 CFStringAppendFormat(description,
1596 NULL,
1597 CFSTR("domain=%@"),
1598 domain);
1599 }
1600
1601 search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains);
1602 if (isA_CFArray(search)) {
1603 CFStringRef str;
1604
1605 str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(","));
1606 CFStringAppendFormat(description,
1607 NULL,
1608 CFSTR("%ssearch=%@"),
1609 CFStringGetLength(description) > 0 ? ", " : "",
1610 str);
1611 CFRelease(str);
1612 }
1613
1614 servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses);
1615 if (isA_CFArray(servers)) {
1616 CFStringRef str;
1617
1618 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
1619 CFStringAppendFormat(description,
1620 NULL,
1621 CFSTR("%sservers=%@"),
1622 CFStringGetLength(description) > 0 ? ", " : "",
1623 str);
1624 CFRelease(str);
1625 }
1626 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
1627 CFStringRef method;
1628
1629 method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod);
1630 if (isA_CFString(method)) {
1631 CFArrayRef addresses;
1632
1633 addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses);
1634 if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) &&
1635 isA_CFArray(addresses)) {
1636 CFStringAppendFormat(description,
1637 NULL,
1638 CFSTR("%@, address=%@"),
1639 method,
1640 CFArrayGetValueAtIndex(addresses, 0));
1641 } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) &&
1642 isA_CFArray(addresses)) {
1643 CFStringAppendFormat(description,
1644 NULL,
1645 CFSTR("%@, address=%@"),
1646 method,
1647 CFArrayGetValueAtIndex(addresses, 0));
1648 } else {
1649 CFStringAppendFormat(description,
1650 NULL,
1651 CFSTR("%@"),
1652 method);
1653 }
1654 }
1655 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
1656 CFStringRef method;
1657
1658 method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod);
1659 if (isA_CFString(method)) {
1660 CFStringAppendFormat(description,
1661 NULL,
1662 CFSTR("%@"),
1663 method);
1664 }
1665 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
1666 CFIndex i;
1667 static proxyKeys *keys[] = { &proxyKeys_FTP, &proxyKeys_Gopher, &proxyKeys_HTTP, &proxyKeys_HTTPS,
1668 &proxyKeys_RTSP, &proxyKeys_SOCKS, &proxyKeys_PAC, &proxyKeys_WPAD };
1669
1670 for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
1671 proxyKeys *currentProxy = keys[i];
1672
1673 if (!__proxy_enabled(configuration, currentProxy->keyEnable)) {
1674 continue;
1675 }
1676
1677 if (((currentProxy->keyProxy != NULL) &&
1678 !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) ||
1679 ((currentProxy->keyURL != NULL) &&
1680 !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) {
1681 continue;
1682 }
1683
1684 CFStringAppendFormat(description,
1685 NULL,
1686 CFSTR("%s%s"),
1687 CFStringGetLength(description) > 0 ? ", " : "",
1688 currentProxy->proxy);
1689 }
1690 }
1691
1692 done :
1693
1694 if (skipEmpty && CFStringGetLength(description) == 0) {
1695 CFRelease(description);
1696 description = NULL;
1697 }
1698
1699 return description;
1700 }