s3 libaddns: Prevent a crash when dns_create_update fails
[sfrench/samba-autobuild/.git] / lib / addns / dnsrecord.c
index 559c2644d44a1ef3d5fb37b4797184d80e446cd0..de70bca214e812b2bbd713d678c21e3a2bccd831 100644 (file)
@@ -31,8 +31,8 @@ DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
        struct dns_question *q;
        DNS_ERROR err;
 
-       if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
-           !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
+       if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
+           !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
            !(req->questions[0] = talloc(req->questions,
                                         struct dns_question))) {
                TALLOC_FREE(req);
@@ -64,8 +64,8 @@ DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
        struct dns_zone *z;
        DNS_ERROR err;
 
-       if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
-           !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
+       if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
+           !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
            !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
                TALLOC_FREE(req);
                return ERROR_DNS_NO_MEMORY;
@@ -127,12 +127,11 @@ DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
        struct in_addr ip;
 
        if (pss->ss_family != AF_INET) {
-               /* Silently ignore this. */
-               return ERROR_DNS_SUCCESS;
+               return ERROR_DNS_INVALID_PARAMETER;
        }
 
-       ip = ((struct sockaddr_in *)pss)->sin_addr;
-       if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
+       ip = ((const struct sockaddr_in *)pss)->sin_addr;
+       if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip.s_addr,
                                            sizeof(ip.s_addr)))) {
                return ERROR_DNS_NO_MEMORY;
        }
@@ -147,13 +146,54 @@ DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
        return err;
 }
 
+DNS_ERROR dns_create_aaaa_record(TALLOC_CTX *mem_ctx, const char *host,
+                                uint32 ttl, const struct sockaddr_storage *pss,
+                                struct dns_rrec **prec)
+{
+#ifdef HAVE_IPV6
+       uint8 *data;
+       DNS_ERROR err;
+       struct in6_addr ip6;
+
+       if (pss->ss_family != AF_INET6) {
+               return ERROR_DNS_INVALID_PARAMETER;
+       }
+
+       ip6 = ((const struct sockaddr_in6 *)pss)->sin6_addr;
+       if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip6.s6_addr,
+                                           sizeof(ip6.s6_addr)))) {
+               return ERROR_DNS_NO_MEMORY;
+       }
+
+       err = dns_create_rrec(mem_ctx, host, QTYPE_AAAA, DNS_CLASS_IN, ttl,
+                             sizeof(ip6.s6_addr), data, prec);
+
+       if (!ERR_DNS_IS_OK(err)) {
+               TALLOC_FREE(data);
+       }
+
+       return err;
+#else
+       return ERROR_DNS_INVALID_PARAMETER;
+#endif
+}
+
 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
                                        const char *name,
                                        const struct sockaddr_storage *ss,
                                        struct dns_rrec **prec)
 {
        if (ss != NULL) {
-               return dns_create_a_record(mem_ctx, name, 0, ss, prec);
+               switch (ss->ss_family) {
+               case AF_INET:
+                       return dns_create_a_record(mem_ctx, name, 0, ss, prec);
+#ifdef HAVE_IPV6
+               case AF_INET6:
+                       return dns_create_aaaa_record(mem_ctx, name, 0, ss, prec);
+#endif
+               default:
+                       return ERROR_DNS_INVALID_PARAMETER;
+               }
        }
 
        return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
@@ -240,7 +280,7 @@ DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
        if (!ERR_DNS_IS_OK(buf.error)) goto error;
 
        if (tkey->key_length) {
-               if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
+               if (!(tkey->key = talloc_array(tkey, uint8, tkey->key_length))) {
                        buf.error = ERROR_DNS_NO_MEMORY;
                        goto error;
                }
@@ -308,7 +348,7 @@ DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
 {
        struct dns_rrec **new_records;
 
-       if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
+       if (!(new_records = talloc_realloc(mem_ctx, *records,
                                                 struct dns_rrec *,
                                                 (*num_records)+1))) {
                return ERROR_DNS_NO_MEMORY;
@@ -337,7 +377,7 @@ DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
        uint16 i;
 
        err = dns_create_update(mem_ctx, zone, &req);
-       if (!ERR_DNS_IS_OK(err)) goto error;
+       if (!ERR_DNS_IS_OK(err)) return err;
 
        err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
        if (!ERR_DNS_IS_OK(err)) goto error;
@@ -404,7 +444,19 @@ DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
         */
 
        for ( i=0; i<num_addrs; i++ ) {
-               err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
+
+               switch(ss_addrs[i].ss_family) {
+               case AF_INET:
+                       err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
+                       break;
+#ifdef HAVE_IPV6
+               case AF_INET6:
+                       err = dns_create_aaaa_record(req, hostname, 3600, &ss_addrs[i], &rec);
+                       break;
+#endif
+               default:
+                       continue;
+               }
                if (!ERR_DNS_IS_OK(err))
                        goto error;