]> git.saurik.com Git - apple/configd.git/blob - Plugins/IPMonitor/set-hostname.c
configd-293.8.tar.gz
[apple/configd.git] / Plugins / IPMonitor / set-hostname.c
1 /*
2 * Copyright (c) 2004-2009 Apple 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 #include <ctype.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <sys/param.h>
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>
40 #include <SystemConfiguration/SCPrivate.h>
41
42 #include <notify.h>
43
44 static SCDynamicStoreRef store = NULL;
45 static CFRunLoopSourceRef rls = NULL;
46
47 static Boolean dnsActive = FALSE;
48 static CFMachPortRef dnsPort = NULL;
49 static struct timeval dnsQueryStart;
50
51 static Boolean _verbose = FALSE;
52
53
54 #define HOSTNAME_NOTIFY_KEY "com.apple.system.hostname"
55
56
57 static void
58 set_hostname(CFStringRef hostname)
59 {
60 if (hostname != NULL) {
61 char old_name[MAXHOSTNAMELEN];
62 char new_name[MAXHOSTNAMELEN];
63
64 if (gethostname(old_name, sizeof(old_name)) == -1) {
65 SCLog(TRUE, LOG_ERR, CFSTR("gethostname() failed: %s"), strerror(errno));
66 old_name[0] = '\0';
67 }
68
69 if (_SC_cfstring_to_cstring(hostname,
70 new_name,
71 sizeof(new_name),
72 kCFStringEncodingUTF8) == NULL) {
73 SCLog(TRUE, LOG_ERR, CFSTR("could not convert [new] hostname"));
74 new_name[0] = '\0';
75 }
76
77 old_name[sizeof(old_name)-1] = '\0';
78 new_name[sizeof(new_name)-1] = '\0';
79 if (strcmp(old_name, new_name) != 0) {
80 if (sethostname(new_name, strlen(new_name)) == 0) {
81 uint32_t status;
82
83 SCLog(TRUE, LOG_NOTICE,
84 CFSTR("setting hostname to \"%s\""),
85 new_name);
86
87 status = notify_post(HOSTNAME_NOTIFY_KEY);
88 if (status != NOTIFY_STATUS_OK) {
89 SCLog(TRUE, LOG_ERR,
90 CFSTR("notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu"),
91 status);
92 }
93 } else {
94 SCLog(TRUE, LOG_ERR,
95 CFSTR("sethostname(%s, %d) failed: %s"),
96 new_name,
97 strlen(new_name),
98 strerror(errno));
99 }
100 }
101 }
102
103 return;
104 }
105
106
107 #define HOSTCONFIG "/etc/hostconfig"
108 #define HOSTNAME_KEY "HOSTNAME="
109 #define AUTOMATIC "-AUTOMATIC-"
110
111 #define HOSTNAME_KEY_LEN (sizeof(HOSTNAME_KEY) - 1)
112
113 static CFStringRef
114 copy_static_name()
115 {
116 FILE * f;
117 char buf[256];
118 CFStringRef name = NULL;
119
120 f = fopen(HOSTCONFIG, "r");
121 if (f == NULL) {
122 return NULL;
123 }
124
125 while (fgets(buf, sizeof(buf), f) != NULL) {
126 char * bp;
127 int n;
128 char * np;
129 Boolean str_escape;
130 Boolean str_quote;
131
132 n = strlen(buf);
133 if (buf[n-1] == '\n') {
134 /* the entire line fit in the buffer, remove the newline */
135 buf[n-1] = '\0';
136 } else {
137 /* eat the remainder of the line */
138 do {
139 n = fgetc(f);
140 } while ((n != '\n') && (n != EOF));
141 }
142
143 // skip leading white space
144 bp = &buf[0];
145 while (isspace(*bp)) {
146 bp++;
147 }
148
149 // find "HOSTNAME=" key
150 if (strncmp(bp, HOSTNAME_KEY, HOSTNAME_KEY_LEN) != 0) {
151 continue; // if not
152 }
153
154 // get the hostname string
155 bp += HOSTNAME_KEY_LEN;
156 str_escape = FALSE;
157 str_quote = FALSE;
158
159 np = &buf[0];
160 while (*bp != '\0') {
161 char ch = *bp;
162
163 switch (ch) {
164 case '\\' :
165 if (!str_escape) {
166 str_escape = TRUE;
167 bp++;
168 continue;
169 }
170 break;
171 case '"' :
172 if (!str_escape) {
173 str_quote = !str_quote;
174 bp++;
175 continue;
176 }
177 break;
178 default :
179 break;
180 }
181
182 if (str_escape) {
183 str_escape = FALSE;
184 } else if (!str_quote && (isspace(ch) || (ch == '#'))) {
185 break;
186 }
187
188 *np++ = ch;
189 bp++;
190 }
191
192 *np = '\0';
193
194 if (name != NULL) {
195 CFRelease(name);
196 name = NULL;
197 }
198
199 if (str_quote) {
200 // the shell won't parse this file so neither will we
201 break;
202 }
203
204 if (strcmp(buf, AUTOMATIC) == 0) {
205 // skip "-AUTOMATIC-"
206 continue;
207 }
208
209 name = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
210 }
211
212 (void) fclose(f);
213 return name;
214 }
215
216
217 static CFStringRef
218 copy_prefs_hostname(SCDynamicStoreRef store)
219 {
220 CFDictionaryRef dict;
221 CFStringRef key;
222 CFStringRef name = NULL;
223
224 key = SCDynamicStoreKeyCreateComputerName(NULL);
225 dict = SCDynamicStoreCopyValue(store, key);
226 CFRelease(key);
227 if (dict == NULL) {
228 goto done;
229 }
230 if (!isA_CFDictionary(dict)) {
231 goto done;
232 }
233
234 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemHostName));
235 if (name == NULL) {
236 goto done;
237 }
238 CFRetain(name);
239
240 done :
241
242 if (dict != NULL) CFRelease(dict);
243
244 return name;
245 }
246
247
248 static CFStringRef
249 copy_primary_service(SCDynamicStoreRef store)
250 {
251 CFDictionaryRef dict;
252 CFStringRef key;
253 CFStringRef serviceID = NULL;
254
255 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
256 kSCDynamicStoreDomainState,
257 kSCEntNetIPv4);
258 dict = SCDynamicStoreCopyValue(store, key);
259 CFRelease(key);
260
261 if (dict != NULL) {
262 if (isA_CFDictionary(dict)) {
263 serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService);
264 if (isA_CFString(serviceID)) {
265 CFRetain(serviceID);
266 } else {
267 serviceID = NULL;
268 }
269 }
270 CFRelease(dict);
271 }
272
273 return serviceID;
274 }
275
276
277 static CFStringRef
278 copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID)
279 {
280 CFDictionaryRef dict;
281 CFStringRef key;
282 CFStringRef address = NULL;
283
284 key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
285 kSCDynamicStoreDomainState,
286 serviceID,
287 kSCEntNetIPv4);
288 dict = SCDynamicStoreCopyValue(store, key);
289 CFRelease(key);
290
291 if (dict != NULL) {
292 if (isA_CFDictionary(dict)) {
293 CFArrayRef addresses;
294
295 addresses = CFDictionaryGetValue(dict, kSCPropNetIPv4Addresses);
296 if (isA_CFArray(addresses) && (CFArrayGetCount(addresses) > 0)) {
297 address = CFArrayGetValueAtIndex(addresses, 0);
298 if (isA_CFString(address)) {
299 CFRetain(address);
300 } else {
301 address = NULL;
302 }
303 }
304 }
305 CFRelease(dict);
306 }
307
308 return address;
309 }
310
311
312 #define DHCP_OPTION_HOSTNAME 12
313
314 static CFStringRef
315 copy_dhcp_name(SCDynamicStoreRef store, CFStringRef serviceID)
316 {
317 CFDictionaryRef info;
318 CFStringRef name = NULL;
319
320 info = SCDynamicStoreCopyDHCPInfo(store, serviceID);
321 if (info != NULL) {
322 CFDataRef data;
323
324 data = DHCPInfoGetOptionData(info, DHCP_OPTION_HOSTNAME);
325 if (data != NULL) {
326 name = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8);
327 }
328
329 CFRelease(info);
330 }
331
332 return name;
333 }
334
335
336 static void
337 reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
338 {
339 struct timeval dnsQueryComplete;
340 struct timeval dnsQueryElapsed;
341 CFStringRef hostname;
342 SCDynamicStoreRef store = (SCDynamicStoreRef)context;
343
344 (void) gettimeofday(&dnsQueryComplete, NULL);
345 timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed);
346 SCLog(_verbose, LOG_INFO,
347 CFSTR("async DNS complete%s (query time = %d.%3.3d)"),
348 ((status == 0) && (host != NULL)) ? "" : ", host not found",
349 dnsQueryElapsed.tv_sec,
350 dnsQueryElapsed.tv_usec / 1000);
351
352 // use reverse DNS name, if available
353
354 switch (status) {
355 case 0 :
356 /*
357 * if [reverse] DNS query was successful
358 */
359 if (host != NULL) {
360 hostname = CFStringCreateWithCString(NULL, host, kCFStringEncodingUTF8);
361 if (hostname != NULL) {
362 SCLog(TRUE, LOG_INFO, CFSTR("hostname (reverse DNS query) = %@"), hostname);
363 set_hostname(hostname);
364 CFRelease(hostname);
365 goto done;
366 }
367 }
368 break;
369
370 case EAI_NONAME :
371 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
372 case EAI_NODATA:
373 #endif
374 /*
375 * if no name available
376 */
377 break;
378
379 default :
380 /*
381 * Hmmmm...
382 */
383 SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo() failed: %s"), gai_strerror(status));
384 }
385
386 // get local (multicast DNS) name, if available
387
388 hostname = SCDynamicStoreCopyLocalHostName(store);
389 if (hostname != NULL) {
390 CFMutableStringRef localName;
391
392 SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
393 localName = CFStringCreateMutableCopy(NULL, 0, hostname);
394 CFStringAppend(localName, CFSTR(".local"));
395 set_hostname(localName);
396 CFRelease(localName);
397 CFRelease(hostname);
398 goto done;
399 }
400
401 // use "localhost" if not other name is available
402
403 set_hostname(CFSTR("localhost"));
404
405 done :
406
407 if (host != NULL) free(host);
408 if (serv != NULL) free(serv);
409 dnsActive = FALSE;
410 return;
411 }
412
413
414 static CFStringRef
415 replyMPCopyDescription(const void *info)
416 {
417 SCDynamicStoreRef store = (SCDynamicStoreRef)info;
418
419 return CFStringCreateWithFormat(NULL,
420 NULL,
421 CFSTR("<getnameinfo_async_start reply MP> {store = %p}"),
422 store);
423 }
424
425
426 static void
427 getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
428 {
429 mach_port_t mp = MACH_PORT_NULL;
430 int32_t status;
431
432 if (port != dnsPort) {
433 // we've received a callback on the async DNS port but since the
434 // associated CFMachPort doesn't match than the request must have
435 // already been cancelled.
436 SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo_async_handleCFReply(): port != dnsPort"));
437 return;
438 }
439
440 mp = CFMachPortGetPort(port);
441 CFMachPortInvalidate(dnsPort);
442 CFRelease(dnsPort);
443 dnsPort = NULL;
444 __MACH_PORT_DEBUG(mp != NULL, "*** set-hostname (after unscheduling)", mp);
445
446 status = getnameinfo_async_handle_reply(msg);
447 __MACH_PORT_DEBUG(mp != NULL, "*** set-hostname (after getnameinfo_async_handle_reply)", mp);
448 if ((status == 0) && dnsActive && (mp != MACH_PORT_NULL)) {
449 CFMachPortContext context = { 0
450 , (void *)store
451 , CFRetain
452 , CFRelease
453 , replyMPCopyDescription
454 };
455 CFRunLoopSourceRef rls;
456
457 // if request has been re-queued
458 dnsPort = CFMachPortCreateWithPort(NULL,
459 mp,
460 getnameinfo_async_handleCFReply,
461 &context,
462 NULL);
463 rls = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0);
464 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
465 CFRelease(rls);
466 __MACH_PORT_DEBUG(mp != NULL, "*** set-hostname (after rescheduling)", mp);
467 }
468
469 return;
470 }
471
472
473 static void
474 start_dns_query(SCDynamicStoreRef store, CFStringRef address)
475 {
476 char addr[64];
477 SCNetworkReachabilityFlags flags;
478 Boolean haveDNS;
479 Boolean ok;
480 struct sockaddr *sa;
481 struct sockaddr_in sin;
482 struct sockaddr_in6 sin6;
483
484 if (_SC_cfstring_to_cstring(address, addr, sizeof(addr), kCFStringEncodingASCII) == NULL) {
485 SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
486 return;
487 }
488
489 bzero(&sin, sizeof(sin));
490 sin.sin_len = sizeof(sin);
491 sin.sin_family = AF_INET;
492
493 bzero(&sin6, sizeof(sin6));
494 sin6.sin6_len = sizeof(sin6);
495 sin6.sin6_family = AF_INET6;
496
497 if (inet_aton(addr, &sin.sin_addr) == 1) {
498 /*
499 * if IPv4 address
500 */
501 sa = (struct sockaddr *)&sin;
502 } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr) == 1) {
503 /*
504 * if IPv6 address
505 */
506 char *p;
507
508 p = strchr(addr, '%');
509 if (p != NULL) {
510 sin6.sin6_scope_id = if_nametoindex(p + 1);
511 }
512
513 sa = (struct sockaddr *)&sin6;
514 } else {
515 goto done;
516 }
517
518
519 ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, sa);
520 if (ok) {
521 if (!(flags & kSCNetworkReachabilityFlagsReachable) ||
522 (flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
523 // if not reachable *OR* connection required
524 ok = FALSE;
525 }
526 }
527
528 if (ok) {
529 CFMachPortContext context = { 0
530 , (void *)store
531 , CFRetain
532 , CFRelease
533 , replyMPCopyDescription
534 };
535 int32_t error;
536 mach_port_t mp;
537 CFRunLoopSourceRef rls;
538
539 (void) gettimeofday(&dnsQueryStart, NULL);
540
541 error = getnameinfo_async_start(&mp,
542 sa,
543 sa->sa_len,
544 NI_NAMEREQD, // flags
545 reverseDNSComplete,
546 NULL);
547 if (error != 0) {
548 goto done;
549 }
550 __MACH_PORT_DEBUG(TRUE, "*** set-hostname (after getnameinfo_async_start)", mp);
551
552 dnsActive = TRUE;
553 dnsPort = CFMachPortCreateWithPort(NULL,
554 mp,
555 getnameinfo_async_handleCFReply,
556 &context,
557 NULL);
558 rls = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0);
559 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
560 CFRelease(rls);
561 __MACH_PORT_DEBUG(TRUE, "*** set-hostname (after scheduling)", mp);
562 }
563
564 done :
565
566 return;
567 }
568
569
570 static void
571 update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
572 {
573 CFStringRef address = NULL;
574 CFStringRef hostname = NULL;
575 CFStringRef serviceID = NULL;
576
577 // if active, cancel any in-progress attempt to resolve the primary IP address
578
579 if (dnsPort != NULL) {
580 mach_port_t mp = CFMachPortGetPort(dnsPort);
581
582 /* cancel the outstanding DNS query */
583 CFMachPortInvalidate(dnsPort);
584 CFRelease(dnsPort);
585 dnsPort = NULL;
586
587 getnameinfo_async_cancel(mp);
588 }
589
590 // get static hostname, if available
591
592 hostname = copy_static_name();
593 if (hostname != NULL) {
594 SCLog(TRUE, LOG_INFO, CFSTR("hostname (static) = %@"), hostname);
595 set_hostname(hostname);
596 goto done;
597 }
598
599 // get [prefs] hostname, if available
600
601 hostname = copy_prefs_hostname(store);
602 if (hostname != NULL) {
603 SCLog(TRUE, LOG_INFO, CFSTR("hostname (prefs) = %@"), hostname);
604 set_hostname(hostname);
605 goto done;
606 }
607
608 // get primary service ID
609
610 serviceID = copy_primary_service(store);
611 if (serviceID == NULL) {
612 goto mDNS;
613 }
614
615 // get DHCP provided name, if available
616
617 hostname = copy_dhcp_name(store, serviceID);
618 if (hostname != NULL) {
619 SCLog(TRUE, LOG_INFO, CFSTR("hostname (DHCP) = %@"), hostname);
620 set_hostname(hostname);
621 goto done;
622 }
623
624 // get DNS name associated with primary IP, if available
625
626 address = copy_primary_ip(store, serviceID);
627 if (address != NULL) {
628 // start reverse DNS query using primary IP address
629 (void) start_dns_query(store, address);
630 goto done;
631 }
632
633 mDNS :
634
635 // get local (multicast DNS) name, if available
636
637 hostname = SCDynamicStoreCopyLocalHostName(store);
638 if (hostname != NULL) {
639 CFMutableStringRef localName;
640
641 SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
642 localName = CFStringCreateMutableCopy(NULL, 0, hostname);
643 CFStringAppend(localName, CFSTR(".local"));
644 set_hostname(localName);
645 CFRelease(localName);
646 goto done;
647 }
648
649 // use "localhost" if not other name is available
650
651 set_hostname(CFSTR("localhost"));
652
653 done :
654
655 if (address) CFRelease(address);
656 if (hostname) CFRelease(hostname);
657 if (serviceID) CFRelease(serviceID);
658
659 return;
660 }
661
662
663 __private_extern__
664 void
665 load_hostname(Boolean verbose)
666 {
667 CFStringRef key;
668 CFMutableArrayRef keys = NULL;
669 CFMutableArrayRef patterns = NULL;
670
671 if (verbose) {
672 _verbose = TRUE;
673 }
674
675 /* initialize a few globals */
676
677 store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), update_hostname, NULL);
678 if (store == NULL) {
679 SCLog(TRUE, LOG_ERR,
680 CFSTR("SCDynamicStoreCreate() failed: %s"),
681 SCErrorString(SCError()));
682 goto error;
683 }
684
685 /* establish notification keys and patterns */
686
687 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
688 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
689
690 /* ...watch for primary service / interface changes */
691 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
692 kSCDynamicStoreDomainState,
693 kSCEntNetIPv4);
694 CFArrayAppendValue(keys, key);
695 CFRelease(key);
696
697 /* ...watch for DNS configuration changes */
698 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
699 kSCDynamicStoreDomainState,
700 kSCEntNetDNS);
701 CFArrayAppendValue(keys, key);
702 CFRelease(key);
703
704 /* ...watch for (per-service) DHCP option changes */
705 key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
706 kSCDynamicStoreDomainState,
707 kSCCompAnyRegex,
708 kSCEntNetDHCP);
709 CFArrayAppendValue(patterns, key);
710 CFRelease(key);
711
712 /* ...watch for (BSD) hostname changes */
713 key = SCDynamicStoreKeyCreateComputerName(NULL);
714 CFArrayAppendValue(keys, key);
715 CFRelease(key);
716
717 /* ...watch for local (multicast DNS) hostname changes */
718 key = SCDynamicStoreKeyCreateHostNames(NULL);
719 CFArrayAppendValue(keys, key);
720 CFRelease(key);
721
722 /* register the keys/patterns */
723 if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
724 SCLog(TRUE, LOG_ERR,
725 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
726 SCErrorString(SCError()));
727 goto error;
728 }
729
730 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
731 if (!rls) {
732 SCLog(TRUE, LOG_ERR,
733 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
734 SCErrorString(SCError()));
735 goto error;
736 }
737 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
738
739 CFRelease(keys);
740 CFRelease(patterns);
741 return;
742
743 error :
744
745 if (keys != NULL) CFRelease(keys);
746 if (patterns != NULL) CFRelease(patterns);
747 if (store != NULL) CFRelease(store);
748 return;
749 }
750
751
752 #ifdef MAIN
753 int
754 main(int argc, char **argv)
755 {
756
757 #ifdef DEBUG
758
759 _sc_log = FALSE;
760 if ((argc > 1) && (strcmp(argv[1], "-d") == 0)) {
761 _sc_verbose = TRUE;
762 argv++;
763 argc--;
764 }
765
766 CFStringRef address;
767 CFStringRef hostname;
768 CFStringRef serviceID;
769 SCDynamicStoreRef store;
770
771 store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), NULL, NULL);
772 if (store == NULL) {
773 SCPrint(TRUE, stdout,
774 CFSTR("SCDynamicStoreCreate() failed: %s\n"),
775 SCErrorString(SCError()));
776 exit(1);
777 }
778
779 // get static hostname
780 hostname = copy_static_name();
781 if (hostname != NULL) {
782 SCPrint(TRUE, stdout, CFSTR("hostname (static) = %@\n"), hostname);
783 CFRelease(hostname);
784 }
785
786 // get [prefs] hostname, if available
787 hostname = copy_prefs_hostname(store);
788 if (hostname != NULL) {
789 SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname);
790 CFRelease(hostname);
791 }
792
793 // get primary service
794 serviceID = copy_primary_service(store);
795 if (serviceID != NULL) {
796 SCPrint(TRUE, stdout, CFSTR("primary service ID = %@\n"), serviceID);
797 } else {
798 SCPrint(TRUE, stdout, CFSTR("No primary service\n"));
799 goto mDNS;
800 }
801
802 if ((argc == (2+1)) && (argv[1][0] == 's')) {
803 if (serviceID != NULL) CFRelease(serviceID);
804 serviceID = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
805 SCPrint(TRUE, stdout, CFSTR("alternate service ID = %@\n"), serviceID);
806 }
807
808 // get DHCP provided name
809 hostname = copy_dhcp_name(store, serviceID);
810 if (hostname != NULL) {
811 SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname);
812 CFRelease(hostname);
813 }
814
815 // get primary IP address
816 address = copy_primary_ip(store, serviceID);
817 if (address != NULL) {
818 SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address);
819
820 if ((argc == (2+1)) && (argv[1][0] == 'a')) {
821 if (address != NULL) CFRelease(address);
822 address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
823 SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address);
824 }
825
826 // start reverse DNS query using primary IP address
827 start_dns_query(store, address);
828 CFRelease(address);
829 }
830
831 CFRelease(serviceID);
832
833 mDNS :
834
835 // get local (multicast DNS) name, if available
836
837 hostname = SCDynamicStoreCopyLocalHostName(store);
838 if (hostname != NULL) {
839 CFMutableStringRef localName;
840
841 SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname);
842 localName = CFStringCreateMutableCopy(NULL, 0, hostname);
843 CFStringAppend(localName, CFSTR(".local"));
844 CFRelease(localName);
845 }
846
847 if (hostname != NULL) CFRelease(hostname);
848
849 update_hostname(store, NULL, NULL);
850
851 CFRelease(store);
852
853 CFRunLoopRun();
854
855 #else /* DEBUG */
856
857 _sc_log = FALSE;
858 _sc_verbose = (argc > 1) ? TRUE : FALSE;
859
860 load_hostname((argc > 1) ? TRUE : FALSE);
861 CFRunLoopRun();
862 /* not reached */
863
864 #endif /* DEBUG */
865
866 exit(0);
867 return 0;
868 }
869 #endif /* MAIN */