2 * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
27 #include "SystemConfiguration.h"
28 #include "SCValidation.h"
29 #include "SCDynamicStoreCopyDHCPInfo.h"
30 #include "DHCPClientPreferences.h"
32 #define DHCPCLIENT_PREFERENCES_ID "DHCPClient.xml"
33 #define DHCPCLIENT_APPLICATION_PREF "Application"
35 #define DHCP_REQUESTED_PARAMETER_LIST "DHCPRequestedParameterList"
38 ** DHCPClientPreferences{Set,Get}ApplicationOptions()
41 S_get_char_array(CFArrayRef arr
, CFIndex
* len
)
49 count
= CFArrayGetCount(arr
);
58 for (i
= 0, real_count
= 0; i
< count
; i
++) {
59 CFNumberRef n
= isA_CFNumber(CFArrayGetValueAtIndex(arr
, i
));
62 if (n
&& CFNumberGetValue(n
, kCFNumberIntType
, &val
)) {
63 buf
[real_count
++] = (UInt8
) val
;
69 if (count
== 0 && buf
) {
77 my_CFArrayAppendUniqueValue(CFMutableArrayRef arr
, CFTypeRef
new)
81 for (i
= 0; i
< CFArrayGetCount(arr
); i
++) {
82 CFStringRef element
= CFArrayGetValueAtIndex(arr
, i
);
83 if (CFEqual(element
, new)) {
87 CFArrayAppendValue(arr
, new);
91 static __inline__ CFStringRef
92 S_application_path(CFStringRef applicationID
)
94 return (CFStringCreateWithFormat(NULL
, NULL
,
95 CFSTR("/" DHCPCLIENT_APPLICATION_PREF
101 DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID
,
105 CFMutableDictionaryRef dict
= NULL
;
106 CFStringRef path
= NULL
;
107 SCPreferencesRef session
= NULL
;
108 Boolean success
= FALSE
;
110 if (applicationID
== NULL
) {
113 path
= S_application_path(applicationID
);
117 session
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientSetAppReqParams"),
118 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
119 if (session
== NULL
) {
122 dict
= (CFMutableDictionaryRef
)SCPreferencesPathGetValue(session
, path
);
124 dict
= CFDictionaryCreateMutable(NULL
, 0,
125 &kCFTypeDictionaryKeyCallBacks
,
126 &kCFTypeDictionaryValueCallBacks
);
129 dict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
134 if (options
&& count
> 0) {
136 CFMutableArrayRef array
;
138 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
142 for (i
= 0; i
< count
; i
++) {
146 if (options
[i
] == 0 || options
[i
] == 255) {
147 /* ignore pads and end */
151 number
= CFNumberCreate(NULL
, kCFNumberIntType
, &val
);
152 if (number
== NULL
) {
156 my_CFArrayAppendUniqueValue(array
, number
);
159 CFDictionarySetValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
),
164 CFDictionaryRemoveValue(dict
, CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
166 if (SCPreferencesLock(session
, TRUE
)) {
167 success
= SCPreferencesPathSetValue(session
, path
, dict
);
169 success
= SCPreferencesCommitChanges(session
);
171 (void)SCPreferencesApplyChanges(session
);
174 (void)SCPreferencesUnlock(session
);
190 DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID
,
193 CFDictionaryRef dict
= NULL
;
194 UInt8
* options
= NULL
;
196 CFStringRef path
= NULL
;
197 SCPreferencesRef session
= NULL
;
199 if (applicationID
== NULL
) {
202 path
= S_application_path(applicationID
);
206 session
= SCPreferencesCreate(NULL
, CFSTR("DHCPClientCopyAppReqParams"),
207 CFSTR(DHCPCLIENT_PREFERENCES_ID
));
208 if (session
== NULL
) {
211 dict
= SCPreferencesPathGetValue(session
, path
);
215 parms
= CFDictionaryGetValue(dict
,
216 CFSTR(DHCP_REQUESTED_PARAMETER_LIST
));
217 if (isA_CFArray(parms
) == NULL
) {
220 options
= S_get_char_array(parms
, count
);
237 SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store
, CFStringRef serviceID
)
239 CFDictionaryRef dhcp_dict
= NULL
;
240 CFStringRef key
= NULL
;
241 boolean_t needs_close
= FALSE
;
242 CFDictionaryRef primary_dict
= NULL
;
246 store
= SCDynamicStoreCreate(NULL
,
247 CFSTR("SCDynamicStoreCopyDHCPInfo"),
254 if (serviceID
== NULL
) {
255 /* get the primary service name */
256 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
257 kSCDynamicStoreDomainState
,
260 primary_dict
= SCDynamicStoreCopyValue(store
, key
);
262 serviceID
= CFDictionaryGetValue(primary_dict
,
263 kSCDynamicStorePropNetPrimaryService
);
268 if (serviceID
== NULL
) {
271 key
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
272 kSCDynamicStoreDomainState
,
276 dhcp_dict
= SCDynamicStoreCopyValue(store
, key
);
277 if (dhcp_dict
!= NULL
278 && isA_CFDictionary(dhcp_dict
) == NULL
) {
279 CFRelease(dhcp_dict
);
286 CFRelease(primary_dict
);
288 if (needs_close
== TRUE
&& store
!= NULL
) {
295 DHCPInfoGetOptionData(CFDictionaryRef dhcp_dict
, UInt8 code
)
297 CFDataRef data
= NULL
;
298 CFStringRef option_code_str
= NULL
;
300 option_code_str
= CFStringCreateWithFormat(NULL
, NULL
,
301 CFSTR("Option_%d"), code
);
302 if (option_code_str
== NULL
) {
306 data
= CFDictionaryGetValue(dhcp_dict
, option_code_str
);
307 data
= isA_CFData(data
);
310 CFRelease(option_code_str
);
315 DHCPInfoGetLeaseStartTime(CFDictionaryRef dhcp_dict
)
317 return (CFDictionaryGetValue(dhcp_dict
, CFSTR("LeaseStartTime")));
320 #ifdef TEST_DHCPCLIENT_PREFERENCES
322 print_data(u_char
* data_p
, int n_bytes
)
324 #define CHARS_PER_LINE 16
325 char line_buf
[CHARS_PER_LINE
+ 1];
329 for (line_pos
= 0, offset
= 0; offset
< n_bytes
; offset
++, data_p
++) {
331 printf("%04x ", offset
);
333 line_buf
[line_pos
] = isprint(*data_p
) ? *data_p
: '.';
334 printf(" %02x", *data_p
);
336 if (line_pos
== CHARS_PER_LINE
) {
337 line_buf
[CHARS_PER_LINE
] = '\0';
338 printf(" %s\n", line_buf
);
341 else if (line_pos
== (CHARS_PER_LINE
/ 2))
344 if (line_pos
) { /* need to finish up the line */
345 for (; line_pos
< CHARS_PER_LINE
; line_pos
++) {
347 line_buf
[line_pos
] = ' ';
349 line_buf
[CHARS_PER_LINE
] = '\0';
350 printf(" %s\n", line_buf
);
354 #define CMDSTR_GETOPTION "getoption"
355 #define CMDSTR_LEASE "leaseinfo"
356 #define CMDSTR_GETPARAMS "getparams"
357 #define CMDSTR_SETPARAMS "setparams"
359 static __inline__
void
360 S_print_char_array(UInt8
* params
, int n_params
)
364 for (i
= 0; i
< n_params
; i
++) {
366 printf("%d", params
[i
]);
368 printf(", %d", params
[i
]);
376 printf("%s " CMDSTR_GETOPTION
" <serviceID> <opt> [ <type> ]\n"
377 "%s " CMDSTR_LEASE
" <serviceID>\n"
378 "%s " CMDSTR_GETPARAMS
" <app_id>\n"
379 "%s " CMDSTR_SETPARAMS
" <app_id> [ <opt> [ <opt> ] ... [ <opt> ] ] ]\n"
381 " <serviceID> : service ID string | \"\"\n"
382 " <opt> : DHCP/BOOTP option code\n"
383 " (e.g. 1 == subnet mask, 3 == router, 6 = dns, 15 = domain)\n"
384 " <type> : type of option: string, ip\n"
385 " <app_id> : application id (e.g. com.apple.ntpd, com.thursby.Dave)\n",
386 prog
, prog
, prog
, prog
);
391 dump_gregorian_date(CFGregorianDate d
)
393 printf("%d/%d/%d %02d:%02d:%02d\n",
394 (int)d
.year
, d
.month
, d
.day
, d
.hour
, d
.minute
, (int)d
.second
);
399 show_date(CFAbsoluteTime t
)
402 static CFTimeZoneRef tz
= NULL
;
405 tz
= CFTimeZoneCopySystem();
408 d
= CFAbsoluteTimeGetGregorianDate(t
, tz
);
409 dump_gregorian_date(d
);
413 #define IP_FORMAT "%d.%d.%d.%d"
414 #define IP_CH(ip, i) (((u_char *)(ip))[i])
415 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
426 main(int argc
, char * argv
[])
429 command_t command
= command_none_e
;
432 CFDictionaryRef info
;
434 CFStringRef serviceID
= NULL
;
436 command_str
= argv
[1];
439 if (strcmp(command_str
, CMDSTR_GETOPTION
) == 0) {
440 if (argc
< 4 || argc
> 5) {
443 command
= command_getoption_e
;
445 else if (strcmp(command_str
, CMDSTR_LEASE
) == 0) {
449 command
= command_lease_e
;
451 else if (strcmp(command_str
, CMDSTR_SETPARAMS
) == 0) {
452 command
= command_setparams_e
;
457 else if (strcmp(command_str
, CMDSTR_GETPARAMS
) == 0) {
458 command
= command_getparams_e
;
468 case command_getoption_e
: {
472 boolean_t printed
= FALSE
;
477 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
478 CFSTR("%s"), argv
[2]);
481 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
490 code
= atoi(code_str
);
492 option
= DHCPInfoGetOptionData(info
, code
);
493 if (option
== NULL
) {
496 len
= CFDataGetLength(option
);
499 if (strcmp(type
, "ip") == 0) {
501 const void * ptr
= CFDataGetBytePtr(option
);
505 printf(IP_FORMAT
, IP_LIST(ptr
));
508 printf(" " IP_FORMAT
, IP_LIST(ptr
));
516 else if (strcmp(type
, "string") == 0) {
517 printf("%.*s\n", (int)len
, (char *)CFDataGetBytePtr(option
));
523 if (printed
== FALSE
) {
524 print_data((void *)CFDataGetBytePtr(option
), len
);
527 CFRelease(serviceID
);
531 case command_lease_e
: {
535 serviceID
= CFStringCreateWithFormat(NULL
, NULL
,
536 CFSTR("%s"), argv
[2]);
539 info
= SCDynamicStoreCopyDHCPInfo(NULL
, serviceID
);
543 start
= DHCPInfoGetLeaseStartTime(info
);
549 #define OPTION_LEASE_TIME 51
551 option
= DHCPInfoGetOptionData(info
, OPTION_LEASE_TIME
);
552 if (option
== NULL
) {
553 fprintf(stderr
, "what, no lease time?\n");
556 printf("Lease start: ");
557 show_date(CFDateGetAbsoluteTime(start
));
558 lease
= ntohl(*((int32_t *)CFDataGetBytePtr(option
)));
559 if (lease
== 0xffffffff) {
560 printf("Lease is infinite\n");
563 printf("Lease expires: ");
564 show_date(lease
+ CFDateGetAbsoluteTime(start
));
566 option
= DHCPInfoGetOptionData(info
, SERVER_ID
);
568 printf("Server IP: " IP_FORMAT
"\n",
569 IP_LIST(CFDataGetBytePtr(option
)));
573 printf("no lease\n");
576 CFRelease(serviceID
);
580 case command_getparams_e
: {
581 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
582 CFSTR("%s"), argv
[2]);
583 params
= DHCPClientPreferencesCopyApplicationOptions(app_id
, &count
);
585 printf("%s params = {", argv
[2]);
586 S_print_char_array(params
, count
);
592 case command_setparams_e
: {
594 UInt8
* options
= NULL
;
600 options
= malloc(count
);
601 if (options
== NULL
) {
602 fprintf(stderr
, "malloc failed %s\n",
606 for (i
= 0; i
< count
; i
++) {
607 options
[i
] = atoi(argv
[3 + i
]);
610 app_id
= CFStringCreateWithFormat(NULL
, NULL
,
611 CFSTR("%s"), argv
[2]);
612 if (DHCPClientPreferencesSetApplicationOptions(app_id
, options
,
614 printf("operation failed\n");
627 #endif TEST_DHCPCLIENT_PREFERENCES