]> git.saurik.com Git - apple/configd.git/blame - Plugins/IPMonitor/set-hostname.c
configd-1109.40.9.tar.gz
[apple/configd.git] / Plugins / IPMonitor / set-hostname.c
CommitLineData
dbf6a266 1/*
59647b27 2 * Copyright (c) 2004-2018, 2020 Apple Inc. All rights reserved.
dbf6a266
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
78403150 5 *
dbf6a266
A
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.
78403150 12 *
dbf6a266
A
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.
78403150 20 *
dbf6a266
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <ctype.h>
24#include <stdio.h>
25#include <unistd.h>
851a47a8 26#include <sys/param.h>
dbf6a266
A
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/time.h>
30#include <net/if.h>
31#include <net/if_dl.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34#include <netdb_async.h>
35
36#include <CoreFoundation/CoreFoundation.h>
37#include <SystemConfiguration/SystemConfiguration.h>
38#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
39#include <SystemConfiguration/SCValidation.h>
edebe297 40#include <SystemConfiguration/SCPrivate.h>
dbf6a266
A
41
42#include <notify.h>
78403150
A
43
44#ifdef MAIN
942cecd7 45#define my_log(__level, __format, ...) SCPrint(TRUE, stdout, CFSTR(__format "\n"), ## __VA_ARGS__)
78403150 46#else // MAIN
5e9ce69e 47#include "ip_plugin.h"
78403150 48#endif // MAIN
dbf6a266 49
dbf6a266 50static SCDynamicStoreRef store = NULL;
9de8ab86 51static CFRunLoopRef rl = NULL;
dbf6a266 52static CFRunLoopSourceRef rls = NULL;
9de8ab86
A
53static dispatch_queue_t queue = NULL;
54
55static int notify_token = -1;
dbf6a266 56
78403150
A
57static struct timeval ptrQueryStart;
58static SCNetworkReachabilityRef ptrTarget = NULL;
dbf6a266 59
dbf6a266 60
dbf6a266 61#define HOSTNAME_NOTIFY_KEY "com.apple.system.hostname"
9de8ab86 62#define SET_HOSTNAME_QUEUE "com.apple.config.set-hostname"
dbf6a266 63
17d3ee29 64CFStringRef copy_dhcp_hostname(CFStringRef serviceID);
dbf6a266
A
65
66static void
67set_hostname(CFStringRef hostname)
68{
69 if (hostname != NULL) {
70 char old_name[MAXHOSTNAMELEN];
71 char new_name[MAXHOSTNAMELEN];
72
73 if (gethostname(old_name, sizeof(old_name)) == -1) {
5e9ce69e 74 my_log(LOG_ERR, "gethostname() failed: %s", strerror(errno));
dbf6a266
A
75 old_name[0] = '\0';
76 }
77
78 if (_SC_cfstring_to_cstring(hostname,
79 new_name,
80 sizeof(new_name),
81 kCFStringEncodingUTF8) == NULL) {
9de8ab86 82 my_log(LOG_NOTICE, "could not convert [new] hostname");
dbf6a266
A
83 new_name[0] = '\0';
84 }
85
86 old_name[sizeof(old_name)-1] = '\0';
87 new_name[sizeof(new_name)-1] = '\0';
88 if (strcmp(old_name, new_name) != 0) {
78403150 89 if (sethostname(new_name, (int)strlen(new_name)) == 0) {
dbf6a266
A
90 uint32_t status;
91
5e9ce69e
A
92 my_log(LOG_NOTICE,
93 "setting hostname to \"%s\"",
94 new_name);
dbf6a266
A
95
96 status = notify_post(HOSTNAME_NOTIFY_KEY);
97 if (status != NOTIFY_STATUS_OK) {
5e9ce69e 98 my_log(LOG_ERR,
78403150 99 "notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%u",
5e9ce69e 100 status);
dbf6a266
A
101 }
102 } else {
5e9ce69e 103 my_log(LOG_ERR,
78403150 104 "sethostname(%s, %ld) failed: %s",
5e9ce69e
A
105 new_name,
106 strlen(new_name),
107 strerror(errno));
dbf6a266
A
108 }
109 }
110 }
111
112 return;
113}
114
115
dbf6a266
A
116static CFStringRef
117copy_prefs_hostname(SCDynamicStoreRef store)
118{
119 CFDictionaryRef dict;
120 CFStringRef key;
121 CFStringRef name = NULL;
122
123 key = SCDynamicStoreKeyCreateComputerName(NULL);
124 dict = SCDynamicStoreCopyValue(store, key);
125 CFRelease(key);
126 if (dict == NULL) {
127 goto done;
128 }
129 if (!isA_CFDictionary(dict)) {
130 goto done;
131 }
132
edebe297 133 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemHostName));
dbf6a266
A
134 if (name == NULL) {
135 goto done;
136 }
137 CFRetain(name);
138
139 done :
140
141 if (dict != NULL) CFRelease(dict);
edebe297 142
dbf6a266
A
143 return name;
144}
145
146
147static CFStringRef
148copy_primary_service(SCDynamicStoreRef store)
149{
150 CFDictionaryRef dict;
151 CFStringRef key;
152 CFStringRef serviceID = NULL;
153
154 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
155 kSCDynamicStoreDomainState,
156 kSCEntNetIPv4);
157 dict = SCDynamicStoreCopyValue(store, key);
158 CFRelease(key);
159
160 if (dict != NULL) {
161 if (isA_CFDictionary(dict)) {
162 serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService);
163 if (isA_CFString(serviceID)) {
164 CFRetain(serviceID);
165 } else {
166 serviceID = NULL;
167 }
168 }
169 CFRelease(dict);
170 }
171
172 return serviceID;
173}
174
175
176static CFStringRef
177copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID)
178{
179 CFDictionaryRef dict;
180 CFStringRef key;
181 CFStringRef address = NULL;
182
183 key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
184 kSCDynamicStoreDomainState,
185 serviceID,
186 kSCEntNetIPv4);
187 dict = SCDynamicStoreCopyValue(store, key);
188 CFRelease(key);
189
190 if (dict != NULL) {
191 if (isA_CFDictionary(dict)) {
192 CFArrayRef addresses;
193
194 addresses = CFDictionaryGetValue(dict, kSCPropNetIPv4Addresses);
195 if (isA_CFArray(addresses) && (CFArrayGetCount(addresses) > 0)) {
196 address = CFArrayGetValueAtIndex(addresses, 0);
197 if (isA_CFString(address)) {
198 CFRetain(address);
199 } else {
200 address = NULL;
201 }
202 }
203 }
204 CFRelease(dict);
205 }
206
207 return address;
208}
209
78403150 210
dbf6a266 211static void
78403150 212ptr_query_stop()
dbf6a266 213{
78403150
A
214 if (ptrTarget == NULL) {
215 return;
216 }
217
9de8ab86
A
218 my_log(LOG_INFO, "hostname: ptr query stop");
219
78403150 220 SCNetworkReachabilitySetCallback(ptrTarget, NULL, NULL);
9de8ab86 221 SCNetworkReachabilityUnscheduleFromRunLoop(ptrTarget, rl, kCFRunLoopDefaultMode);
78403150
A
222 CFRelease(ptrTarget);
223 ptrTarget = NULL;
dbf6a266 224
78403150
A
225 return;
226}
227
228
9de8ab86
A
229/* Return a ptr record if the sharing pref name is a matching FQDN */
230static CFStringRef
231hostname_match_full(CFArrayRef hosts, CFIndex count, CFStringRef nameToMatch)
232{
233 CFIndex i;
234 CFStringRef matchedHostName = NULL;
235
236 for (i = 0; i < count; i++) {
237 CFStringRef tempHostName;
238
239 tempHostName = CFArrayGetValueAtIndex(hosts, i);
240 if (CFStringCompare(tempHostName, nameToMatch, kCFCompareCaseInsensitive) == 0) {
241 matchedHostName = tempHostName;
242 break;
243 }
244 }
245 return matchedHostName;
246}
247
248
249/* Return a ptr record if the sharing pref name matches DNS record's first label */
250static CFStringRef
251hostname_match_first_label(CFArrayRef hosts, CFIndex count, CFStringRef nameToMatch)
252{
253 CFIndex i;
254 CFStringRef matchedHostName = NULL;
255
256 for (i = 0; i < count; i++) {
257 CFArrayRef fqdnSeparated;
258 CFStringRef tempHostName;
259
260 tempHostName = CFArrayGetValueAtIndex(hosts, i);
261 fqdnSeparated = CFStringCreateArrayBySeparatingStrings(NULL, tempHostName, CFSTR("."));
262 if (fqdnSeparated != NULL) {
263 CFStringRef firstLabel;
264 Boolean matchFound;
265
266 firstLabel = CFArrayGetValueAtIndex(fqdnSeparated, 0);
267 matchFound = (CFStringCompare(firstLabel, nameToMatch, kCFCompareCaseInsensitive) == 0);
268 CFRelease(fqdnSeparated);
269 if (matchFound) {
270 matchedHostName = tempHostName;
271 break;
272 }
273 }
274 }
275 return matchedHostName;
276}
277
278
78403150
A
279static void
280ptr_query_callback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
281{
1ef45fa4 282#pragma unused(info)
78403150
A
283 CFStringRef hostname = NULL;
284 struct timeval ptrQueryComplete;
285 struct timeval ptrQueryElapsed;
286
287 (void) gettimeofday(&ptrQueryComplete, NULL);
288 timersub(&ptrQueryComplete, &ptrQueryStart, &ptrQueryElapsed);
dbf6a266
A
289
290 // use reverse DNS name, if available
291
78403150
A
292 if (flags & kSCNetworkReachabilityFlagsReachable) {
293 int error_num;
294 CFArrayRef hosts;
295
296 /*
297 * if [reverse] DNS query was successful
298 */
299 hosts = SCNetworkReachabilityCopyResolvedAddress(target, &error_num);
300 if (hosts != NULL) {
9de8ab86
A
301 CFIndex count = CFArrayGetCount(hosts);
302 if (count > 0) {
303 CFStringRef computerName;
304 CFStringRef localHostName;
305
306 my_log(LOG_INFO, "hostname: ptr query complete (query time = %ld.%3.3d)",
307 ptrQueryElapsed.tv_sec,
308 ptrQueryElapsed.tv_usec / 1000);
309
310 // first, check if ComputerName is dns-clean
311 computerName = _SCPreferencesCopyComputerName(NULL, NULL);
312 if (computerName != NULL) {
313 if (_SC_CFStringIsValidDNSName(computerName)) {
314 CFRange dotsCheck;
315
316 dotsCheck = CFStringFind(computerName, CFSTR("."), 0);
317 if (dotsCheck.length == 0) {
318 hostname = hostname_match_first_label(hosts, count, computerName);
319 } else {
320 hostname = hostname_match_full(hosts, count, computerName);
321 }
322 }
323 CFRelease(computerName);
324 }
325
326 // if no match, check LocalHostName against the first label of FQDN
327 localHostName = (hostname == NULL) ? SCDynamicStoreCopyLocalHostName(store) : NULL;
328 if (localHostName != NULL) {
329 hostname = hostname_match_first_label(hosts, count, localHostName);
330 CFRelease(localHostName);
331 }
332
333 // if no match, use the first of the returned names
334 if (hostname == NULL) {
335 hostname = CFArrayGetValueAtIndex(hosts, 0);
336 }
78403150 337
9de8ab86 338 my_log(LOG_INFO, "hostname (reverse DNS query) = %@", hostname);
78403150 339 set_hostname(hostname);
9de8ab86
A
340 } else {
341 my_log(LOG_INFO, "hostname: ptr query complete w/no hosts (query time = %ld.%3.3d)",
342 ptrQueryElapsed.tv_sec,
343 ptrQueryElapsed.tv_usec / 1000);
78403150
A
344 }
345 CFRelease(hosts);
346
347 if (hostname != NULL) {
348 goto done;
dbf6a266 349 }
9de8ab86
A
350 } else {
351 // if kSCNetworkReachabilityFlagsReachable and hosts == NULL
352 // it means the PTR request has not come back yet
353 // we must wait for this callback to be called again
354 my_log(LOG_INFO, "hostname: ptr query reply w/no hosts (query time = %ld.%3.3d)",
355 ptrQueryElapsed.tv_sec,
356 ptrQueryElapsed.tv_usec / 1000);
357 return;
78403150 358 }
9de8ab86
A
359 } else {
360 my_log(LOG_INFO, "hostname: ptr query complete, host not found (query time = %ld.%3.3d)",
361 ptrQueryElapsed.tv_sec,
362 ptrQueryElapsed.tv_usec / 1000);
dbf6a266
A
363 }
364
365 // get local (multicast DNS) name, if available
366
367 hostname = SCDynamicStoreCopyLocalHostName(store);
368 if (hostname != NULL) {
9de8ab86
A
369 CFMutableStringRef localHostName;
370
371 my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname);
372 localHostName = CFStringCreateMutableCopy(NULL, 0, hostname);
373 assert(localHostName != NULL);
374 CFStringAppend(localHostName, CFSTR(".local"));
375 set_hostname(localHostName);
376 CFRelease(localHostName);
dbf6a266
A
377 CFRelease(hostname);
378 goto done;
379 }
380
381 // use "localhost" if not other name is available
382
9de8ab86 383 my_log(LOG_INFO, "hostname (localhost)");
dbf6a266
A
384 set_hostname(CFSTR("localhost"));
385
386 done :
387
78403150 388 ptr_query_stop();
a40a14f8 389
78403150 390#ifdef MAIN
9de8ab86 391 CFRunLoopStop(rl);
78403150 392#endif // MAIN
a40a14f8
A
393
394 return;
395}
396
397
78403150
A
398static Boolean
399ptr_query_start(CFStringRef address)
dbf6a266 400{
17d3ee29 401 union {
78403150
A
402 struct sockaddr sa;
403 struct sockaddr_in sin;
404 struct sockaddr_in6 sin6;
17d3ee29
A
405 } addr;
406 char buf[64];
78403150
A
407 CFDataRef data;
408 CFMutableDictionaryRef options;
dbf6a266 409
17d3ee29 410 if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
78403150
A
411 my_log(LOG_ERR, "could not convert [primary] address string");
412 return FALSE;
dbf6a266
A
413 }
414
17d3ee29 415 if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
78403150
A
416 my_log(LOG_ERR, "could not convert [primary] address");
417 return FALSE;
edebe297
A
418 }
419
78403150
A
420 options = CFDictionaryCreateMutable(NULL,
421 0,
422 &kCFTypeDictionaryKeyCallBacks,
423 &kCFTypeDictionaryValueCallBacks);
424 data = CFDataCreate(NULL, (const UInt8 *)&addr.sa, addr.sa.sa_len);
425 CFDictionarySetValue(options, kSCNetworkReachabilityOptionPTRAddress, data);
426 CFRelease(data);
427 ptrTarget = SCNetworkReachabilityCreateWithOptions(NULL, options);
428 CFRelease(options);
429 if (ptrTarget == NULL) {
430 my_log(LOG_ERR, "could not resolve [primary] address");
431 return FALSE;
dbf6a266
A
432 }
433
9de8ab86
A
434 my_log(LOG_INFO, "hostname: ptr query start");
435
afb19109 436 (void) gettimeofday(&ptrQueryStart, NULL);
78403150 437 (void) SCNetworkReachabilitySetCallback(ptrTarget, ptr_query_callback, NULL);
9de8ab86 438 (void) SCNetworkReachabilityScheduleWithRunLoop(ptrTarget, rl, kCFRunLoopDefaultMode);
dbf6a266 439
78403150 440 return TRUE;
dbf6a266
A
441}
442
443
444static void
445update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
446{
1ef45fa4
A
447#pragma unused(changedKeys)
448#pragma unused(info)
dbf6a266
A
449 CFStringRef address = NULL;
450 CFStringRef hostname = NULL;
451 CFStringRef serviceID = NULL;
452
d6c893b2
A
453 // if active, cancel any in-progress attempt to resolve the primary IP address
454
78403150
A
455 if (ptrTarget != NULL) {
456 ptr_query_stop();
dbf6a266
A
457 }
458
459 // get [prefs] hostname, if available
460
461 hostname = copy_prefs_hostname(store);
462 if (hostname != NULL) {
9de8ab86 463 my_log(LOG_INFO, "hostname (prefs) = %@", hostname);
dbf6a266
A
464 set_hostname(hostname);
465 goto done;
466 }
467
468 // get primary service ID
469
470 serviceID = copy_primary_service(store);
471 if (serviceID == NULL) {
472 goto mDNS;
473 }
474
475 // get DHCP provided name, if available
476
17d3ee29 477 hostname = copy_dhcp_hostname(serviceID);
dbf6a266 478 if (hostname != NULL) {
9de8ab86 479 my_log(LOG_INFO, "hostname (DHCP) = %@", hostname);
dbf6a266
A
480 set_hostname(hostname);
481 goto done;
482 }
483
484 // get DNS name associated with primary IP, if available
485
486 address = copy_primary_ip(store, serviceID);
487 if (address != NULL) {
942cecd7 488 boolean_t isExpensive;
78403150 489
dbf6a266 490 // start reverse DNS query using primary IP address
9de8ab86
A
491 // if primary service is not expensive
492 isExpensive = check_if_service_expensive(serviceID);
942cecd7
A
493 if (!isExpensive) {
494 Boolean ok;
9de8ab86 495
9de8ab86
A
496 ok = ptr_query_start(address);
497 if (ok) {
498 // if query started
499 goto done;
500 }
78403150 501 }
dbf6a266
A
502 }
503
504 mDNS :
505
506 // get local (multicast DNS) name, if available
507
508 hostname = SCDynamicStoreCopyLocalHostName(store);
509 if (hostname != NULL) {
9de8ab86
A
510 CFMutableStringRef localHostName;
511
512 my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname);
513 localHostName = CFStringCreateMutableCopy(NULL, 0, hostname);
514 assert(localHostName != NULL);
515 CFStringAppend(localHostName, CFSTR(".local"));
516 set_hostname(localHostName);
517 CFRelease(localHostName);
dbf6a266
A
518 goto done;
519 }
520
521 // use "localhost" if not other name is available
522
523 set_hostname(CFSTR("localhost"));
524
525 done :
526
527 if (address) CFRelease(address);
528 if (hostname) CFRelease(hostname);
529 if (serviceID) CFRelease(serviceID);
530
531 return;
532}
533
534
535__private_extern__
536void
537load_hostname(Boolean verbose)
538{
1ef45fa4 539#pragma unused(verbose)
dbf6a266
A
540 CFStringRef key;
541 CFMutableArrayRef keys = NULL;
9de8ab86
A
542 dispatch_block_t notify_block;
543 Boolean ok;
dbf6a266 544 CFMutableArrayRef patterns = NULL;
9de8ab86 545 uint32_t status;
dbf6a266
A
546
547 /* initialize a few globals */
548
549 store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), update_hostname, NULL);
550 if (store == NULL) {
5e9ce69e
A
551 my_log(LOG_ERR,
552 "SCDynamicStoreCreate() failed: %s",
553 SCErrorString(SCError()));
dbf6a266
A
554 goto error;
555 }
942cecd7 556
9de8ab86
A
557 queue = dispatch_queue_create(SET_HOSTNAME_QUEUE, NULL);
558 if (queue == NULL) {
559 my_log(LOG_ERR,
560 "dispatch_queue_create() failed");
561 goto error;
562 }
dbf6a266
A
563
564 /* establish notification keys and patterns */
565
566 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
567 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
568
dbf6a266
A
569 /* ...watch for (per-service) DHCP option changes */
570 key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
571 kSCDynamicStoreDomainState,
572 kSCCompAnyRegex,
573 kSCEntNetDHCP);
574 CFArrayAppendValue(patterns, key);
575 CFRelease(key);
576
577 /* ...watch for (BSD) hostname changes */
578 key = SCDynamicStoreKeyCreateComputerName(NULL);
579 CFArrayAppendValue(keys, key);
580 CFRelease(key);
581
582 /* ...watch for local (multicast DNS) hostname changes */
583 key = SCDynamicStoreKeyCreateHostNames(NULL);
584 CFArrayAppendValue(keys, key);
585 CFRelease(key);
586
587 /* register the keys/patterns */
9de8ab86
A
588 ok = SCDynamicStoreSetNotificationKeys(store, keys, patterns);
589 CFRelease(keys);
590 CFRelease(patterns);
591 if (!ok) {
5e9ce69e
A
592 my_log(LOG_ERR,
593 "SCDynamicStoreSetNotificationKeys() failed: %s",
594 SCErrorString(SCError()));
dbf6a266
A
595 goto error;
596 }
597
9de8ab86 598 rl = CFRunLoopGetCurrent();
dbf6a266 599 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
9de8ab86 600 if (rls == NULL) {
5e9ce69e
A
601 my_log(LOG_ERR,
602 "SCDynamicStoreCreateRunLoopSource() failed: %s",
603 SCErrorString(SCError()));
dbf6a266
A
604 goto error;
605 }
9de8ab86
A
606 CFRunLoopAddSource(rl, rls, kCFRunLoopDefaultMode);
607
608 /* ...watch for primary service/interface and DNS configuration changes */
609 notify_block = ^{
610 CFArrayRef changes;
611 CFStringRef key;
612
613 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
614 kSCDynamicStoreDomainState,
615 kSCEntNetDNS);
616 changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
617 (*update_hostname)(store, changes, NULL);
618 CFRelease(changes);
619 CFRelease(key);
620
621 return;
622 };
623 status = notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE,
624 &notify_token,
625 queue,
626 ^(int token){
1ef45fa4 627#pragma unused(token)
9de8ab86
A
628 CFRunLoopPerformBlock(rl,
629 kCFRunLoopDefaultMode,
630 notify_block);
631 CFRunLoopWakeUp(rl);
632 });
633 if (status != NOTIFY_STATUS_OK) {
634 my_log(LOG_ERR, "notify_register_dispatch() failed: %u", status);
635 goto error;
636 }
dbf6a266 637
dbf6a266
A
638 return;
639
640 error :
641
9de8ab86
A
642 if (rls != NULL) {
643 CFRunLoopRemoveSource(rl, rls, kCFRunLoopDefaultMode);
644 CFRelease(rls);
645 rls = NULL;
646 }
647 if (store != NULL) {
648 CFRelease(store);
649 store = NULL;
650 }
651 if (queue != NULL) {
652 dispatch_release(queue);
653 queue = NULL;
654 }
655
dbf6a266
A
656 return;
657}
658
659
660#ifdef MAIN
661int
662main(int argc, char **argv)
663{
664
665#ifdef DEBUG
666
59647b27 667 _sc_log = kSCLogDestinationFile;
dbf6a266
A
668 if ((argc > 1) && (strcmp(argv[1], "-d") == 0)) {
669 _sc_verbose = TRUE;
670 argv++;
671 argc--;
672 }
673
674 CFStringRef address;
675 CFStringRef hostname;
676 CFStringRef serviceID;
677 SCDynamicStoreRef store;
678
679 store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), NULL, NULL);
680 if (store == NULL) {
681 SCPrint(TRUE, stdout,
682 CFSTR("SCDynamicStoreCreate() failed: %s\n"),
683 SCErrorString(SCError()));
684 exit(1);
685 }
686
78403150
A
687 // get [prefs] hostname, if available
688 hostname = copy_prefs_hostname(store);
dbf6a266 689 if (hostname != NULL) {
78403150 690 SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname);
dbf6a266
A
691 CFRelease(hostname);
692 }
693
78403150
A
694 // get local (multicast DNS) name, if available
695
696 hostname = SCDynamicStoreCopyLocalHostName(store);
dbf6a266 697 if (hostname != NULL) {
78403150 698 SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname);
dbf6a266
A
699 CFRelease(hostname);
700 }
701
702 // get primary service
703 serviceID = copy_primary_service(store);
704 if (serviceID != NULL) {
705 SCPrint(TRUE, stdout, CFSTR("primary service ID = %@\n"), serviceID);
706 } else {
707 SCPrint(TRUE, stdout, CFSTR("No primary service\n"));
dbf6a266
A
708 }
709
710 if ((argc == (2+1)) && (argv[1][0] == 's')) {
711 if (serviceID != NULL) CFRelease(serviceID);
712 serviceID = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
713 SCPrint(TRUE, stdout, CFSTR("alternate service ID = %@\n"), serviceID);
714 }
715
78403150
A
716 if (serviceID != NULL) {
717 // get DHCP provided name
718 hostname = copy_dhcp_hostname(serviceID);
719 if (hostname != NULL) {
720 SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname);
721 CFRelease(hostname);
dbf6a266
A
722 }
723
78403150
A
724 // get primary IP address
725 address = copy_primary_ip(store, serviceID);
726 if (address != NULL) {
727 SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address);
dbf6a266 728
78403150
A
729 if ((argc == (2+1)) && (argv[1][0] == 'a')) {
730 if (address != NULL) CFRelease(address);
731 address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
732 SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address);
733 }
dbf6a266 734
78403150
A
735 // start reverse DNS query using primary IP address
736 (void) ptr_query_start(address);
737 CFRelease(address);
738 }
dbf6a266 739
78403150 740 CFRelease(serviceID);
dbf6a266
A
741 }
742
dbf6a266
A
743 CFRelease(store);
744
745 CFRunLoopRun();
746
747#else /* DEBUG */
748
59647b27 749 _sc_log = kSCLogDestinationFile;
dbf6a266
A
750 _sc_verbose = (argc > 1) ? TRUE : FALSE;
751
752 load_hostname((argc > 1) ? TRUE : FALSE);
753 CFRunLoopRun();
754 /* not reached */
755
756#endif /* DEBUG */
757
758 exit(0);
759 return 0;
760}
761#endif /* MAIN */