/*
- * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2020 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#if !TARGET_OS_IPHONE
-#include <notify.h>
-extern uint32_t notify_monitor_file(int token, const char *name, int flags);
-#endif // !TARGET_OS_IPHONE
#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CoreFoundation.h>
#include <dns_sd.h>
#include <dns_sd_private.h>
+#if !TARGET_OS_IPHONE
+#include <CoreServices/CoreServices.h>
+#else // TARGET_OS_IPHONE
+#include <FSEvents/FSEvents.h>
+#endif // TARGET_OS_IPHONE
+
#define DNS_CONFIGURATION_FLAGS_KEY CFSTR("__FLAGS__")
#define DNS_CONFIGURATION_IF_INDEX_KEY CFSTR("__IF_INDEX__")
#define DNS_CONFIGURATION_ORDER_KEY CFSTR("__ORDER__")
// check if the service has v4 configured
if (((resolver_flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS) == 0) &&
- service_contains_protocol(service, AF_INET)) {
+ service_is_routable(service, AF_INET)) {
resolver_flags |= DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS;
}
// check if the service has v6 configured
if (((resolver_flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS) == 0) &&
- service_contains_protocol(service, AF_INET6)) {
+ service_is_routable(service, AF_INET6)) {
resolver_flags |= DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS;
}
*slash = '\0';
}
- bzero(&sortaddr, sizeof(sortaddr));
+ memset(&sortaddr, 0, sizeof(sortaddr));
if (inet_aton(buf, &sortaddr.address) != 1) {
/* if address not valid */
continue;
CFDictionaryRef services,
CFArrayRef serviceOrder,
CFArrayRef multicastResolvers,
- CFArrayRef privateResolvers)
+ CFArrayRef privateResolvers,
+ CFDictionaryRef *globalResolver)
{
dns_create_config_t dns_create_config;
Boolean changed = FALSE;
CFArrayRef mySearchDomains = NULL;
CFIndex n_resolvers;
CFMutableArrayRef resolvers;
- unsigned char signature[CC_SHA1_DIGEST_LENGTH];
- static unsigned char signature_last[CC_SHA1_DIGEST_LENGTH];
+ unsigned char signature[CC_SHA256_DIGEST_LENGTH];
+ static unsigned char signature_last[CC_SHA256_DIGEST_LENGTH];
// establish list of resolvers
resolver = new_resolver;
}
+ if (i == 0) {
+ *globalResolver = CFRetain(resolver);
+ }
+
_resolver = create_resolver(resolver);
_dns_configuration_add_resolver(&dns_create_config, _resolver);
_dns_resolver_free(&_resolver);
}
}
-#if !TARGET_OS_IPHONE
// add flatfile resolvers
_dnsinfo_flatfile_set_flags(default_resolver_flags);
_dnsinfo_flatfile_add_resolvers(&dns_create_config);
-#endif // !TARGET_OS_IPHONE
}
// check if the configuration changed
_dns_configuration_signature(&dns_create_config, signature, sizeof(signature));
if (bcmp(signature, signature_last, sizeof(signature)) != 0) {
// save [new] signature
- bcopy(signature, signature_last, sizeof(signature));
+ memcpy(signature_last, signature, sizeof(signature));
my_log(LOG_INFO, "Updating DNS configuration");
if (dns_create_config != NULL) {
}
-#if !TARGET_OS_IPHONE
static SCDynamicStoreRef dns_configuration_store;
static SCDynamicStoreCallBack dns_configuration_callout;
static void
-dns_configuration_changed(CFMachPortRef port, void *msg, CFIndex size, void *info)
+dns_configuration_changed(ConstFSEventStreamRef streamRef,
+ void *clientCallBackInfo,
+ size_t numEvents,
+ void *eventPaths,
+ const FSEventStreamEventFlags *eventFlags,
+ const FSEventStreamEventId *eventIds)
{
-#pragma unused(port)
-#pragma unused(msg)
-#pragma unused(size)
-#pragma unused(info)
- os_activity_t activity;
+#pragma unused(streamRef)
+#pragma unused(clientCallBackInfo)
+#pragma unused(numEvents)
+#pragma unused(eventPaths)
+#pragma unused(eventFlags)
+#pragma unused(eventIds)
static const CFStringRef key = CFSTR(_PATH_RESOLVER_DIR);
CFArrayRef keys;
Boolean resolvers_now;
static Boolean resolvers_save = FALSE;
struct stat statbuf;
- activity = os_activity_create("processing DNS configuration change",
- OS_ACTIVITY_CURRENT,
- OS_ACTIVITY_FLAG_DEFAULT);
- os_activity_scope(activity);
-
resolvers_now = (stat(_PATH_RESOLVER_DIR, &statbuf) == 0);
if (!resolvers_save && (resolvers_save == resolvers_now)) {
// if we did not (and still do not) have an "/etc/resolvers"
// directory than this notification is the result of a change
// to the "/etc" directory.
- goto done;
+ return;
}
resolvers_save = resolvers_now;
(*dns_configuration_callout)(dns_configuration_store, keys, NULL);
CFRelease(keys);
- done :
+ return;
+}
- os_release(activity);
- return;
+static Boolean
+normalize_path(const char *file_name, char resolved_name[PATH_MAX])
+{
+ char *ch;
+ char path[PATH_MAX];
+
+ strlcpy(path, file_name, sizeof(path));
+ if (realpath(path, resolved_name) != NULL) {
+ // if the path exists
+ return TRUE;
+ }
+
+ ch = strrchr(path, '/');
+ if (ch != NULL) {
+ *ch = '\0';
+ if (realpath(path, resolved_name) != NULL) {
+ // if a parent path exists
+ strlcat(resolved_name, "/", PATH_MAX);
+ strlcat(resolved_name, ch+1, PATH_MAX);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
void
dns_configuration_monitor(SCDynamicStoreRef store, SCDynamicStoreCallBack callout)
{
- CFMachPortRef mp;
- mach_port_t notify_port;
- int notify_token;
- CFRunLoopSourceRef rls;
- uint32_t status;
+ FSEventStreamContext context = { 0, // version
+ NULL, // info
+ NULL, // retain
+ NULL, // release
+ NULL }; // copyDescription
+ FSEventStreamCreateFlags flags = kFSEventStreamCreateFlagUseCFTypes
+ | kFSEventStreamCreateFlagFileEvents
+ | kFSEventStreamCreateFlagWatchRoot;
+ FSEventStreamRef monitor;
+ CFStringRef path;
+ CFMutableArrayRef paths;
+ char resolver_directory_path[PATH_MAX];
+
+ if (!normalize_path(_PATH_RESOLVER_DIR, resolver_directory_path)) {
+ my_log(LOG_ERR, "Not monitoring \"%s\", could not resolve directory path", _PATH_RESOLVER_DIR);
+ return;
+ }
dns_configuration_store = store;
dns_configuration_callout = callout;
- status = notify_register_mach_port(_PATH_RESOLVER_DIR, ¬ify_port, 0, ¬ify_token);
- if (status != NOTIFY_STATUS_OK) {
- my_log(LOG_ERR, "notify_register_mach_port() failed");
- return;
- }
+ paths = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ path = CFStringCreateWithCString(NULL, resolver_directory_path, kCFStringEncodingUTF8);
+ CFArrayAppendValue(paths, path);
+ CFRelease(path);
- status = notify_monitor_file(notify_token, "/private" _PATH_RESOLVER_DIR, 0);
- if (status != NOTIFY_STATUS_OK) {
- my_log(LOG_ERR, "notify_monitor_file() failed");
- (void)notify_cancel(notify_token);
- return;
- }
+ monitor = FSEventStreamCreate(NULL, // allocator
+ dns_configuration_changed, // callback
+ &context, // context
+ paths, // pathsToWatch (CFArray)
+ kFSEventStreamEventIdSinceNow, // sinceWhen
+ 0.0, // latency
+ flags); // flags
- mp = _SC_CFMachPortCreateWithPort("IPMonitor/dns_configuration",
- notify_port,
- dns_configuration_changed,
- NULL);
+ CFRelease(paths);
- rls = CFMachPortCreateRunLoopSource(NULL, mp, -1);
- if (rls == NULL) {
- my_log(LOG_ERR, "SCDynamicStoreCreateRunLoopSource() failed");
- CFRelease(mp);
- (void)notify_cancel(notify_token);
- return;
- }
- CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
- CFRelease(rls);
+ FSEventStreamScheduleWithRunLoop(monitor, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ FSEventStreamStart(monitor);
- CFRelease(mp);
return;
}
-#endif // !TARGET_OS_IPHONE
__private_extern__
main(int argc, char **argv)
{
CFDictionaryRef entities;
+ CFDictionaryRef globalResolver = NULL;
CFStringRef key;
CFArrayRef multicast_resolvers;
CFStringRef pattern;
SCDynamicStoreRef store;
_sc_debug = TRUE;
- _sc_log = FALSE;
+ _sc_log = kSCLogDestinationFile;
_sc_verbose = (argc > 1) ? TRUE : FALSE;
store = SCDynamicStoreCreate(NULL, CFSTR("TEST"), NULL, NULL);
service_state_dict,
service_order,
multicast_resolvers,
- private_resolvers);
+ private_resolvers,
+ &globalResolver);
// cleanup
if (setup_global_ipv4 != NULL) CFRelease(setup_global_ipv4);
if (state_global_ipv4 != NULL) CFRelease(state_global_ipv4);
if (multicast_resolvers != NULL) CFRelease(multicast_resolvers);
if (private_resolvers != NULL) CFRelease(private_resolvers);
+ if (globalResolver != NULL) CFRelease(globalResolver);
CFRelease(service_state_dict);
CFRelease(store);