/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009, 2011, 2012, 2014 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <net/if.h>
#include <sys/dir.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <unistd.h>
#include "dnsinfo.h"
#include "dnsinfo_private.h"
#include "dnsinfo_create.h"
+static uint32_t _dnsinfo_flatfile_flags;
+
enum {
+ TOKEN_DOMAIN,
+ TOKEN_FLAGS,
+ TOKEN_INTERFACE,
TOKEN_NAMESERVER,
+ TOKEN_OPTIONS,
TOKEN_PORT,
- TOKEN_DOMAIN,
TOKEN_SEARCH,
TOKEN_SEARCH_ORDER,
TOKEN_SORTLIST,
TOKEN_TIMEOUT,
- TOKEN_OPTIONS,
TOKEN_MAX
};
int token;
int max_count;
} tokens [] = {
+ { "domain", TOKEN_DOMAIN, 1 },
+ { "flags", TOKEN_FLAGS, 1 },
+ { "interface", TOKEN_INTERFACE, 1 },
{ "nameserver", TOKEN_NAMESERVER, MAXNS },
+ { "options", TOKEN_OPTIONS, 1 },
{ "port", TOKEN_PORT, 1 },
- { "domain", TOKEN_DOMAIN, 1 },
{ "search", TOKEN_SEARCH, 1 },
{ "search_order", TOKEN_SEARCH_ORDER, 1 },
{ "sortlist", TOKEN_SORTLIST, 1 },
{ "timeout", TOKEN_TIMEOUT, 1 },
- { "options", TOKEN_OPTIONS, 1 },
};
switch (sa->sa_family) {
case AF_INET :
- ((struct sockaddr_in *)sa)->sin_port = port;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ ((struct sockaddr_in *)(void *)sa)->sin_port = port;
break;
case AF_INET6 :
- ((struct sockaddr_in6 *)sa)->sin6_port = port;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ ((struct sockaddr_in6 *)(void *)sa)->sin6_port = port;
break;
}
}
// if not AF_INET
goto done;
} else {
- addr = ((struct sockaddr_in *)sa)->sin_addr;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ addr = ((struct sockaddr_in *)(void *)sa)->sin_addr;
free(sa);
sa = NULL;
}
// if mask not AF_INET
goto done;
} else {
- mask = ((struct sockaddr_in *)sa)->sin_addr;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ mask = ((struct sockaddr_in *)(void *)sa)->sin_addr;
free(sa);
sa = NULL;
}
}
+/*
+ * _dnsinfo_flatfile_set_flags
+ *
+ * Set the default resolver flags.
+ */
+__private_extern__
+void
+_dnsinfo_flatfile_set_flags(uint32_t flags)
+{
+ _dnsinfo_flatfile_flags = flags;
+ return;
+}
+
+
+static void
+_dnsinfo_flatfile_update_flags(dns_create_resolver_t *_resolver)
+{
+ uint32_t new_flags;
+ uint32_t old_flags;
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ old_flags = ntohl(resolver->resolver.flags);
+ new_flags = old_flags | _dnsinfo_flatfile_flags;
+ _dns_resolver_set_flags(_resolver, new_flags);
+ return;
+}
+
+
/*
* _dnsinfo_flatfile_create_resolver
*
_dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
{
char *buf;
+ uint32_t config_flags = 0;
FILE *f;
char filename[FILENAME_MAX];
size_t len = 0;
}
switch (token) {
- case TOKEN_DOMAIN:
- _dns_resolver_set_domain(&res, word);
+ case TOKEN_DOMAIN: {
+ size_t len;
+
+ len = strlen(word);
+ while ((len > 0) && (word[len - 1] == '.')) {
+ // trim trailing '.'
+ word[--len] = '\0';
+ }
+ if (len > 0) {
+ _dns_resolver_set_domain(&res, word);
+ }
+ break;
+ }
+
+ case TOKEN_FLAGS: {
+ while (word != NULL) {
+ if (word[0] != '\0') {
+ if (strcasecmp(word, "scoped") == 0) {
+ config_flags |= DNS_RESOLVER_FLAGS_SCOPED;
+ } else if (strcasecmp(word, "a") == 0) {
+ config_flags |= DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS;
+ } else if (strcasecmp(word, "aaaa") == 0) {
+ config_flags |= DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS;
+ }
+ }
+ word = strsep(&lineptr, sep);
+ }
+ break;
+ }
+
+ case TOKEN_INTERFACE: {
+ unsigned int if_index;
+
+ if_index = if_nametoindex(word);
+ if (if_index > 0) {
+ _dns_resolver_set_if_index(&res, if_index);
+ }
break;
+ }
case TOKEN_NAMESERVER: {
struct sockaddr *sa;
break;
}
+ case TOKEN_OPTIONS: {
+ char *options = NULL;
+
+ while (word != NULL) {
+ if (word[0] != '\0') {
+ if (options == NULL) {
+ options = malloc(len+1);
+ if (options == NULL) break;
+
+ strlcpy(options, word, len+1);
+ } else {
+ strlcat(options, " ", len+1);
+ strlcat(options, word, len+1);
+ }
+ }
+ word = strsep(&lineptr, sep);
+ }
+
+ if (options != NULL) {
+ _dns_resolver_set_options(&res, options);
+ free(options);
+ }
+ break;
+ }
+
case TOKEN_PORT: {
long number = -1;
// multiple search domains are supported
while ((word != NULL) && (n++ < MAXDNSRCH)) {
- _dns_resolver_add_search(&res, word);
+ size_t len;
+
+ len = strlen(word);
+ while ((len > 0) && (word[len - 1] == '.')) {
+ // trim trailing '.'
+ word[--len] = '\0';
+ }
+ if (len > 0) {
+ _dns_resolver_add_search(&res, word);
+ }
word = strsep(&lineptr, sep);
}
break;
}
+ case TOKEN_SEARCH_ORDER: {
+ long number = -1;
+
+ number = strtol(word, NULL, 0);
+ if (number < 0 || number > UINT32_MAX) break;
+ _dns_resolver_set_order(&res, (uint32_t)number);
+ break;
+ }
+
case TOKEN_SORTLIST: {
int n = 0;
break;
}
- case TOKEN_OPTIONS:
- _dns_resolver_set_options(&res, lineptr);
- break;
-
case TOKEN_TIMEOUT: {
long number = -1;
number = strtol(word, NULL, 0);
if (number < 0 || number > UINT32_MAX) break;
- _dns_resolver_set_timeout(&res, number);
- break;
- }
-
- case TOKEN_SEARCH_ORDER: {
- long number = -1;
-
- number = strtol(word, NULL, 0);
- if (number < 0 || number > UINT32_MAX) break;
- _dns_resolver_set_order(&res, number);
+ _dns_resolver_set_timeout(&res, (uint32_t)number);
break;
}
}
_dns_resolver_set_domain(&res, domain);
}
+ if (res != NULL) {
+ // config flags should overwrite any default flags
+ if (config_flags != 0) {
+ _dns_resolver_set_flags(&res, config_flags);
+ } else {
+ _dnsinfo_flatfile_update_flags(&res);
+ }
+ }
+
done :
fclose(f);
* Parse the files in the resolver config directory (/etc/resolver) and add each
* resolver to the dns config.
*/
+__private_extern__
void
_dnsinfo_flatfile_add_resolvers(dns_create_config_t *config)
{
}
-#ifdef MAIN
+#ifdef MAIN
+#undef MAIN
#include "dnsinfo_copy.c"
return 0;
}
+
#endif