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