2 * Copyright (c) 2001-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
30 #include "SystemConfiguration.h"
31 #include "SCValidation.h"
32 #include "SCDynamicStoreCopyDHCPInfo.h"
33 #include "DHCPClientPreferences.h"
35 #define DHCPCLIENT_PREFERENCES_ID "DHCPClient.xml"
36 #define DHCPCLIENT_APPLICATION_PREF "Application"
38 #define DHCP_REQUESTED_PARAMETER_LIST "DHCPRequestedParameterList"
41 ** DHCPClientPreferences{Set,Get}ApplicationOptions()
44 S_get_char_array(CFArrayRef arr
, CFIndex
* len
)
52 count
= CFArrayGetCount(arr
);
61 for (i
= 0, real_count
= 0; i
< count
; i
++) {
62 CFNumberRef n
= isA_CFNumber(CFArrayGetValueAtIndex(arr
, i
));
65 if (n
&& CFNumberGetValue(n
, kCFNumberIntType
, &val
)) {
66 buf
[real_count
++] = (UInt8
) val
;
72 if (count
== 0 && buf
) {
80 my_CFArrayAppendUniqueValue(CFMutableArrayRef arr
, CFTypeRef
new)
83 int n
= CFArrayGetCount(arr
);
85 for (i
= 0; i
< n
; i
++) {
86 CFStringRef element
= CFArrayGetValueAtIndex(arr
, i
);
87 if (CFEqual(element
, new)) {
91 CFArrayAppendValue(arr
, new);
95 static __inline__ CFStringRef
96 S_application_path(CFStringRef applicationID
)
98 return (CFStringCreateWithFormat(NULL
, NULL
,
99 CFSTR("/" DHCPCLIENT_APPLICATION_PREF
105 DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID
,
109 CFMutableDictionaryRef dict
= NULL
;
110 CFStringRef path
= NULL
;
111 SCPreferencesRef session
= NULL
;
112 Boolean success
= FALSE
;
114 if (applicationID
== NULL
) {
117 path
= S_application_path(applicationID
);
121 session
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientSetAppReqParams"),
122 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
123 if (session
== NULL
) {
126 dict
= (CFMutableDictionaryRef
)SCPreferencesPathGetValue(session
, path
);
128 dict
= CFDictionaryCreateMutable(NULL
, 0,
129 &kCFTypeDictionaryKeyCallBacks
,
130 &kCFTypeDictionaryValueCallBacks
);
133 dict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
138 if (options
&& count
> 0) {
140 CFMutableArrayRef array
;
142 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
146 for (i
= 0; i
< count
; i
++) {
150 if (options
[i
] == 0 || options
[i
] == 255) {
151 /* ignore pads and end */
155 number
= CFNumberCreate(NULL
, kCFNumberIntType
, &val
);
156 if (number
== NULL
) {
160 my_CFArrayAppendUniqueValue(array
, number
);
163 CFDictionarySetValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
),
168 CFDictionaryRemoveValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
170 if (SCPreferencesLock(session
, TRUE
)) {
171 success
= SCPreferencesPathSetValue(session
, path
, dict
);
173 success
= SCPreferencesCommitChanges(session
);
175 (void)SCPreferencesApplyChanges(session
);
178 (void)SCPreferencesUnlock(session
);
194 DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID
,
197 CFDictionaryRef dict
= NULL
;
198 UInt8
* options
= NULL
;
200 CFStringRef path
= NULL
;
201 SCPreferencesRef session
= NULL
;
203 if (applicationID
== NULL
) {
206 path
= S_application_path(applicationID
);
210 session
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientCopyAppReqParams"),
211 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
212 if (session
== NULL
) {
215 dict
= SCPreferencesPathGetValue(session
, path
);
219 parms
= CFDictionaryGetValue(dict
,
220 CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
221 if (isA_CFArray(parms
) == NULL
) {
224 options
= S_get_char_array(parms
, count
);
241 SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store
, CFStringRef serviceID
)
243 CFDictionaryRef dhcp_dict
= NULL
;
244 CFStringRef key
= NULL
;
245 boolean_t needs_close
= FALSE
;
246 CFDictionaryRef primary_dict
= NULL
;
250 store
= SCDynamicStoreCreate(NULL
,
251 CFSTR("SCDynamicStoreCopyDHCPInfo"),
258 if (serviceID
== NULL
) {
259 /* get the primary service name */
260 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
261 kSCDynamicStoreDomainState
,
264 primary_dict
= SCDynamicStoreCopyValue(store
, key
);
266 serviceID
= CFDictionaryGetValue(primary_dict
,
267 kSCDynamicStorePropNetPrimaryService
);
272 if (serviceID
== NULL
) {
275 key
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
276 kSCDynamicStoreDomainState
,
280 dhcp_dict
= SCDynamicStoreCopyValue(store
, key
);
281 if (dhcp_dict
!= NULL
282 && isA_CFDictionary(dhcp_dict
) == NULL
) {
283 CFRelease(dhcp_dict
);
290 CFRelease(primary_dict
);
292 if (needs_close
== TRUE
&& store
!= NULL
) {
299 DHCPInfoGetOptionData(CFDictionaryRef dhcp_dict
, UInt8 code
)
301 CFDataRef data
= NULL
;
302 CFStringRef option_code_str
= NULL
;
304 option_code_str
= CFStringCreateWithFormat(NULL
, NULL
,
305 CFSTR("Option_%d"), code
);
306 if (option_code_str
== NULL
) {
310 data
= CFDictionaryGetValue(dhcp_dict
, option_code_str
);
311 data
= isA_CFData(data
);
314 CFRelease(option_code_str
);
319 DHCPInfoGetLeaseStartTime(CFDictionaryRef dhcp_dict
)
321 return (CFDictionaryGetValue(dhcp_dict
, CFSTR("LeaseStartTime")));
324 #ifdef TEST_DHCPCLIENT_PREFERENCES
326 print_data(u_char
* data_p
, int n_bytes
)
328 #define CHARS_PER_LINE 16
329 char line_buf
[CHARS_PER_LINE
+ 1];
333 for (line_pos
= 0, offset
= 0; offset
< n_bytes
; offset
++, data_p
++) {
335 printf("%04x ", offset
);
337 line_buf
[line_pos
] = isprint(*data_p
) ? *data_p
: '.';
338 printf(" %02x", *data_p
);
340 if (line_pos
== CHARS_PER_LINE
) {
341 line_buf
[CHARS_PER_LINE
] = '\0';
342 printf(" %s\n", line_buf
);
345 else if (line_pos
== (CHARS_PER_LINE
/ 2))
348 if (line_pos
) { /* need to finish up the line */
349 for (; line_pos
< CHARS_PER_LINE
; line_pos
++) {
351 line_buf
[line_pos
] = ' ';
353 line_buf
[CHARS_PER_LINE
] = '\0';
354 printf(" %s\n", line_buf
);
358 #define CMDSTR_GETOPTION "getoption"
359 #define CMDSTR_LEASE "leaseinfo"
360 #define CMDSTR_GETPARAMS "getparams"
361 #define CMDSTR_SETPARAMS "setparams"
363 static __inline__
void
364 S_print_char_array(UInt8
* params
, int n_params
)
368 for (i
= 0; i
< n_params
; i
++) {
370 printf("%d", params
[i
]);
372 printf(", %d", params
[i
]);
380 printf("%s " CMDSTR_GETOPTION
" <serviceID> <opt> [ <type> ]\n"
381 "%s " CMDSTR_LEASE
" <serviceID>\n"
382 "%s " CMDSTR_GETPARAMS
" <app_id>\n"
383 "%s " CMDSTR_SETPARAMS
" <app_id> [ <opt> [ <opt> ] ... [ <opt> ] ] ]\n"
385 " <serviceID> : service ID string | \"\"\n"
386 " <opt> : DHCP/BOOTP option code\n"
387 " (e.g. 1 == subnet mask, 3 == router, 6 = dns, 15 = domain)\n"
388 " <type> : type of option: string, ip\n"
389 " <app_id> : application id (e.g. com.apple.ntpd, com.thursby.Dave)\n",
390 prog
, prog
, prog
, prog
);
395 dump_gregorian_date(CFGregorianDate d
)
397 printf("%d/%d/%d %02d:%02d:%02d\n",
398 (int)d
.year
, d
.month
, d
.day
, d
.hour
, d
.minute
, (int)d
.second
);
403 show_date(CFAbsoluteTime t
)
406 static CFTimeZoneRef tz
= NULL
;
409 tz
= CFTimeZoneCopySystem();
412 d
= CFAbsoluteTimeGetGregorianDate(t
, tz
);
413 dump_gregorian_date(d
);
417 #define IP_FORMAT "%d.%d.%d.%d"
418 #define IP_CH(ip, i) (((u_char *)(ip))[i])
419 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
430 main(int argc
, char * argv
[])
433 command_t command
= command_none_e
;
436 CFDictionaryRef info
;
438 CFStringRef serviceID
= NULL
;
440 command_str
= argv
[1];
443 if (strcmp(command_str
, CMDSTR_GETOPTION
) == 0) {
444 if (argc
< 4 || argc
> 5) {
447 command
= command_getoption_e
;
449 else if (strcmp(command_str
, CMDSTR_LEASE
) == 0) {
453 command
= command_lease_e
;
455 else if (strcmp(command_str
, CMDSTR_SETPARAMS
) == 0) {
456 command
= command_setparams_e
;
461 else if (strcmp(command_str
, CMDSTR_GETPARAMS
) == 0) {
462 command
= command_getparams_e
;
472 case command_getoption_e
: {
476 boolean_t printed
= FALSE
;
481 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
482 CFSTR("%s"), argv
[2]);
485 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
494 code
= atoi(code_str
);
496 option
= DHCPInfoGetOptionData(info
, code
);
497 if (option
== NULL
) {
500 len
= CFDataGetLength(option
);
503 if (strcmp(type
, "ip") == 0) {
505 const void * ptr
= CFDataGetBytePtr(option
);
509 printf(IP_FORMAT
, IP_LIST(ptr
));
512 printf(" " IP_FORMAT
, IP_LIST(ptr
));
520 else if (strcmp(type
, "string") == 0) {
521 printf("%.*s\n", (int)len
, (char *)CFDataGetBytePtr(option
));
527 if (printed
== FALSE
) {
528 print_data((void *)CFDataGetBytePtr(option
), len
);
531 CFRelease(serviceID
);
535 case command_lease_e
: {
539 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
540 CFSTR("%s"), argv
[2]);
543 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
547 start
= DHCPInfoGetLeaseStartTime(info
);
553 #define OPTION_LEASE_TIME 51
555 option
= DHCPInfoGetOptionData(info
, OPTION_LEASE_TIME
);
556 if (option
== NULL
) {
557 fprintf(stderr
, "what, no lease time?\n");
560 printf("Lease start: ");
561 show_date(CFDateGetAbsoluteTime(start
));
562 lease
= ntohl(*((int32_t *)CFDataGetBytePtr(option
)));
563 if (lease
== 0xffffffff) {
564 printf("Lease is infinite\n");
567 printf("Lease expires: ");
568 show_date(lease
+ CFDateGetAbsoluteTime(start
));
570 option
= DHCPInfoGetOptionData(info
, SERVER_ID
);
572 printf("Server IP: " IP_FORMAT
"\n",
573 IP_LIST(CFDataGetBytePtr(option
)));
577 printf("no lease\n");
580 CFRelease(serviceID
);
584 case command_getparams_e
: {
585 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
586 CFSTR("%s"), argv
[2]);
587 params
= DHCPClientPreferencesCopyApplicationOptions(app_id
, &count
);
589 printf("%s params = {", argv
[2]);
590 S_print_char_array(params
, count
);
596 case command_setparams_e
: {
598 UInt8
* options
= NULL
;
604 options
= malloc(count
);
605 if (options
== NULL
) {
606 fprintf(stderr
, "malloc failed %s\n",
610 for (i
= 0; i
< count
; i
++) {
611 options
[i
] = atoi(argv
[3 + i
]);
614 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
615 CFSTR("%s"), argv
[2]);
616 if (DHCPClientPreferencesSetApplicationOptions(app_id
, options
,
618 printf("operation failed\n");
631 #endif TEST_DHCPCLIENT_PREFERENCES