configd-699.1.5.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_flatfile.c
index 378be841b2a48339f5ab3d08b70b51b3d457a1d3..a52be6b9544db0eeed276d7820373980cf5224cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
 };
 
@@ -57,14 +64,16 @@ static const struct {
        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       },
 };
 
 
@@ -136,10 +145,12 @@ _dnsinfo_parse_nameserver(char *token)
 
                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;
                }
        }
@@ -175,7 +186,8 @@ _dnsinfo_parse_sortaddr(char *token)
                // 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;
        }
@@ -189,7 +201,8 @@ _dnsinfo_parse_sortaddr(char *token)
                        // 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;
                }
@@ -222,6 +235,34 @@ _dnsinfo_parse_sortaddr(char *token)
 }
 
 
+/*
+ * _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
  *
@@ -232,6 +273,7 @@ static dns_create_resolver_t
 _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;
@@ -313,9 +355,45 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                }
 
                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;
@@ -328,6 +406,31 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                                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;
 
@@ -342,12 +445,30 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
 
                                // 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;
 
@@ -363,25 +484,12 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                                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;
                        }
                }
@@ -401,6 +509,15 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                _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);
@@ -414,6 +531,7 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
  * 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)
 {
@@ -442,7 +560,8 @@ _dnsinfo_flatfile_add_resolvers(dns_create_config_t *config)
 }
 
 
-#ifdef MAIN
+#ifdef MAIN
+#undef MAIN
 
 #include "dnsinfo_copy.c"
 
@@ -472,4 +591,5 @@ main(int argc, char **argv)
 
        return 0;
 }
+
 #endif