LCOV - code coverage report
Current view: top level - source4/rpc_server/dnsserver - dnsdata.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 406 615 66.0 %
Date: 2021-09-23 10:06:22 Functions: 15 16 93.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    DNS Server
       5             : 
       6             :    Copyright (C) Amitay Isaacs 2011
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "dnsserver.h"
      24             : #include "dns_server/dnsserver_common.h"
      25             : #include "lib/replace/system/network.h"
      26             : #include "librpc/gen_ndr/ndr_dnsp.h"
      27             : #include "librpc/gen_ndr/ndr_dnsserver.h"
      28             : 
      29             : #undef strcasecmp
      30             : 
      31          12 : struct IP4_ARRAY *ip4_array_copy(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4)
      32             : {
      33             :         struct IP4_ARRAY *ret;
      34             : 
      35          12 :         if (!ip4) {
      36          12 :                 return NULL;
      37             :         }
      38             : 
      39           0 :         ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
      40           0 :         if (!ret) {
      41           0 :                 return ret;
      42             :         }
      43             : 
      44           0 :         ret->AddrCount = ip4->AddrCount;
      45           0 :         if (ip4->AddrCount > 0) {
      46           0 :                 ret->AddrArray = talloc_zero_array(mem_ctx, unsigned int, ip4->AddrCount);
      47           0 :                 if (ret->AddrArray) {
      48           0 :                         memcpy(ret->AddrArray, ip4->AddrArray,
      49           0 :                                 sizeof(unsigned int) * ip4->AddrCount);
      50             :                 } else {
      51           0 :                         talloc_free(ret);
      52           0 :                         return NULL;
      53             :                 }
      54             :         }
      55           0 :         return ret;
      56             : }
      57             : 
      58             : 
      59          83 : struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx,
      60             :                                                         struct IP4_ARRAY *ip4)
      61             : {
      62             :         struct DNS_ADDR_ARRAY *ret;
      63             :         int i;
      64             : 
      65          83 :         if (!ip4) {
      66          83 :                 return NULL;
      67             :         }
      68             : 
      69           0 :         ret = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
      70           0 :         if (!ret) {
      71           0 :                 return ret;
      72             :         }
      73             : 
      74           0 :         ret->MaxCount = ip4->AddrCount;
      75           0 :         ret->AddrCount = ip4->AddrCount;
      76           0 :         ret->Family = AF_INET;
      77           0 :         if (ip4->AddrCount > 0) {
      78           0 :                 ret->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR, ip4->AddrCount);
      79           0 :                 if (ret->AddrArray) {
      80           0 :                         for (i=0; i<ip4->AddrCount; i++) {
      81           0 :                                 ret->AddrArray[i].MaxSa[0] = 0x02;
      82           0 :                                 ret->AddrArray[i].MaxSa[3] = 53;
      83           0 :                                 memcpy(&ret->AddrArray[i].MaxSa[4], ip4->AddrArray,
      84             :                                         sizeof(unsigned int));
      85           0 :                                 ret->AddrArray[i].DnsAddrUserDword[0] = 6;
      86             :                         }
      87             : 
      88             :                 } else {
      89           0 :                         talloc_free(ret);
      90           0 :                         return NULL;
      91             :                 }
      92             :         }
      93           0 :         return ret;
      94             : }
      95             : 
      96          16 : struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx,
      97             :                                               struct DNS_ADDR_ARRAY *ip)
      98             : {
      99             :         struct IP4_ARRAY *ret;
     100             :         size_t i, count, curr;
     101             : 
     102          16 :         if (ip == NULL) {
     103           0 :                 return NULL;
     104             :         }
     105             :         /* We must only return IPv4 addresses.
     106             :            The passed DNS_ADDR_ARRAY may contain:
     107             :            - only ipv4 addresses
     108             :            - only ipv6 addresses
     109             :            - a mixture of both
     110             :            - an empty array
     111             :         */
     112          16 :         ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
     113          16 :         if (!ret) {
     114           0 :                 return ret;
     115             :         }
     116          16 :         if (ip->AddrCount == 0 || ip->Family == AF_INET6) {
     117           0 :                 ret->AddrCount = 0;
     118           0 :                 return ret;
     119             :         }
     120             :         /* Now only ipv4 addresses or a mixture are left */
     121          16 :         count = 0;
     122          48 :         for (i = 0; i < ip->AddrCount; i++) {
     123          32 :                 if (ip->AddrArray[i].MaxSa[0] == 0x02) {
     124             :                         /* Is ipv4 */
     125          16 :                         count++;
     126             :                 }
     127             :         }
     128          16 :         if (count == 0) {
     129             :                 /* should not happen */
     130           0 :                 ret->AddrCount = 0;
     131           0 :                 return ret;
     132             :         }
     133          16 :         ret->AddrArray = talloc_zero_array(mem_ctx, uint32_t, count);
     134          16 :         if (ret->AddrArray) {
     135          16 :                 curr = 0;
     136          48 :                 for (i = 0; i < ip->AddrCount; i++) {
     137          32 :                         if (ip->AddrArray[i].MaxSa[0] == 0x02) {
     138             :                                 /* Is ipv4 */
     139          16 :                                 memcpy(&ret->AddrArray[curr],
     140          16 :                                        &ip->AddrArray[i].MaxSa[4],
     141             :                                        sizeof(uint32_t));
     142          16 :                                 curr++;
     143             :                         }
     144             :                 }
     145             :         } else {
     146           0 :                 talloc_free(ret);
     147           0 :                 return NULL;
     148             :         }
     149          16 :         ret->AddrCount = curr;
     150          16 :         return ret;
     151             : }
     152             : 
     153           0 : struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx,
     154             :                                                 struct DNS_ADDR_ARRAY *addr)
     155             : {
     156             :         struct DNS_ADDR_ARRAY *ret;
     157             : 
     158           0 :         if (!addr) {
     159           0 :                 return NULL;
     160             :         }
     161             : 
     162           0 :         ret = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
     163           0 :         if (!ret) {
     164           0 :                 return ret;
     165             :         }
     166             : 
     167           0 :         ret->MaxCount = addr->MaxCount;
     168           0 :         ret->AddrCount = addr->AddrCount;
     169           0 :         ret->Family = addr->Family;
     170           0 :         if (addr->AddrCount > 0) {
     171           0 :                 ret->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR, addr->AddrCount);
     172           0 :                 if (ret->AddrArray) {
     173           0 :                         memcpy(ret->AddrArray, addr->AddrArray,
     174           0 :                                 sizeof(struct DNS_ADDR) * addr->AddrCount);
     175             :                 } else {
     176           0 :                         talloc_free(ret);
     177           0 :                         return NULL;
     178             :                 }
     179             :         }
     180           0 :         return ret;
     181             : }
     182             : 
     183             : 
     184        1740 : int dns_split_name_components(TALLOC_CTX *tmp_ctx, const char *name, char ***components)
     185             : {
     186        1740 :         char *str = NULL, *ptr, **list;
     187        1740 :         int count = 0;
     188             : 
     189        1740 :         if (name == NULL) {
     190           0 :                 return 0;
     191             :         }
     192             : 
     193        1740 :         str = talloc_strdup(tmp_ctx, name);
     194        1740 :         if (!str) {
     195           0 :                 goto failed;
     196             :         }
     197             : 
     198        1740 :         list = talloc_zero_array(tmp_ctx, char *, 0);
     199        1740 :         if (!list) {
     200           0 :                 goto failed;
     201             :         }
     202             : 
     203        1740 :         ptr = strtok(str, ".");
     204        6605 :         while (ptr != NULL) {
     205        3646 :                 count++;
     206        3646 :                 list = talloc_realloc(tmp_ctx, list, char *, count);
     207        3646 :                 if (!list) {
     208           0 :                         goto failed;
     209             :                 }
     210        3646 :                 list[count-1] = talloc_strdup(tmp_ctx, ptr);
     211        3646 :                 if (list[count-1] == NULL) {
     212           0 :                         goto failed;
     213             :                 }
     214        3646 :                 ptr = strtok(NULL, ".");
     215             :         }
     216             : 
     217        1740 :         talloc_free(str);
     218             : 
     219        1740 :         *components = list;
     220        1740 :         return count;
     221             : 
     222           0 : failed:
     223           0 :         TALLOC_FREE(str);
     224           0 :         return -1;
     225             : }
     226             : 
     227             : 
     228        5176 : char *dns_split_node_name(TALLOC_CTX *tmp_ctx, const char *node_name, const char *zone_name)
     229             : {
     230             :         char **nlist, **zlist;
     231             :         char *prefix;
     232             :         int ncount, zcount, i, match;
     233             : 
     234             :         /*
     235             :          * If node_name is "@", return the zone_name
     236             :          * If node_name is ".", return NULL
     237             :          * If there is no '.' in node_name, return the node_name as is.
     238             :          *
     239             :          * If node_name does not have zone_name in it, return the node_name as is.
     240             :          *
     241             :          * If node_name has additional components as compared to zone_name
     242             :          *  return only the additional components as a prefix.
     243             :          *
     244             :          */
     245        5176 :         if (strcmp(node_name, "@") == 0) {
     246           6 :                 prefix = talloc_strdup(tmp_ctx, zone_name);
     247        5170 :         } else if (strcmp(node_name, ".") == 0) {
     248           0 :                 prefix = NULL;
     249        5170 :         } else if (strchr(node_name, '.') == NULL) {
     250        4868 :                 prefix = talloc_strdup(tmp_ctx, node_name);
     251             :         } else {
     252         302 :                 zcount = dns_split_name_components(tmp_ctx, zone_name, &zlist);
     253         302 :                 ncount = dns_split_name_components(tmp_ctx, node_name, &nlist);
     254         302 :                 if (zcount < 0 || ncount < 0) {
     255           0 :                         return NULL;
     256             :                 }
     257             : 
     258         302 :                 if (ncount < zcount) {
     259          26 :                         prefix = talloc_strdup(tmp_ctx, node_name);
     260             :                 } else {
     261         276 :                         match = 0;
     262        1025 :                         for (i=1; i<=zcount; i++) {
     263         818 :                                 if (strcasecmp(nlist[ncount-i], zlist[zcount-i]) != 0) {
     264          69 :                                         break;
     265             :                                 }
     266         749 :                                 match++;
     267             :                         }
     268             : 
     269         276 :                         if (match == ncount) {
     270           0 :                                 prefix = talloc_strdup(tmp_ctx, zone_name);
     271             :                         } else {
     272         276 :                                 prefix = talloc_strdup(tmp_ctx, nlist[0]);
     273         276 :                                 if (prefix != NULL) {
     274         624 :                                         for (i=1; i<ncount-match; i++) {
     275         348 :                                                 prefix = talloc_asprintf_append(prefix, ".%s", nlist[i]);
     276         348 :                                                 if (prefix == NULL) {
     277           0 :                                                         break;
     278             :                                                 }
     279             :                                         }
     280             :                                 }
     281             :                         }
     282             :                 }
     283             : 
     284         302 :                 talloc_free(zlist);
     285         302 :                 talloc_free(nlist);
     286             :         }
     287             : 
     288        5176 :         return prefix;
     289             : }
     290             : 
     291             : 
     292        1510 : void dnsp_to_dns_copy(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *dnsp,
     293             :                                 struct DNS_RPC_RECORD *dns)
     294             : {
     295             :         int i, len;
     296             : 
     297        1510 :         ZERO_STRUCTP(dns);
     298             : 
     299        1510 :         dns->wDataLength = dnsp->wDataLength;
     300        1510 :         dns->wType = dnsp->wType;
     301        1510 :         dns->dwFlags = dnsp->rank;
     302        1510 :         dns->dwSerial = dnsp->dwSerial;
     303        1510 :         dns->dwTtlSeconds = dnsp->dwTtlSeconds;
     304        1510 :         dns->dwTimeStamp = dnsp->dwTimeStamp;
     305             : 
     306        1510 :         switch (dnsp->wType) {
     307             : 
     308           0 :         case DNS_TYPE_TOMBSTONE:
     309           0 :                 dns->data.EntombedTime = dnsp->data.EntombedTime;
     310           0 :                 break;
     311             : 
     312         227 :         case DNS_TYPE_A:
     313         227 :                 dns->data.ipv4 = talloc_strdup(mem_ctx, dnsp->data.ipv4);
     314         227 :                 break;
     315             : 
     316         214 :         case DNS_TYPE_NS:
     317         214 :                 len = strlen(dnsp->data.ns);
     318         214 :                 if (dnsp->data.ns[len-1] == '.') {
     319           0 :                         dns->data.name.len = len;
     320           0 :                         dns->data.name.str = talloc_strdup(mem_ctx, dnsp->data.ns);
     321             :                 } else {
     322         214 :                         dns->data.name.len = len+1;
     323         214 :                         dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.ns);
     324             :                 }
     325         214 :                 break;
     326             : 
     327         115 :         case DNS_TYPE_CNAME:
     328         115 :                 len = strlen(dnsp->data.cname);
     329         115 :                 if (dnsp->data.cname[len-1] == '.') {
     330           0 :                         dns->data.name.len = len;
     331           0 :                         dns->data.name.str = talloc_strdup(mem_ctx, dnsp->data.cname);
     332             :                 } else {
     333         115 :                         dns->data.name.len = len+1;
     334         115 :                         dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.cname);
     335             :                 }
     336         115 :                 break;
     337             : 
     338           0 :         case DNS_TYPE_SOA:
     339           0 :                 dns->data.soa.dwSerialNo = dnsp->data.soa.serial;
     340           0 :                 dns->data.soa.dwRefresh = dnsp->data.soa.refresh;
     341           0 :                 dns->data.soa.dwRetry = dnsp->data.soa.retry;
     342           0 :                 dns->data.soa.dwExpire = dnsp->data.soa.expire;
     343           0 :                 dns->data.soa.dwMinimumTtl = dnsp->data.soa.minimum;
     344             : 
     345           0 :                 len = strlen(dnsp->data.soa.mname);
     346           0 :                 if (dnsp->data.soa.mname[len-1] == '.') {
     347           0 :                         dns->data.soa.NamePrimaryServer.len = len;
     348           0 :                         dns->data.soa.NamePrimaryServer.str = talloc_strdup(mem_ctx, dnsp->data.soa.mname);
     349             :                 } else {
     350           0 :                         dns->data.soa.NamePrimaryServer.len = len+1;
     351           0 :                         dns->data.soa.NamePrimaryServer.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.soa.mname);
     352             :                 }
     353             : 
     354           0 :                 len = strlen(dnsp->data.soa.rname);
     355           0 :                 if (dnsp->data.soa.rname[len-1] == '.') {
     356           0 :                         dns->data.soa.ZoneAdministratorEmail.len = len;
     357           0 :                         dns->data.soa.ZoneAdministratorEmail.str = talloc_strdup(mem_ctx, dnsp->data.soa.rname);
     358             :                 } else {
     359           0 :                         dns->data.soa.ZoneAdministratorEmail.len = len+1;
     360           0 :                         dns->data.soa.ZoneAdministratorEmail.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.soa.rname);
     361             :                 }
     362           0 :                 break;
     363             : 
     364         184 :         case DNS_TYPE_PTR:
     365         184 :                 dns->data.ptr.len = strlen(dnsp->data.ptr);
     366         184 :                 dns->data.ptr.str = talloc_strdup(mem_ctx, dnsp->data.ptr);
     367         184 :                 break;
     368             : 
     369         160 :         case DNS_TYPE_MX:
     370         160 :                 dns->data.mx.wPreference = dnsp->data.mx.wPriority;
     371         160 :                 len = strlen(dnsp->data.mx.nameTarget);
     372         160 :                 if (dnsp->data.mx.nameTarget[len-1] == '.') {
     373           0 :                         dns->data.mx.nameExchange.len = len;
     374           0 :                         dns->data.mx.nameExchange.str = talloc_strdup(mem_ctx, dnsp->data.mx.nameTarget);
     375             :                 } else {
     376         160 :                         dns->data.mx.nameExchange.len = len+1;
     377         160 :                         dns->data.mx.nameExchange.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.mx.nameTarget);
     378             :                 }
     379         160 :                 break;
     380             : 
     381         126 :         case DNS_TYPE_TXT:
     382         126 :                 dns->data.txt.count = dnsp->data.txt.count;
     383         126 :                 dns->data.txt.str = talloc_array(mem_ctx, struct DNS_RPC_NAME, dnsp->data.txt.count);
     384         267 :                 for (i=0; i<dnsp->data.txt.count; i++) {
     385         141 :                         dns->data.txt.str[i].str = talloc_strdup(mem_ctx, dnsp->data.txt.str[i]);
     386         141 :                         dns->data.txt.str[i].len = strlen(dnsp->data.txt.str[i]);
     387             :                 }
     388         126 :                 break;
     389             : 
     390         241 :         case DNS_TYPE_AAAA:
     391         241 :                 dns->data.ipv6 = talloc_strdup(mem_ctx, dnsp->data.ipv6);
     392         241 :                 break;
     393             : 
     394         243 :         case DNS_TYPE_SRV:
     395         243 :                 dns->data.srv.wPriority = dnsp->data.srv.wPriority;
     396         243 :                 dns->data.srv.wWeight = dnsp->data.srv.wWeight;
     397         243 :                 dns->data.srv.wPort = dnsp->data.srv.wPort;
     398         243 :                 len = strlen(dnsp->data.srv.nameTarget);
     399         243 :                 if (dnsp->data.srv.nameTarget[len-1] == '.') {
     400           0 :                         dns->data.srv.nameTarget.len = len;
     401           0 :                         dns->data.srv.nameTarget.str = talloc_strdup(mem_ctx, dnsp->data.srv.nameTarget);
     402             :                 } else {
     403         243 :                         dns->data.srv.nameTarget.len = len+1;
     404         243 :                         dns->data.srv.nameTarget.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.srv.nameTarget);
     405             :                 }
     406         243 :                 break;
     407             : 
     408           0 :         default:
     409           0 :                 memcpy(&dns->data, &dnsp->data, sizeof(union DNS_RPC_RECORD_DATA));
     410           0 :                 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dnsp->wType));
     411             :         }
     412             : 
     413        1510 : }
     414             : 
     415        4053 : WERROR dns_to_dnsp_convert(TALLOC_CTX *mem_ctx, struct DNS_RPC_RECORD *dns,
     416             :                            struct dnsp_DnssrvRpcRecord **out_dnsp, bool check_name)
     417             : {
     418             :         WERROR res;
     419             :         int i, len;
     420             :         const char *name;
     421        4053 :         char *talloc_res = NULL;
     422        4053 :         struct dnsp_DnssrvRpcRecord *dnsp = NULL;
     423             : 
     424        4053 :         dnsp = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
     425        4053 :         if (dnsp == NULL) {
     426           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     427             :         }
     428             : 
     429        4053 :         dnsp->wDataLength = dns->wDataLength;
     430        4053 :         dnsp->wType = dns->wType;
     431        4053 :         dnsp->version = 5;
     432        4053 :         dnsp->rank = dns->dwFlags & 0x000000FF;
     433        4053 :         dnsp->dwSerial = dns->dwSerial;
     434        4053 :         dnsp->dwTtlSeconds = dns->dwTtlSeconds;
     435        4053 :         dnsp->dwTimeStamp = dns->dwTimeStamp;
     436             : 
     437        4053 :         switch (dns->wType) {
     438             : 
     439           0 :         case DNS_TYPE_TOMBSTONE:
     440           0 :                 dnsp->data.EntombedTime = dns->data.EntombedTime;
     441           0 :                 break;
     442             : 
     443         633 :         case DNS_TYPE_A:
     444         633 :                 talloc_res = talloc_strdup(mem_ctx, dns->data.ipv4);
     445         633 :                 if (talloc_res == NULL) {
     446           0 :                         goto fail_nomemory;
     447             :                 }
     448         633 :                 dnsp->data.ipv4 = talloc_res;
     449         633 :                 break;
     450             : 
     451         471 :         case DNS_TYPE_NS:
     452         471 :                 name = dns->data.name.str;
     453         471 :                 len = dns->data.name.len;
     454             : 
     455         471 :                 if (check_name) {
     456         266 :                         res = dns_name_check(mem_ctx, len, name);
     457         266 :                         if (!W_ERROR_IS_OK(res)) {
     458          40 :                                 return res;
     459             :                         }
     460             :                 }
     461             : 
     462         431 :                 if (len > 0 && name[len-1] == '.') {
     463          48 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     464          48 :                         if (talloc_res == NULL) {
     465           0 :                                 goto fail_nomemory;
     466             :                         }
     467          48 :                         dnsp->data.ns = talloc_res;
     468             :                 } else {
     469         383 :                         talloc_res = talloc_strdup(mem_ctx, name);
     470         383 :                         if (talloc_res == NULL) {
     471           0 :                                 goto fail_nomemory;
     472             :                         }
     473         383 :                         dnsp->data.ns = talloc_res;
     474             :                 }
     475             : 
     476         431 :                 break;
     477             : 
     478         426 :         case DNS_TYPE_CNAME:
     479         426 :                 name = dns->data.name.str;
     480         426 :                 len = dns->data.name.len;
     481             : 
     482         426 :                 if (check_name) {
     483         257 :                         res = dns_name_check(mem_ctx, len, name);
     484         257 :                         if (!W_ERROR_IS_OK(res)) {
     485          40 :                                 return res;
     486             :                         }
     487             :                 }
     488             : 
     489         386 :                 if (len > 0 && name[len-1] == '.') {
     490          42 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     491          42 :                         if (talloc_res == NULL) {
     492           0 :                                 goto fail_nomemory;
     493             :                         }
     494          42 :                         dnsp->data.cname = talloc_res;
     495             :                 } else {
     496         344 :                         talloc_res = talloc_strdup(mem_ctx, name);
     497         344 :                         if (talloc_res == NULL) {
     498           0 :                                 goto fail_nomemory;
     499             :                         }
     500         344 :                         dnsp->data.cname = talloc_res;
     501             :                 }
     502             : 
     503         386 :                 break;
     504             : 
     505           0 :         case DNS_TYPE_SOA:
     506           0 :                 dnsp->data.soa.serial = dns->data.soa.dwSerialNo;
     507           0 :                 dnsp->data.soa.refresh = dns->data.soa.dwRefresh;
     508           0 :                 dnsp->data.soa.retry = dns->data.soa.dwRetry;
     509           0 :                 dnsp->data.soa.expire = dns->data.soa.dwExpire;
     510           0 :                 dnsp->data.soa.minimum = dns->data.soa.dwMinimumTtl;
     511             : 
     512           0 :                 name = dns->data.soa.NamePrimaryServer.str;
     513           0 :                 len = dns->data.soa.NamePrimaryServer.len;
     514             : 
     515           0 :                 if (check_name) {
     516           0 :                         res = dns_name_check(mem_ctx, len, name);
     517           0 :                         if (!W_ERROR_IS_OK(res)) {
     518           0 :                                 return res;
     519             :                         }
     520             :                 }
     521             : 
     522           0 :                 if (len > 0 && name[len-1] == '.') {
     523           0 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     524           0 :                         if (talloc_res == NULL) {
     525           0 :                                 goto fail_nomemory;
     526             :                         }
     527           0 :                         dnsp->data.soa.mname = talloc_res;
     528             :                 } else {
     529           0 :                         talloc_res = talloc_strdup(mem_ctx, name);
     530           0 :                         if (talloc_res == NULL) {
     531           0 :                                 goto fail_nomemory;
     532             :                         }
     533           0 :                         dnsp->data.soa.mname = talloc_res;
     534             :                 }
     535             : 
     536           0 :                 name = dns->data.soa.ZoneAdministratorEmail.str;
     537           0 :                 len = dns->data.soa.ZoneAdministratorEmail.len;
     538             : 
     539           0 :                 res = dns_name_check(mem_ctx, len, name);
     540           0 :                 if (!W_ERROR_IS_OK(res)) {
     541           0 :                         return res;
     542             :                 }
     543             : 
     544           0 :                 if (len > 0 && name[len-1] == '.') {
     545           0 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     546           0 :                         if (talloc_res == NULL) {
     547           0 :                                 goto fail_nomemory;
     548             :                         }
     549           0 :                         dnsp->data.soa.rname = talloc_res;
     550             :                 } else {
     551           0 :                         talloc_res = talloc_strdup(mem_ctx, name);
     552           0 :                         if (talloc_res == NULL) {
     553           0 :                                 goto fail_nomemory;
     554             :                         }
     555           0 :                         dnsp->data.soa.rname = talloc_res;
     556             :                 }
     557             : 
     558           0 :                 break;
     559             : 
     560         467 :         case DNS_TYPE_PTR:
     561         467 :                 name = dns->data.ptr.str;
     562         467 :                 len = dns->data.ptr.len;
     563             : 
     564         467 :                 if (check_name) {
     565         262 :                         res = dns_name_check(mem_ctx, len, name);
     566         262 :                         if (!W_ERROR_IS_OK(res)) {
     567          40 :                                 return res;
     568             :                         }
     569             :                 }
     570             : 
     571         427 :                 talloc_res = talloc_strdup(mem_ctx, name);
     572         427 :                 if (talloc_res == NULL) {
     573           0 :                         goto fail_nomemory;
     574             :                 }
     575         427 :                 dnsp->data.ptr = talloc_res;
     576             : 
     577         427 :                 break;
     578             : 
     579         427 :         case DNS_TYPE_MX:
     580         427 :                 dnsp->data.mx.wPriority = dns->data.mx.wPreference;
     581             : 
     582         427 :                 name = dns->data.mx.nameExchange.str;
     583         427 :                 len = dns->data.mx.nameExchange.len;
     584             : 
     585         427 :                 if (check_name) {
     586         237 :                         res = dns_name_check(mem_ctx, len, name);
     587         237 :                         if (!W_ERROR_IS_OK(res)) {
     588          38 :                                 return res;
     589             :                         }
     590             :                 }
     591             : 
     592         389 :                 if (len > 0 && name[len-1] == '.') {
     593          35 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     594          35 :                         if (talloc_res == NULL) {
     595           0 :                                 goto fail_nomemory;
     596             :                         }
     597          35 :                         dnsp->data.mx.nameTarget = talloc_res;
     598             :                 } else {
     599         354 :                         talloc_res = talloc_strdup(mem_ctx, name);
     600         354 :                         if (talloc_res == NULL) {
     601           0 :                                 goto fail_nomemory;
     602             :                         }
     603         354 :                         dnsp->data.mx.nameTarget = talloc_res;
     604             :                 }
     605             : 
     606         389 :                 break;
     607             : 
     608         396 :         case DNS_TYPE_TXT:
     609         396 :                 dnsp->data.txt.count = dns->data.txt.count;
     610         396 :                 dnsp->data.txt.str = talloc_array(mem_ctx, const char *, dns->data.txt.count);
     611         821 :                 for (i=0; i<dns->data.txt.count; i++) {
     612         425 :                         talloc_res = talloc_strdup(mem_ctx, dns->data.txt.str[i].str);
     613         425 :                         if (talloc_res == NULL) {
     614           0 :                                 goto fail_nomemory;
     615             :                         }
     616         425 :                         dnsp->data.txt.str[i] = talloc_res;
     617             :                 }
     618         396 :                 break;
     619             : 
     620         680 :         case DNS_TYPE_AAAA:
     621         680 :                 dnsp->data.ipv6 = talloc_strdup(mem_ctx, dns->data.ipv6);
     622         680 :                 break;
     623             : 
     624         553 :         case DNS_TYPE_SRV:
     625         553 :                 dnsp->data.srv.wPriority = dns->data.srv.wPriority;
     626         553 :                 dnsp->data.srv.wWeight = dns->data.srv.wWeight;
     627         553 :                 dnsp->data.srv.wPort = dns->data.srv.wPort;
     628             : 
     629         553 :                 name = dns->data.srv.nameTarget.str;
     630         553 :                 len = dns->data.srv.nameTarget.len;
     631             : 
     632         553 :                 if (check_name) {
     633         329 :                         res = dns_name_check(mem_ctx, len, name);
     634         329 :                         if (!W_ERROR_IS_OK(res)) {
     635          38 :                                 return res;
     636             :                         }
     637             :                 }
     638             : 
     639         515 :                 if (len > 0 && name[len-1] == '.') {
     640          48 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     641          48 :                         if (talloc_res == NULL) {
     642           0 :                                 goto fail_nomemory;
     643             :                         }
     644          48 :                         dnsp->data.srv.nameTarget = talloc_res;
     645             :                 } else {
     646         467 :                         talloc_res = talloc_strdup(mem_ctx, name);
     647         467 :                         if (talloc_res == NULL) {
     648           0 :                                 goto fail_nomemory;
     649             :                         }
     650         467 :                         dnsp->data.srv.nameTarget = talloc_res;
     651             :                 }
     652             : 
     653         515 :                 break;
     654             : 
     655           0 :         default:
     656           0 :                 memcpy(&dnsp->data, &dns->data, sizeof(union dnsRecordData));
     657           0 :                 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dns->wType));
     658             :         }
     659             : 
     660        3857 :         *out_dnsp = dnsp;
     661        3857 :         return WERR_OK;
     662             : 
     663           0 : fail_nomemory:
     664           0 :         return WERR_NOT_ENOUGH_MEMORY;
     665             : }
     666             : 
     667             : /* Intialize tree with given name as the root */
     668        1073 : static struct dns_tree *dns_tree_init(TALLOC_CTX *mem_ctx, const char *name, void *data)
     669             : {
     670             :         struct dns_tree *tree;
     671             : 
     672        1073 :         tree = talloc_zero(mem_ctx, struct dns_tree);
     673        1073 :         if (tree == NULL) {
     674           0 :                 return NULL;
     675             :         }
     676             : 
     677        1073 :         tree->name = talloc_strdup(tree, name);
     678        1073 :         if (tree->name == NULL) {
     679           0 :                 talloc_free(tree);
     680           0 :                 return NULL;
     681             :         }
     682             : 
     683        1073 :         tree->data = data;
     684             : 
     685        1073 :         return tree;
     686             : }
     687             : 
     688             : 
     689             : /* Add a child one level below */
     690          70 : static struct dns_tree *dns_tree_add(struct dns_tree *tree, const char *name, void *data)
     691             : {
     692             :         struct dns_tree *node;
     693             : 
     694          70 :         node = talloc_zero(tree, struct dns_tree);
     695          70 :         if (node == NULL) {
     696           0 :                 return NULL;
     697             :         }
     698             : 
     699          70 :         node->name = talloc_strdup(tree, name);
     700          70 :         if (node->name == NULL) {
     701           0 :                 talloc_free(node);
     702           0 :                 return NULL;
     703             :         }
     704          70 :         node->level = tree->level + 1;
     705          70 :         node->num_children = 0;
     706          70 :         node->children = NULL;
     707          70 :         node->data = data;
     708             : 
     709          70 :         if (tree->num_children == 0) {
     710          19 :                 tree->children = talloc_zero(tree, struct dns_tree *);
     711             :         } else {
     712          51 :                 tree->children = talloc_realloc(tree, tree->children, struct dns_tree *,
     713             :                                                 tree->num_children+1);
     714             :         }
     715          70 :         if (tree->children == NULL) {
     716           0 :                 talloc_free(node);
     717           0 :                 return NULL;
     718             :         }
     719          70 :         tree->children[tree->num_children] = node;
     720          70 :         tree->num_children++;
     721             : 
     722          70 :         return node;
     723             : }
     724             : 
     725             : /* Find a node that matches the name components */
     726          63 : static struct dns_tree *dns_tree_find(struct dns_tree *tree, int ncount, char **nlist, int *match_count)
     727             : {
     728             :         struct dns_tree *node, *next;
     729             :         int i, j, start;
     730             : 
     731          63 :         *match_count = -1;
     732             : 
     733          63 :         if (strcmp(tree->name, "@") == 0) {
     734          33 :                 start = 0;
     735             :         } else {
     736          30 :                 if (strcasecmp(tree->name, nlist[ncount-1]) != 0) {
     737           0 :                         return NULL;
     738             :                 }
     739          30 :                 start = 1;
     740          30 :                 *match_count = 0;
     741             :         }
     742             : 
     743          63 :         node = tree;
     744          93 :         for (i=start; i<ncount; i++) {
     745          93 :                 if (node->num_children == 0) {
     746          12 :                         break;
     747             :                 }
     748          81 :                 next = NULL;
     749         216 :                 for (j=0; j<node->num_children; j++) {
     750         165 :                         if (strcasecmp(nlist[(ncount-1)-i], node->children[j]->name) == 0) {
     751          30 :                                 next = node->children[j];
     752          30 :                                 *match_count = i;
     753          30 :                                 break;
     754             :                         }
     755             :                 }
     756          81 :                 if (next == NULL) {
     757          51 :                         break;
     758             :                 } else {
     759          30 :                         node = next;
     760             :                 }
     761             :         }
     762             : 
     763          63 :         return node;
     764             : }
     765             : 
     766             : /* Build a 2-level tree for resulting dns names */
     767        1073 : struct dns_tree *dns_build_tree(TALLOC_CTX *mem_ctx, const char *name, struct ldb_result *res)
     768             : {
     769             :         struct dns_tree *root, *base, *tree, *node;
     770             :         const char *ptr;
     771             :         int rootcount, ncount;
     772             :         char **nlist;
     773             :         int i, level, match_count;
     774             : 
     775        1073 :         rootcount = dns_split_name_components(mem_ctx, name, &nlist);
     776        1073 :         if (rootcount <= 0) {
     777           0 :                 return NULL;
     778             :         }
     779             : 
     780        1073 :         root = dns_tree_init(mem_ctx, nlist[rootcount-1], NULL);
     781        1073 :         if (root == NULL) {
     782           0 :                 talloc_free(nlist);
     783           0 :                 return NULL;
     784             :         }
     785             : 
     786        1073 :         tree = root;
     787        1080 :         for (i=rootcount-2; i>=0; i--) {
     788           7 :                 tree = dns_tree_add(tree, nlist[i], NULL);
     789           7 :                 if (tree == NULL) {
     790           0 :                         goto failed;
     791             :                 }
     792             :         }
     793             : 
     794        1073 :         base = tree;
     795             : 
     796             :         /* Add all names in the result in a tree */
     797        2203 :         for (i=0; i<res->count; i++) {
     798        1130 :                 ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
     799        1130 :                 if (ptr == NULL) {
     800           0 :                         DBG_ERR("dnsserver: dns record has no name (%s)",
     801             :                                 ldb_dn_get_linearized(res->msgs[i]->dn));
     802           0 :                         goto failed;
     803             :                 }
     804             : 
     805             :                 /*
     806             :                  * This might be the sub-domain in the zone being
     807             :                  * requested, or @ for the root of the zone
     808             :                  */
     809        1130 :                 if (strcasecmp(ptr, name) == 0) {
     810        1067 :                         base->data = res->msgs[i];
     811        1067 :                         continue;
     812             :                 }
     813             : 
     814          63 :                 ncount = dns_split_name_components(root, ptr, &nlist);
     815          63 :                 if (ncount < 0) {
     816           0 :                         goto failed;
     817             :                 }
     818             : 
     819             :                 /* Find matching node */
     820          63 :                 tree = dns_tree_find(root, ncount, nlist, &match_count);
     821          63 :                 if (tree == NULL) {
     822           0 :                         goto failed;
     823             :                 }
     824             : 
     825             :                 /* If the node is on leaf, then add record data */
     826          63 :                 if (match_count+1 == ncount) {
     827           0 :                         tree->data = res->msgs[i];
     828             :                 }
     829             : 
     830             :                 /* Add missing name components */
     831         126 :                 for (level=match_count+1; level<ncount; level++) {
     832          63 :                         if (tree->level == rootcount+1) {
     833           0 :                                 break;
     834             :                         }
     835          63 :                         if (level == ncount-1) {
     836          63 :                                 node = dns_tree_add(tree, nlist[(ncount-1)-level], res->msgs[i]);
     837             :                         } else {
     838           0 :                                 node = dns_tree_add(tree, nlist[(ncount-1)-level], NULL);
     839             :                         }
     840          63 :                         if (node == NULL) {
     841           0 :                                 goto failed;
     842             :                         }
     843          63 :                         tree = node;
     844             :                 }
     845             : 
     846          63 :                 talloc_free(nlist);
     847             :         }
     848             : 
     849             :         /* Mark the base record, so it can be found easily */
     850        1073 :         base->level = -1;
     851             : 
     852        1073 :         return root;
     853             : 
     854           0 : failed:
     855           0 :         talloc_free(nlist);
     856           0 :         talloc_free(root);
     857           0 :         return NULL;
     858             : }
     859             : 
     860             : 
     861         732 : static void _dns_add_name(TALLOC_CTX *mem_ctx, const char *name, char ***add_names, int *add_count)
     862             : {
     863             :         int i;
     864         732 :         char **ptr = *add_names;
     865         732 :         int count = *add_count;
     866             : 
     867        1100 :         for (i=0; i<count; i++) {
     868         422 :                 if (strcasecmp(ptr[i], name) == 0) {
     869          54 :                         return;
     870             :                 }
     871             :         }
     872             : 
     873         678 :         ptr = talloc_realloc(mem_ctx, ptr, char *, count+1);
     874         678 :         if (ptr == NULL) {
     875           0 :                 return;
     876             :         }
     877             : 
     878         678 :         ptr[count] = talloc_strdup(mem_ctx, name);
     879         678 :         if (ptr[count] == NULL) {
     880           0 :                 talloc_free(ptr);
     881           0 :                 return;
     882             :         }
     883             : 
     884         678 :         *add_names = ptr;
     885         678 :         *add_count = count+1;
     886             : }
     887             : 
     888             : 
     889        1510 : static void dns_find_additional_names(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *rec, char ***add_names, int *add_count)
     890             : {
     891        1510 :         if (add_names == NULL) {
     892          39 :                 return;
     893             :         }
     894             : 
     895        1471 :         switch (rec->wType) {
     896             : 
     897         214 :         case DNS_TYPE_NS:
     898         214 :                 _dns_add_name(mem_ctx, rec->data.ns, add_names, add_count);
     899         214 :                 break;
     900             : 
     901         115 :         case DNS_TYPE_CNAME:
     902         115 :                 _dns_add_name(mem_ctx, rec->data.cname, add_names, add_count);
     903         115 :                 break;
     904             : 
     905           0 :         case DNS_TYPE_SOA:
     906           0 :                 _dns_add_name(mem_ctx, rec->data.soa.mname, add_names, add_count);
     907           0 :                 break;
     908             : 
     909         160 :         case DNS_TYPE_MX:
     910         160 :                 _dns_add_name(mem_ctx, rec->data.mx.nameTarget, add_names, add_count);
     911         160 :                 break;
     912             : 
     913         243 :         case DNS_TYPE_SRV:
     914         243 :                 _dns_add_name(mem_ctx, rec->data.srv.nameTarget, add_names, add_count);
     915         243 :                 break;
     916             : 
     917         739 :         default:
     918         739 :                 break;
     919             :         }
     920             : }
     921             : 
     922             : 
     923        1178 : WERROR dns_fill_records_array(TALLOC_CTX *mem_ctx,
     924             :                                 struct dnsserver_zone *z,
     925             :                                 enum dns_record_type record_type,
     926             :                                 unsigned int select_flag,
     927             :                                 const char *branch_name,
     928             :                                 struct ldb_message *msg,
     929             :                                 int num_children,
     930             :                                 struct DNS_RPC_RECORDS_ARRAY *recs,
     931             :                                 char ***add_names,
     932             :                                 int *add_count)
     933             : {
     934             :         struct ldb_message_element *el;
     935             :         const char *ptr;
     936             :         int i, j;
     937             :         bool found;
     938             : 
     939        1178 :         if (recs->count == 0) {
     940        1076 :                 recs->rec = talloc_zero(recs, struct DNS_RPC_RECORDS);
     941             :         } else {
     942         102 :                 recs->rec = talloc_realloc(recs, recs->rec, struct DNS_RPC_RECORDS, recs->count+1);
     943             :         }
     944        1178 :         if (recs->rec == NULL) {
     945           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     946             :         }
     947        1178 :         i = recs->count;
     948        1178 :         recs->rec[i].wLength = 0;
     949        1178 :         recs->rec[i].wRecordCount = 0;
     950        1178 :         recs->rec[i].dwChildCount = num_children;
     951        1178 :         recs->rec[i].dwFlags = 0;
     952             : 
     953             :         /* The base records returned with empty name */
     954             :         /* Children records returned with names */
     955        1178 :         if (branch_name == NULL) {
     956        1076 :                 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, "");
     957        1076 :                 recs->rec[i].dnsNodeName.len = 0;
     958             :         } else {
     959         102 :                 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, branch_name);
     960         102 :                 recs->rec[i].dnsNodeName.len = strlen(branch_name);
     961             :         }
     962        1178 :         recs->rec[i].records = talloc_zero_array(recs, struct DNS_RPC_RECORD, 0);
     963        1178 :         recs->count++;
     964             : 
     965             :         /* Allow empty records */
     966        1178 :         if (msg == NULL) {
     967           6 :                 return WERR_OK;
     968             :         }
     969             : 
     970             :         /* Do not return RR records, if the node has children */
     971        1172 :         if (branch_name != NULL && num_children > 0) {
     972           0 :                 return WERR_OK;
     973             :         }
     974             : 
     975        1172 :         ptr = ldb_msg_find_attr_as_string(msg, "name", NULL);
     976        1172 :         if (ptr == NULL) {
     977           0 :                 DBG_ERR("dnsserver: dns record has no name (%s)",
     978             :                         ldb_dn_get_linearized(msg->dn));
     979           0 :                 return WERR_INTERNAL_DB_ERROR;
     980             :         }
     981             : 
     982        1172 :         el = ldb_msg_find_element(msg, "dnsRecord");
     983        1172 :         if (el == NULL || el->values == 0) {
     984           0 :                 return WERR_OK;
     985             :         }
     986             : 
     987             :         /* Add RR records */
     988        5550 :         for (j=0; j<el->num_values; j++) {
     989             :                 struct dnsp_DnssrvRpcRecord dnsp_rec;
     990             :                 struct DNS_RPC_RECORD *dns_rec;
     991             :                 enum ndr_err_code ndr_err;
     992             : 
     993        2022 :                 ndr_err = ndr_pull_struct_blob(&el->values[j], mem_ctx, &dnsp_rec,
     994             :                                         (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
     995        2022 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     996           0 :                         DEBUG(0, ("dnsserver: Unable to parse dns record (%s)", ldb_dn_get_linearized(msg->dn)));
     997           0 :                         return WERR_INTERNAL_DB_ERROR;
     998             :                 }
     999             : 
    1000             :                 /* Match the records based on search criteria */
    1001        2022 :                 if (record_type == DNS_TYPE_ALL || dnsp_rec.wType == record_type) {
    1002        1514 :                         found = false;
    1003             : 
    1004        1514 :                         if (select_flag & DNS_RPC_VIEW_AUTHORITY_DATA) {
    1005        1436 :                                 if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1006        1257 :                                         found = true;
    1007         179 :                                 } else if (dnsp_rec.rank == DNS_RANK_NS_GLUE) {
    1008             :                                         /*
    1009             :                                          * If branch_name is NULL, we're
    1010             :                                          * explicitly asked to also return
    1011             :                                          * DNS_RANK_NS_GLUE records
    1012             :                                          */
    1013         175 :                                         if (branch_name == NULL) {
    1014         175 :                                                 found = true;
    1015             :                                         }
    1016             :                                 }
    1017             :                         }
    1018        1514 :                         if (select_flag & DNS_RPC_VIEW_CACHE_DATA) {
    1019           0 :                                 if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1020           0 :                                         found = true;
    1021             :                                 }
    1022             :                         }
    1023        1514 :                         if (select_flag & DNS_RPC_VIEW_GLUE_DATA) {
    1024           0 :                                 if (dnsp_rec.rank == DNS_RANK_GLUE) {
    1025           0 :                                         found = true;
    1026             :                                 }
    1027             :                         }
    1028        1514 :                         if (select_flag & DNS_RPC_VIEW_ROOT_HINT_DATA) {
    1029          78 :                                 if (dnsp_rec.rank == DNS_RANK_ROOT_HINT) {
    1030          78 :                                         found = true;
    1031             :                                 }
    1032             :                         }
    1033             : 
    1034        1514 :                         if (found) {
    1035        1510 :                                 recs->rec[i].records = talloc_realloc(recs,
    1036             :                                                         recs->rec[i].records,
    1037             :                                                         struct DNS_RPC_RECORD,
    1038             :                                                         recs->rec[i].wRecordCount+1);
    1039        1510 :                                 if (recs->rec[i].records == NULL) {
    1040           0 :                                         return WERR_NOT_ENOUGH_MEMORY;
    1041             :                                 }
    1042             : 
    1043        1510 :                                 dns_rec = &recs->rec[i].records[recs->rec[i].wRecordCount];
    1044        1510 :                                 dnsp_to_dns_copy(recs, &dnsp_rec, dns_rec);
    1045             : 
    1046             :                                 /* Fix record flags */
    1047        1510 :                                 if (strcmp(ptr, "@") == 0) {
    1048          42 :                                         dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
    1049             : 
    1050          42 :                                         if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1051           3 :                                                 dns_rec->dwFlags |= DNS_RPC_FLAG_AUTH_ZONE_ROOT;
    1052             :                                         }
    1053             :                                 }
    1054             : 
    1055        1510 :                                 if (dns_rec->dwFlags == DNS_RANK_NS_GLUE) {
    1056         175 :                                         dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
    1057             :                                 }
    1058             : 
    1059        1510 :                                 recs->rec[i].wRecordCount++;
    1060             : 
    1061        1510 :                                 dns_find_additional_names(mem_ctx, &dnsp_rec, add_names, add_count);
    1062             :                         }
    1063             :                 }
    1064             :         }
    1065             : 
    1066        1172 :         return WERR_OK;
    1067             : }
    1068             : 
    1069             : 
    1070         207 : int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const *m2,
    1071             :                      const char *search_name)
    1072             : {
    1073             :         const char *name1, *name2;
    1074             :         const char *ptr1, *ptr2;
    1075             : 
    1076         207 :         name1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
    1077         207 :         name2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
    1078         207 :         if (name1 == NULL || name2 == NULL) {
    1079           0 :                 return 0;
    1080             :         }
    1081             : 
    1082             :         /* Compare the last components of names.
    1083             :          * If search_name is not NULL, compare the second last components of names */
    1084         207 :         ptr1 = strrchr(name1, '.');
    1085         207 :         if (ptr1 == NULL) {
    1086         123 :                 ptr1 = name1;
    1087             :         } else {
    1088          84 :                 if (search_name && strcasecmp(ptr1+1, search_name) == 0) {
    1089           0 :                         ptr1--;
    1090           0 :                         while (ptr1 != name1) {
    1091           0 :                                 ptr1--;
    1092           0 :                                 if (*ptr1 == '.') {
    1093           0 :                                         break;
    1094             :                                 }
    1095             :                         }
    1096             :                 }
    1097          84 :                 if (*ptr1 == '.') {
    1098          84 :                         ptr1 = &ptr1[1];
    1099             :                 }
    1100             :         }
    1101             : 
    1102         207 :         ptr2 = strrchr(name2, '.');
    1103         207 :         if (ptr2 == NULL) {
    1104         123 :                 ptr2 = name2;
    1105             :         } else {
    1106          84 :                 if (search_name && strcasecmp(ptr2+1, search_name) == 0) {
    1107           0 :                         ptr2--;
    1108           0 :                         while (ptr2 != name2) {
    1109           0 :                                 ptr2--;
    1110           0 :                                 if (*ptr2 == '.') {
    1111           0 :                                         break;
    1112             :                                 }
    1113             :                         }
    1114             :                 }
    1115          84 :                 if (*ptr2 == '.') {
    1116          84 :                         ptr2 = &ptr2[1];
    1117             :                 }
    1118             :         }
    1119             : 
    1120         207 :         return strcasecmp(ptr1, ptr2);
    1121             : }

Generated by: LCOV version 1.13