2 * Copyright (c) 2001, 2003-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
28 #include "SystemConfiguration.h"
29 #include "SCValidation.h"
30 #include "SCDynamicStoreCopyDHCPInfo.h"
31 #include "DHCPClientPreferences.h"
33 #define DHCPCLIENT_PREFERENCES_ID "DHCPClient.xml"
34 #define DHCPCLIENT_APPLICATION_PREF "Application"
36 #define DHCP_REQUESTED_PARAMETER_LIST "DHCPRequestedParameterList"
39 ** DHCPClientPreferences{Set,Get}ApplicationOptions()
42 S_get_char_array(CFArrayRef arr
, CFIndex
* len
)
50 count
= CFArrayGetCount(arr
);
59 for (i
= 0, real_count
= 0; i
< count
; i
++) {
60 CFNumberRef n
= isA_CFNumber(CFArrayGetValueAtIndex(arr
, i
));
63 if (n
&& CFNumberGetValue(n
, kCFNumberIntType
, &val
)) {
64 buf
[real_count
++] = (UInt8
) val
;
70 if (count
== 0 && buf
) {
78 my_CFArrayAppendUniqueValue(CFMutableArrayRef arr
, CFTypeRef
new)
81 int n
= CFArrayGetCount(arr
);
83 for (i
= 0; i
< n
; i
++) {
84 CFStringRef element
= CFArrayGetValueAtIndex(arr
, i
);
85 if (CFEqual(element
, new)) {
89 CFArrayAppendValue(arr
, new);
93 static __inline__ CFStringRef
94 S_application_path(CFStringRef applicationID
)
96 return (CFStringCreateWithFormat(NULL
, NULL
,
97 CFSTR("/" DHCPCLIENT_APPLICATION_PREF
103 DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID
,
107 CFMutableDictionaryRef dict
= NULL
;
108 CFStringRef path
= NULL
;
109 SCPreferencesRef prefs
= NULL
;
110 Boolean success
= FALSE
;
112 if (applicationID
== NULL
) {
115 path
= S_application_path(applicationID
);
119 prefs
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientSetAppReqParams"),
120 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
124 dict
= (CFMutableDictionaryRef
)SCPreferencesPathGetValue(prefs
, path
);
126 dict
= CFDictionaryCreateMutable(NULL
, 0,
127 &kCFTypeDictionaryKeyCallBacks
,
128 &kCFTypeDictionaryValueCallBacks
);
131 dict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
136 if (options
&& count
> 0) {
138 CFMutableArrayRef array
;
140 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
144 for (i
= 0; i
< count
; i
++) {
148 if (options
[i
] == 0 || options
[i
] == 255) {
149 /* ignore pads and end */
153 number
= CFNumberCreate(NULL
, kCFNumberIntType
, &val
);
154 if (number
== NULL
) {
158 my_CFArrayAppendUniqueValue(array
, number
);
161 CFDictionarySetValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
),
166 CFDictionaryRemoveValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
168 if (SCPreferencesLock(prefs
, TRUE
)) {
169 success
= SCPreferencesPathSetValue(prefs
, path
, dict
);
171 success
= SCPreferencesCommitChanges(prefs
);
173 (void)SCPreferencesApplyChanges(prefs
);
176 (void)SCPreferencesUnlock(prefs
);
192 DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID
,
195 CFDictionaryRef dict
= NULL
;
196 UInt8
* options
= NULL
;
198 CFStringRef path
= NULL
;
199 SCPreferencesRef prefs
= NULL
;
201 if (applicationID
== NULL
) {
204 path
= S_application_path(applicationID
);
208 prefs
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientCopyAppReqParams"),
209 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
213 dict
= SCPreferencesPathGetValue(prefs
, path
);
217 parms
= CFDictionaryGetValue(dict
,
218 CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
219 if (isA_CFArray(parms
) == NULL
) {
222 options
= S_get_char_array(parms
, count
);
239 SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store
, CFStringRef serviceID
)
241 CFDictionaryRef dhcp_dict
= NULL
;
242 CFStringRef key
= NULL
;
243 boolean_t needs_close
= FALSE
;
244 CFDictionaryRef primary_dict
= NULL
;
248 store
= SCDynamicStoreCreate(NULL
,
249 CFSTR("SCDynamicStoreCopyDHCPInfo"),
256 if (serviceID
== NULL
) {
257 /* get the primary service name */
258 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
259 kSCDynamicStoreDomainState
,
262 primary_dict
= SCDynamicStoreCopyValue(store
, key
);
264 serviceID
= CFDictionaryGetValue(primary_dict
,
265 kSCDynamicStorePropNetPrimaryService
);
270 if (serviceID
== NULL
) {
273 key
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
274 kSCDynamicStoreDomainState
,
278 dhcp_dict
= SCDynamicStoreCopyValue(store
, key
);
279 if (dhcp_dict
!= NULL
280 && isA_CFDictionary(dhcp_dict
) == NULL
) {
281 CFRelease(dhcp_dict
);
288 CFRelease(primary_dict
);
290 if (needs_close
== TRUE
&& store
!= NULL
) {
297 DHCPInfoGetOptionData(CFDictionaryRef dhcp_dict
, UInt8 code
)
299 CFDataRef data
= NULL
;
300 CFStringRef option_code_str
= NULL
;
302 option_code_str
= CFStringCreateWithFormat(NULL
, NULL
,
303 CFSTR("Option_%d"), code
);
304 if (option_code_str
== NULL
) {
308 data
= CFDictionaryGetValue(dhcp_dict
, option_code_str
);
309 data
= isA_CFData(data
);
312 CFRelease(option_code_str
);
317 DHCPInfoGetLeaseStartTime(CFDictionaryRef dhcp_dict
)
319 return (CFDictionaryGetValue(dhcp_dict
, CFSTR("LeaseStartTime")));
322 #ifdef TEST_DHCPCLIENT_PREFERENCES
324 print_data(u_char
* data_p
, int n_bytes
)
326 #define CHARS_PER_LINE 16
327 char line_buf
[CHARS_PER_LINE
+ 1];
331 for (line_pos
= 0, offset
= 0; offset
< n_bytes
; offset
++, data_p
++) {
333 printf("%04x ", offset
);
335 line_buf
[line_pos
] = isprint(*data_p
) ? *data_p
: '.';
336 printf(" %02x", *data_p
);
338 if (line_pos
== CHARS_PER_LINE
) {
339 line_buf
[CHARS_PER_LINE
] = '\0';
340 printf(" %s\n", line_buf
);
343 else if (line_pos
== (CHARS_PER_LINE
/ 2))
346 if (line_pos
) { /* need to finish up the line */
347 for (; line_pos
< CHARS_PER_LINE
; line_pos
++) {
349 line_buf
[line_pos
] = ' ';
351 line_buf
[CHARS_PER_LINE
] = '\0';
352 printf(" %s\n", line_buf
);
356 #define CMDSTR_GETOPTION "getoption"
357 #define CMDSTR_LEASE "leaseinfo"
358 #define CMDSTR_GETPARAMS "getparams"
359 #define CMDSTR_SETPARAMS "setparams"
361 static __inline__
void
362 S_print_char_array(UInt8
* params
, int n_params
)
366 for (i
= 0; i
< n_params
; i
++) {
368 printf("%d", params
[i
]);
370 printf(", %d", params
[i
]);
378 printf("%s " CMDSTR_GETOPTION
" <serviceID> <opt> [ <type> ]\n"
379 "%s " CMDSTR_LEASE
" <serviceID>\n"
380 "%s " CMDSTR_GETPARAMS
" <app_id>\n"
381 "%s " CMDSTR_SETPARAMS
" <app_id> [ <opt> [ <opt> ] ... [ <opt> ] ] ]\n"
383 " <serviceID> : service ID string | \"\"\n"
384 " <opt> : DHCP/BOOTP option code\n"
385 " (e.g. 1 == subnet mask, 3 == router, 6 = dns, 15 = domain)\n"
386 " <type> : type of option: string, ip\n"
387 " <app_id> : application id (e.g. com.apple.ntpd, com.thursby.Dave)\n",
388 prog
, prog
, prog
, prog
);
393 dump_gregorian_date(CFGregorianDate d
)
395 printf("%d/%d/%d %02d:%02d:%02d\n",
396 (int)d
.year
, d
.month
, d
.day
, d
.hour
, d
.minute
, (int)d
.second
);
401 show_date(CFAbsoluteTime t
)
404 static CFTimeZoneRef tz
= NULL
;
407 tz
= CFTimeZoneCopySystem();
410 d
= CFAbsoluteTimeGetGregorianDate(t
, tz
);
411 dump_gregorian_date(d
);
415 #define IP_FORMAT "%d.%d.%d.%d"
416 #define IP_CH(ip, i) (((u_char *)(ip))[i])
417 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
428 main(int argc
, char * argv
[])
431 command_t command
= command_none_e
;
434 CFDictionaryRef info
;
436 CFStringRef serviceID
= NULL
;
438 command_str
= argv
[1];
441 if (strcmp(command_str
, CMDSTR_GETOPTION
) == 0) {
442 if (argc
< 4 || argc
> 5) {
445 command
= command_getoption_e
;
447 else if (strcmp(command_str
, CMDSTR_LEASE
) == 0) {
451 command
= command_lease_e
;
453 else if (strcmp(command_str
, CMDSTR_SETPARAMS
) == 0) {
454 command
= command_setparams_e
;
459 else if (strcmp(command_str
, CMDSTR_GETPARAMS
) == 0) {
460 command
= command_getparams_e
;
470 case command_getoption_e
: {
474 boolean_t printed
= FALSE
;
479 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
480 CFSTR("%s"), argv
[2]);
483 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
492 code
= atoi(code_str
);
494 option
= DHCPInfoGetOptionData(info
, code
);
495 if (option
== NULL
) {
498 len
= CFDataGetLength(option
);
501 if (strcmp(type
, "ip") == 0) {
503 const void * ptr
= CFDataGetBytePtr(option
);
507 printf(IP_FORMAT
, IP_LIST(ptr
));
510 printf(" " IP_FORMAT
, IP_LIST(ptr
));
518 else if (strcmp(type
, "string") == 0) {
519 printf("%.*s\n", (int)len
, (char *)CFDataGetBytePtr(option
));
525 if (printed
== FALSE
) {
526 print_data((void *)CFDataGetBytePtr(option
), len
);
529 CFRelease(serviceID
);
533 case command_lease_e
: {
537 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
538 CFSTR("%s"), argv
[2]);
541 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
545 start
= DHCPInfoGetLeaseStartTime(info
);
551 #define OPTION_LEASE_TIME 51
553 option
= DHCPInfoGetOptionData(info
, OPTION_LEASE_TIME
);
554 if (option
== NULL
) {
555 fprintf(stderr
, "what, no lease time?\n");
558 printf("Lease start: ");
559 show_date(CFDateGetAbsoluteTime(start
));
560 lease
= ntohl(*((int32_t *)CFDataGetBytePtr(option
)));
561 if (lease
== 0xffffffff) {
562 printf("Lease is infinite\n");
565 printf("Lease expires: ");
566 show_date(lease
+ CFDateGetAbsoluteTime(start
));
568 option
= DHCPInfoGetOptionData(info
, SERVER_ID
);
570 printf("Server IP: " IP_FORMAT
"\n",
571 IP_LIST(CFDataGetBytePtr(option
)));
575 printf("no lease\n");
578 CFRelease(serviceID
);
582 case command_getparams_e
: {
583 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
584 CFSTR("%s"), argv
[2]);
585 params
= DHCPClientPreferencesCopyApplicationOptions(app_id
, &count
);
587 printf("%s params = {", argv
[2]);
588 S_print_char_array(params
, count
);
594 case command_setparams_e
: {
596 UInt8
* options
= NULL
;
602 options
= malloc(count
);
603 if (options
== NULL
) {
604 fprintf(stderr
, "malloc failed %s\n",
608 for (i
= 0; i
< count
; i
++) {
609 options
[i
] = atoi(argv
[3 + i
]);
612 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
613 CFSTR("%s"), argv
[2]);
614 if (DHCPClientPreferencesSetApplicationOptions(app_id
, options
,
616 printf("operation failed\n");
629 #endif TEST_DHCPCLIENT_PREFERENCES