]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Add support for passing DDNS information to a DNS server over
authorShawn Routhier <sar@isc.org>
Wed, 21 Sep 2011 20:43:10 +0000 (20:43 +0000)
committerShawn Routhier <sar@isc.org>
Wed, 21 Sep 2011 20:43:10 +0000 (20:43 +0000)
an IPv6 address.  [ISC-Bugs #22647]

RELNOTES
common/conflex.c
common/dns.c
common/parse.c
includes/dhcpd.h
includes/dhctoken.h
server/dhcpd.conf.5

index 211d6062e5967b2a7f1ee4f2da036f90448c649c..69a0486e2354ffcc36c7e7d53e6c7b121dfd3304 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -49,6 +49,9 @@ work on other platforms. Please report any problems and suggested fixes to
 - Add AM_MAINTAINER_MODE to configure.ac to avoid rebuilding
   configuration files.  [ISC-Bugs #24107]
 
+- Add support for passing DDNS information to a DNS server over
+  an IPv6 address.  [ISC-Bugs #22647]
+
                        Changes since 4.2.2rc1
 
 ! Two packets were found that cause a server to halt.  The code
index 1ec2328189eb0a641b18e8d2595a1e98d4f016b8..9c9ed66ab5699979bd880abfd262b3ca7bd2821a 100644 (file)
@@ -1228,6 +1228,8 @@ intern(char *atom, enum dhcp_token dfv) {
                        return PEER;
                if (!strcasecmp (atom + 1, "rimary"))
                        return PRIMARY;
+               if (!strcasecmp (atom + 1, "rimary6"))
+                       return PRIMARY6;
                if (!strncasecmp (atom + 1, "artner", 6)) {
                        if (!atom [7])
                                return PARTNER;
@@ -1317,7 +1319,9 @@ intern(char *atom, enum dhcp_token dfv) {
                            tolower((unsigned char)atom[2]) == 'c') {
                                if (!strncasecmp(atom + 3, "ond", 3)) {
                                         if (!strcasecmp(atom + 6, "ary"))
-                                                return SECONDARY;
+                                               return SECONDARY;
+                                        if (!strcasecmp(atom + 6, "ary6"))
+                                               return SECONDARY6;
                                         if (!strcasecmp(atom + 6, "s"))
                                                 return SECONDS;
                                        break;
index 5ecae67259072cc05a669475e5d2b468cba65c80..3992b6c4347347d84790955797d1d3c7fbe5305f 100644 (file)
  * support update forwarding, AFAIK).   If no TSIG key is listed, the update
  * is attempted without TSIG.
  *
+ * You can also include IPv6 addresses via the primary6 and secondary6
+ * options.  The search order for the addresses is primary, primary6,
+ * secondary and lastly secondary6, with a limit on the number of 
+ * addresses used.  Currently this limit is 3.
+ *
  * The DHCP server tries to find an existing zone for any given name by
  * trying to look up a local zone structure for each domain containing
  * that name, all the way up to '.'.   If it finds one cached, it tries
@@ -602,44 +607,48 @@ int dns_zone_dereference (ptr, file, line)
 {
        struct dns_zone *dns_zone;
 
-       if (!ptr || !*ptr) {
-               log_error ("%s(%d): null pointer", file, line);
+       if ((ptr == NULL) || (*ptr == NULL)) {
+               log_error("%s(%d): null pointer", file, line);
 #if defined (POINTER_DEBUG)
-               abort ();
+               abort();
 #else
-               return 0;
+               return (0);
 #endif
        }
 
        dns_zone = *ptr;
-       *ptr = (struct dns_zone *)0;
-       --dns_zone -> refcnt;
-       rc_register (file, line, ptr, dns_zone, dns_zone -> refcnt, 1, RC_MISC);
-       if (dns_zone -> refcnt > 0)
-               return 1;
-
-       if (dns_zone -> refcnt < 0) {
-               log_error ("%s(%d): negative refcnt!", file, line);
+       *ptr = NULL;
+       --dns_zone->refcnt;
+       rc_register(file, line, ptr, dns_zone, dns_zone->refcnt, 1, RC_MISC);
+       if (dns_zone->refcnt > 0)
+               return (1);
+
+       if (dns_zone->refcnt < 0) {
+               log_error("%s(%d): negative refcnt!", file, line);
 #if defined (DEBUG_RC_HISTORY)
-               dump_rc_history (dns_zone);
+               dump_rc_history(dns_zone);
 #endif
 #if defined (POINTER_DEBUG)
-               abort ();
+               abort();
 #else
-               return 0;
+               return (0);
 #endif
        }
 
-       if (dns_zone -> name)
-               dfree (dns_zone -> name, file, line);
-       if (dns_zone -> key)
-               omapi_auth_key_dereference (&dns_zone -> key, file, line);
-       if (dns_zone -> primary)
-               option_cache_dereference (&dns_zone -> primary, file, line);
-       if (dns_zone -> secondary)
-               option_cache_dereference (&dns_zone -> secondary, file, line);
-       dfree (dns_zone, file, line);
-       return 1;
+       if (dns_zone->name)
+               dfree(dns_zone->name, file, line);
+       if (dns_zone->key)
+               omapi_auth_key_dereference(&dns_zone->key, file, line);
+       if (dns_zone->primary)
+               option_cache_dereference(&dns_zone->primary, file, line);
+       if (dns_zone->secondary)
+               option_cache_dereference(&dns_zone->secondary, file, line);
+       if (dns_zone->primary6)
+               option_cache_dereference(&dns_zone->primary6, file, line);
+       if (dns_zone->secondary6)
+               option_cache_dereference(&dns_zone->secondary6, file, line);
+       dfree(dns_zone, file, line);
+       return (1);
 }
 
 #if defined (NSUPDATE)
@@ -648,9 +657,10 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
 {
        isc_result_t status = ISC_R_NOTFOUND;
        const char *np;
-       struct dns_zone *zone = (struct dns_zone *)0;
+       struct dns_zone *zone = NULL;
        struct data_string nsaddrs;
        struct in_addr zone_addr;
+       struct in6_addr zone_addr6;
        int ix;
 
        if (direction == FIND_FORWARD) {
@@ -661,14 +671,14 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
 
        /* We can't look up a null zone. */
        if ((np == NULL) || (*np == '\0')) {
-               return DHCP_R_INVALIDARG;
+               return (DHCP_R_INVALIDARG);
        }
 
        /*
         * For each subzone, try to find a cached zone.
         */
        for (;;) {
-               status = dns_zone_lookup (&zone, np);
+               status = dns_zone_lookup(&zone, np);
                if (status == ISC_R_SUCCESS)
                        break;
 
@@ -679,32 +689,28 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
        }
 
        if (status != ISC_R_SUCCESS)
-               return status;
+               return (status);
 
        /* Make sure the zone is valid. */
-       if (zone -> timeout && zone -> timeout < cur_time) {
-               dns_zone_dereference (&zone, MDL);
-               return ISC_R_CANCELED;
+       if (zone->timeout && zone->timeout < cur_time) {
+               dns_zone_dereference(&zone, MDL);
+               return (ISC_R_CANCELED);
        }
 
        /* Make sure the zone name will fit. */
        if (strlen(zone->name) > sizeof(ddns_cb->zone_name)) {
-               dns_zone_dereference (&zone, MDL);
-               return ISC_R_NOSPACE;
+               dns_zone_dereference(&zone, MDL);
+               return (ISC_R_NOSPACE);
        }
        strcpy((char *)&ddns_cb->zone_name[0], zone->name);
 
        memset (&nsaddrs, 0, sizeof nsaddrs);
        ix = 0;
 
-       if (zone -> primary) {
-               if (evaluate_option_cache (&nsaddrs, (struct packet *)0,
-                                          (struct lease *)0,
-                                          (struct client_state *)0,
-                                          (struct option_state *)0,
-                                          (struct option_state *)0,
-                                          &global_scope,
-                                          zone -> primary, MDL)) {
+       if (zone->primary) {
+               if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
+                                         NULL, NULL, &global_scope,
+                                         zone->primary, MDL)) {
                        int ip = 0;
                        while (ix < DHCP_MAXNS) {
                                if (ip + 4 > nsaddrs.len)
@@ -719,17 +725,36 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
                                ip += 4;
                                ix++;
                        }
-                       data_string_forget (&nsaddrs, MDL);
+                       data_string_forget(&nsaddrs, MDL);
+               }
+       }
+
+       if (zone->primary6) {
+               if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
+                                         NULL, NULL, &global_scope,
+                                         zone->primary6, MDL)) {
+                       int ip = 0;
+                       while (ix < DHCP_MAXNS) {
+                               if (ip + 16 > nsaddrs.len)
+                                       break;
+                               memcpy(&zone_addr6, &nsaddrs.data[ip], 16);
+                               isc_sockaddr_fromin6(&ddns_cb->zone_addrs[ix],
+                                                   &zone_addr6,
+                                                   NS_DEFAULTPORT);
+                               ISC_LIST_APPEND(ddns_cb->zone_server_list,
+                                               &ddns_cb->zone_addrs[ix],
+                                               link);
+                               ip += 16;
+                               ix++;
+                       }
+                       data_string_forget(&nsaddrs, MDL);
                }
        }
-       if (zone -> secondary) {
-               if (evaluate_option_cache (&nsaddrs, (struct packet *)0,
-                                          (struct lease *)0,
-                                          (struct client_state *)0,
-                                          (struct option_state *)0,
-                                          (struct option_state *)0,
-                                          &global_scope,
-                                          zone -> secondary, MDL)) {
+
+       if (zone->secondary) {
+               if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
+                                         NULL, NULL, &global_scope,
+                                         zone->secondary, MDL)) {
                        int ip = 0;
                        while (ix < DHCP_MAXNS) {
                                if (ip + 4 > nsaddrs.len)
@@ -748,6 +773,28 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
                }
        }
 
+       if (zone->secondary6) {
+               if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
+                                         NULL, NULL, &global_scope,
+                                         zone->secondary6, MDL)) {
+                       int ip = 0;
+                       while (ix < DHCP_MAXNS) {
+                               if (ip + 16 > nsaddrs.len)
+                                       break;
+                               memcpy(&zone_addr6, &nsaddrs.data[ip], 16);
+                               isc_sockaddr_fromin6(&ddns_cb->zone_addrs[ix],
+                                                   &zone_addr6,
+                                                   NS_DEFAULTPORT);
+                               ISC_LIST_APPEND(ddns_cb->zone_server_list,
+                                               &ddns_cb->zone_addrs[ix],
+                                               link);
+                               ip += 16;
+                               ix++;
+                       }
+                       data_string_forget (&nsaddrs, MDL);
+               }
+       }
+
        dns_zone_reference(&ddns_cb->zone, zone, MDL);
        dns_zone_dereference (&zone, MDL);
        return ISC_R_SUCCESS;
index 049ce7b57446cc8cbe1d99d1bdae345d2cf1754a..61488c15994b65d90e1825ff1e9f362fabef8239 100644 (file)
@@ -2698,6 +2698,8 @@ int parse_executable_statement (result, cfile, lose, case_context)
    zone-statement :==
        PRIMARY ip-addresses SEMI |
        SECONDARY ip-addresses SEMI |
+       PRIMARY6 ip-address6 SEMI |
+       SECONDARY6 ip-address6 SEMI |
        key-reference SEMI
    ip-addresses :== ip-addr-or-hostname |
                  ip-addr-or-hostname COMMA ip-addresses
@@ -2779,6 +2781,61 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile)
                    }
                    break;
 
+                 case PRIMARY6:
+                   if (zone->primary6) {
+                           parse_warn(cfile, "more than one primary6.");
+                           skip_to_semi(cfile);
+                           return (0);
+                   }
+                   if (!option_cache_allocate (&zone->primary6, MDL))
+                           log_fatal("can't allocate primary6 option cache.");
+                   oc = zone->primary6;
+                   goto consemup6;
+
+                 case SECONDARY6:
+                   if (zone->secondary6) {
+                           parse_warn(cfile, "more than one secondary6.");
+                           skip_to_semi(cfile);
+                           return (0);
+                   }
+                   if (!option_cache_allocate (&zone->secondary6, MDL))
+                           log_fatal("can't allocate secondary6 "
+                                     "option cache.");
+                   oc = zone->secondary6;
+                 consemup6:
+                   token = next_token(&val, NULL, cfile);
+                   do {
+                           struct expression *expr = NULL;
+                           if (parse_ip6_addr_expr(&expr, cfile) == 0) {
+                                   parse_warn(cfile, "expecting IPv6 addr.");
+                                   skip_to_semi(cfile);
+                                   return (0);
+                           }
+                           if (oc->expression) {
+                                   struct expression *old = NULL;
+                                   expression_reference(&old, oc->expression,
+                                                        MDL);
+                                   expression_dereference(&oc->expression,
+                                                          MDL);
+                                   if (!make_concat(&oc->expression,
+                                                    old, expr))
+                                           log_fatal("no memory for concat.");
+                                   expression_dereference(&expr, MDL);
+                                   expression_dereference(&old, MDL);
+                           } else {
+                                   expression_reference(&oc->expression,
+                                                        expr, MDL);
+                                   expression_dereference(&expr, MDL);
+                           }
+                           token = next_token(&val, NULL, cfile);
+                   } while (token == COMMA);
+                   if (token != SEMI) {
+                           parse_warn(cfile, "expecting semicolon.");
+                           skip_to_semi(cfile);
+                           return (0);
+                   }
+                   break;
+
                  case KEY:
                    token = next_token (&val, (unsigned *)0, cfile);
                    token = peek_token (&val, (unsigned *)0, cfile);
index 99d438763c354f3324fe0bba9a513c7ed81a1512..0a152e3d0c6562fdfa76bcdb04397cf28d9ddfbc 100644 (file)
@@ -1374,6 +1374,8 @@ struct dns_zone {
        char *name;
        struct option_cache *primary;
        struct option_cache *secondary;
+       struct option_cache *primary6;
+       struct option_cache *secondary6;
        struct auth_key *key;
 };
 
index dc28f39fbfd12f8d6810065d3ca5a941c9d7ba2c..9911d70f8ea02f3666e66876df03a33390f02c7c 100644 (file)
@@ -361,7 +361,9 @@ enum dhcp_token {
        GETHOSTNAME = 662,
        REWIND = 663,
        INITIAL_DELAY = 664,
-       GETHOSTBYNAME = 665
+       GETHOSTBYNAME = 665,
+       PRIMARY6 = 666,
+       SECONDARY6 = 667
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index d94b878e064d795984fd18894bfc89c861144987..0373be759c1678b42d5fb018345882434f45b249 100644 (file)
@@ -27,7 +27,7 @@
 .\" Support and other services are available for ISC products - see
 .\" https://www.isc.org for more information or to learn more about ISC.
 .\"
-.\" $Id: dhcpd.conf.5,v 1.106.18.6 2011/06/01 23:30:53 sar Exp $
+.\" $Id: dhcpd.conf.5,v 1.106.18.7 2011/09/21 20:43:10 sar Exp $
 .\"
 .TH dhcpd.conf 5
 .SH NAME
@@ -1357,7 +1357,14 @@ zone 17.127.10.in-addr.arpa. {
 .fi
 .PP
 The \fIprimary\fR statement specifies the IP address of the name
-server whose zone information is to be updated.
+server whose zone information is to be updated.  In addition to
+the \fIprimary\fR statement there are also the \fIprimary6\fR ,
+\fIsecondary\fR and \fIsecondary6\fR statements.  The \fIprimary6\fR
+statement specifies an IPv6 address for the name server.  The
+secondaries provide for additional addresses for name servers
+to be used if the primary does not respond.  The number of name
+servers the DDNS code will attempt to use before giving up
+is limited and is currently set to three.
 .PP
 Note that the zone declarations have to correspond to authority
 records in your name server - in the above example, there must be an