LCOV - code coverage report
Current view: top level - source4/rpc_server/dnsserver - dnsdata.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 406 615 66.0 %
Date: 2024-06-13 04:01:37 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           6 : struct IP4_ARRAY *ip4_array_copy(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4)
      32             : {
      33             :         struct IP4_ARRAY *ret;
      34             : 
      35           6 :         if (!ip4) {
      36           6 :                 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          79 : 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          79 :         if (!ip4) {
      66          79 :                 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           8 : 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           8 :         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           8 :         ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
     113           8 :         if (!ret) {
     114           0 :                 return ret;
     115             :         }
     116           8 :         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           8 :         count = 0;
     122          24 :         for (i = 0; i < ip->AddrCount; i++) {
     123          16 :                 if (ip->AddrArray[i].MaxSa[0] == 0x02) {
     124             :                         /* Is ipv4 */
     125           8 :                         count++;
     126             :                 }
     127             :         }
     128           8 :         if (count == 0) {
     129             :                 /* should not happen */
     130           0 :                 ret->AddrCount = 0;
     131           0 :                 return ret;
     132             :         }
     133           8 :         ret->AddrArray = talloc_zero_array(mem_ctx, uint32_t, count);
     134           8 :         if (ret->AddrArray) {
     135           8 :                 curr = 0;
     136          24 :                 for (i = 0; i < ip->AddrCount; i++) {
     137          16 :                         if (ip->AddrArray[i].MaxSa[0] == 0x02) {
     138             :                                 /* Is ipv4 */
     139           8 :                                 memcpy(&ret->AddrArray[curr],
     140           8 :                                        &ip->AddrArray[i].MaxSa[4],
     141             :                                        sizeof(uint32_t));
     142           8 :                                 curr++;
     143             :                         }
     144             :                 }
     145             :         } else {
     146           0 :                 talloc_free(ret);
     147           0 :                 return NULL;
     148             :         }
     149           8 :         ret->AddrCount = curr;
     150           8 :         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         842 : int dns_split_name_components(TALLOC_CTX *tmp_ctx, const char *name, char ***components)
     185             : {
     186         842 :         char *str = NULL, *ptr, **list;
     187         842 :         int count = 0;
     188             : 
     189         842 :         if (name == NULL) {
     190           0 :                 return 0;
     191             :         }
     192             : 
     193         842 :         str = talloc_strdup(tmp_ctx, name);
     194         842 :         if (!str) {
     195           0 :                 goto failed;
     196             :         }
     197             : 
     198         842 :         list = talloc_zero_array(tmp_ctx, char *, 0);
     199         842 :         if (!list) {
     200           0 :                 goto failed;
     201             :         }
     202             : 
     203         842 :         ptr = strtok(str, ".");
     204        3186 :         while (ptr != NULL) {
     205        1574 :                 count++;
     206        1574 :                 list = talloc_realloc(tmp_ctx, list, char *, count);
     207        1574 :                 if (!list) {
     208           0 :                         goto failed;
     209             :                 }
     210        1574 :                 list[count-1] = talloc_strdup(tmp_ctx, ptr);
     211        1574 :                 if (list[count-1] == NULL) {
     212           0 :                         goto failed;
     213             :                 }
     214        1574 :                 ptr = strtok(NULL, ".");
     215             :         }
     216             : 
     217         842 :         talloc_free(str);
     218             : 
     219         842 :         *components = list;
     220         842 :         return count;
     221             : 
     222           0 : failed:
     223           0 :         TALLOC_FREE(str);
     224           0 :         return -1;
     225             : }
     226             : 
     227             : 
     228        2640 : 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        2640 :         if (strcmp(node_name, "@") == 0) {
     246           2 :                 prefix = talloc_strdup(tmp_ctx, zone_name);
     247        2638 :         } else if (strcmp(node_name, ".") == 0) {
     248           0 :                 prefix = NULL;
     249        2638 :         } else if (strchr(node_name, '.') == NULL) {
     250        2490 :                 prefix = talloc_strdup(tmp_ctx, node_name);
     251             :         } else {
     252         148 :                 zcount = dns_split_name_components(tmp_ctx, zone_name, &zlist);
     253         148 :                 ncount = dns_split_name_components(tmp_ctx, node_name, &nlist);
     254         148 :                 if (zcount < 0 || ncount < 0) {
     255           0 :                         return NULL;
     256             :                 }
     257             : 
     258         148 :                 if (ncount < zcount) {
     259          26 :                         prefix = talloc_strdup(tmp_ctx, node_name);
     260             :                 } else {
     261         122 :                         match = 0;
     262         383 :                         for (i=1; i<=zcount; i++) {
     263         298 :                                 if (strcasecmp(nlist[ncount-i], zlist[zcount-i]) != 0) {
     264          37 :                                         break;
     265             :                                 }
     266         261 :                                 match++;
     267             :                         }
     268             : 
     269         122 :                         if (match == ncount) {
     270           0 :                                 prefix = talloc_strdup(tmp_ctx, zone_name);
     271             :                         } else {
     272         122 :                                 prefix = talloc_strdup(tmp_ctx, nlist[0]);
     273         122 :                                 if (prefix != NULL) {
     274         210 :                                         for (i=1; i<ncount-match; i++) {
     275          88 :                                                 prefix = talloc_asprintf_append(prefix, ".%s", nlist[i]);
     276          88 :                                                 if (prefix == NULL) {
     277           0 :                                                         break;
     278             :                                                 }
     279             :                                         }
     280             :                                 }
     281             :                         }
     282             :                 }
     283             : 
     284         148 :                 talloc_free(zlist);
     285         148 :                 talloc_free(nlist);
     286             :         }
     287             : 
     288        2640 :         return prefix;
     289             : }
     290             : 
     291             : 
     292         676 : 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         676 :         ZERO_STRUCTP(dns);
     298             : 
     299         676 :         dns->wDataLength = dnsp->wDataLength;
     300         676 :         dns->wType = dnsp->wType;
     301         676 :         dns->dwFlags = dnsp->rank;
     302         676 :         dns->dwSerial = dnsp->dwSerial;
     303         676 :         dns->dwTtlSeconds = dnsp->dwTtlSeconds;
     304         676 :         dns->dwTimeStamp = dnsp->dwTimeStamp;
     305             : 
     306         676 :         switch (dnsp->wType) {
     307             : 
     308           0 :         case DNS_TYPE_TOMBSTONE:
     309           0 :                 dns->data.EntombedTime = dnsp->data.EntombedTime;
     310           0 :                 break;
     311             : 
     312          91 :         case DNS_TYPE_A:
     313          91 :                 dns->data.ipv4 = talloc_strdup(mem_ctx, dnsp->data.ipv4);
     314          91 :                 break;
     315             : 
     316          88 :         case DNS_TYPE_NS:
     317          88 :                 len = strlen(dnsp->data.ns);
     318          88 :                 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          88 :                         dns->data.name.len = len+1;
     323          88 :                         dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.ns);
     324             :                 }
     325          88 :                 break;
     326             : 
     327          59 :         case DNS_TYPE_CNAME:
     328          59 :                 len = strlen(dnsp->data.cname);
     329          59 :                 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          59 :                         dns->data.name.len = len+1;
     334          59 :                         dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.cname);
     335             :                 }
     336          59 :                 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          78 :         case DNS_TYPE_PTR:
     365          78 :                 dns->data.ptr.len = strlen(dnsp->data.ptr);
     366          78 :                 dns->data.ptr.str = talloc_strdup(mem_ctx, dnsp->data.ptr);
     367          78 :                 break;
     368             : 
     369          72 :         case DNS_TYPE_MX:
     370          72 :                 dns->data.mx.wPreference = dnsp->data.mx.wPriority;
     371          72 :                 len = strlen(dnsp->data.mx.nameTarget);
     372          72 :                 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          72 :                         dns->data.mx.nameExchange.len = len+1;
     377          72 :                         dns->data.mx.nameExchange.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.mx.nameTarget);
     378             :                 }
     379          72 :                 break;
     380             : 
     381          70 :         case DNS_TYPE_TXT:
     382          70 :                 dns->data.txt.count = dnsp->data.txt.count;
     383          70 :                 dns->data.txt.str = talloc_array(mem_ctx, struct DNS_RPC_NAME, dnsp->data.txt.count);
     384         153 :                 for (i=0; i<dnsp->data.txt.count; i++) {
     385          83 :                         dns->data.txt.str[i].str = talloc_strdup(mem_ctx, dnsp->data.txt.str[i]);
     386          83 :                         dns->data.txt.str[i].len = strlen(dnsp->data.txt.str[i]);
     387             :                 }
     388          70 :                 break;
     389             : 
     390          97 :         case DNS_TYPE_AAAA:
     391          97 :                 dns->data.ipv6 = talloc_strdup(mem_ctx, dnsp->data.ipv6);
     392          97 :                 break;
     393             : 
     394         121 :         case DNS_TYPE_SRV:
     395         121 :                 dns->data.srv.wPriority = dnsp->data.srv.wPriority;
     396         121 :                 dns->data.srv.wWeight = dnsp->data.srv.wWeight;
     397         121 :                 dns->data.srv.wPort = dnsp->data.srv.wPort;
     398         121 :                 len = strlen(dnsp->data.srv.nameTarget);
     399         121 :                 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         121 :                         dns->data.srv.nameTarget.len = len+1;
     404         121 :                         dns->data.srv.nameTarget.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.srv.nameTarget);
     405             :                 }
     406         121 :                 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         676 : }
     414             : 
     415        2139 : 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        2139 :         char *talloc_res = NULL;
     422        2139 :         struct dnsp_DnssrvRpcRecord *dnsp = NULL;
     423             : 
     424        2139 :         dnsp = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
     425        2139 :         if (dnsp == NULL) {
     426           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     427             :         }
     428             : 
     429        2139 :         dnsp->wDataLength = dns->wDataLength;
     430        2139 :         dnsp->wType = dns->wType;
     431        2139 :         dnsp->version = 5;
     432        2139 :         dnsp->rank = dns->dwFlags & 0x000000FF;
     433        2139 :         dnsp->dwSerial = dns->dwSerial;
     434        2139 :         dnsp->dwTtlSeconds = dns->dwTtlSeconds;
     435        2139 :         dnsp->dwTimeStamp = dns->dwTimeStamp;
     436             : 
     437        2139 :         switch (dns->wType) {
     438             : 
     439           0 :         case DNS_TYPE_TOMBSTONE:
     440           0 :                 dnsp->data.EntombedTime = dns->data.EntombedTime;
     441           0 :                 break;
     442             : 
     443         327 :         case DNS_TYPE_A:
     444         327 :                 talloc_res = talloc_strdup(mem_ctx, dns->data.ipv4);
     445         327 :                 if (talloc_res == NULL) {
     446           0 :                         goto fail_nomemory;
     447             :                 }
     448         327 :                 dnsp->data.ipv4 = talloc_res;
     449         327 :                 break;
     450             : 
     451         219 :         case DNS_TYPE_NS:
     452         219 :                 name = dns->data.name.str;
     453         219 :                 len = dns->data.name.len;
     454             : 
     455         219 :                 if (check_name) {
     456         132 :                         res = dns_name_check(mem_ctx, len, name);
     457         132 :                         if (!W_ERROR_IS_OK(res)) {
     458          20 :                                 return res;
     459             :                         }
     460             :                 }
     461             : 
     462         199 :                 if (len > 0 && name[len-1] == '.') {
     463          24 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     464          24 :                         if (talloc_res == NULL) {
     465           0 :                                 goto fail_nomemory;
     466             :                         }
     467          24 :                         dnsp->data.ns = talloc_res;
     468             :                 } else {
     469         175 :                         talloc_res = talloc_strdup(mem_ctx, name);
     470         175 :                         if (talloc_res == NULL) {
     471           0 :                                 goto fail_nomemory;
     472             :                         }
     473         175 :                         dnsp->data.ns = talloc_res;
     474             :                 }
     475             : 
     476         199 :                 break;
     477             : 
     478         232 :         case DNS_TYPE_CNAME:
     479         232 :                 name = dns->data.name.str;
     480         232 :                 len = dns->data.name.len;
     481             : 
     482         232 :                 if (check_name) {
     483         151 :                         res = dns_name_check(mem_ctx, len, name);
     484         151 :                         if (!W_ERROR_IS_OK(res)) {
     485          20 :                                 return res;
     486             :                         }
     487             :                 }
     488             : 
     489         212 :                 if (len > 0 && name[len-1] == '.') {
     490          22 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     491          22 :                         if (talloc_res == NULL) {
     492           0 :                                 goto fail_nomemory;
     493             :                         }
     494          22 :                         dnsp->data.cname = talloc_res;
     495             :                 } else {
     496         190 :                         talloc_res = talloc_strdup(mem_ctx, name);
     497         190 :                         if (talloc_res == NULL) {
     498           0 :                                 goto fail_nomemory;
     499             :                         }
     500         190 :                         dnsp->data.cname = talloc_res;
     501             :                 }
     502             : 
     503         212 :                 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         215 :         case DNS_TYPE_PTR:
     561         215 :                 name = dns->data.ptr.str;
     562         215 :                 len = dns->data.ptr.len;
     563             : 
     564         215 :                 if (check_name) {
     565         128 :                         res = dns_name_check(mem_ctx, len, name);
     566         128 :                         if (!W_ERROR_IS_OK(res)) {
     567          20 :                                 return res;
     568             :                         }
     569             :                 }
     570             : 
     571         195 :                 talloc_res = talloc_strdup(mem_ctx, name);
     572         195 :                 if (talloc_res == NULL) {
     573           0 :                         goto fail_nomemory;
     574             :                 }
     575         195 :                 dnsp->data.ptr = talloc_res;
     576             : 
     577         195 :                 break;
     578             : 
     579         213 :         case DNS_TYPE_MX:
     580         213 :                 dnsp->data.mx.wPriority = dns->data.mx.wPreference;
     581             : 
     582         213 :                 name = dns->data.mx.nameExchange.str;
     583         213 :                 len = dns->data.mx.nameExchange.len;
     584             : 
     585         213 :                 if (check_name) {
     586         125 :                         res = dns_name_check(mem_ctx, len, name);
     587         125 :                         if (!W_ERROR_IS_OK(res)) {
     588          18 :                                 return res;
     589             :                         }
     590             :                 }
     591             : 
     592         195 :                 if (len > 0 && name[len-1] == '.') {
     593          23 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     594          23 :                         if (talloc_res == NULL) {
     595           0 :                                 goto fail_nomemory;
     596             :                         }
     597          23 :                         dnsp->data.mx.nameTarget = talloc_res;
     598             :                 } else {
     599         172 :                         talloc_res = talloc_strdup(mem_ctx, name);
     600         172 :                         if (talloc_res == NULL) {
     601           0 :                                 goto fail_nomemory;
     602             :                         }
     603         172 :                         dnsp->data.mx.nameTarget = talloc_res;
     604             :                 }
     605             : 
     606         195 :                 break;
     607             : 
     608         298 :         case DNS_TYPE_TXT:
     609         298 :                 dnsp->data.txt.count = dns->data.txt.count;
     610         298 :                 dnsp->data.txt.str = talloc_array(mem_ctx, const char *, dns->data.txt.count);
     611         625 :                 for (i=0; i<dns->data.txt.count; i++) {
     612         327 :                         talloc_res = talloc_strdup(mem_ctx, dns->data.txt.str[i].str);
     613         327 :                         if (talloc_res == NULL) {
     614           0 :                                 goto fail_nomemory;
     615             :                         }
     616         327 :                         dnsp->data.txt.str[i] = talloc_res;
     617             :                 }
     618         298 :                 break;
     619             : 
     620         324 :         case DNS_TYPE_AAAA:
     621         324 :                 dnsp->data.ipv6 = talloc_strdup(mem_ctx, dns->data.ipv6);
     622         324 :                 break;
     623             : 
     624         311 :         case DNS_TYPE_SRV:
     625         311 :                 dnsp->data.srv.wPriority = dns->data.srv.wPriority;
     626         311 :                 dnsp->data.srv.wWeight = dns->data.srv.wWeight;
     627         311 :                 dnsp->data.srv.wPort = dns->data.srv.wPort;
     628             : 
     629         311 :                 name = dns->data.srv.nameTarget.str;
     630         311 :                 len = dns->data.srv.nameTarget.len;
     631             : 
     632         311 :                 if (check_name) {
     633         207 :                         res = dns_name_check(mem_ctx, len, name);
     634         207 :                         if (!W_ERROR_IS_OK(res)) {
     635          18 :                                 return res;
     636             :                         }
     637             :                 }
     638             : 
     639         293 :                 if (len > 0 && name[len-1] == '.') {
     640          36 :                         talloc_res = talloc_strndup(mem_ctx, name, len-1);
     641          36 :                         if (talloc_res == NULL) {
     642           0 :                                 goto fail_nomemory;
     643             :                         }
     644          36 :                         dnsp->data.srv.nameTarget = talloc_res;
     645             :                 } else {
     646         257 :                         talloc_res = talloc_strdup(mem_ctx, name);
     647         257 :                         if (talloc_res == NULL) {
     648           0 :                                 goto fail_nomemory;
     649             :                         }
     650         257 :                         dnsp->data.srv.nameTarget = talloc_res;
     651             :                 }
     652             : 
     653         293 :                 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        2043 :         *out_dnsp = dnsp;
     661        2043 :         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         525 : static struct dns_tree *dns_tree_init(TALLOC_CTX *mem_ctx, const char *name, void *data)
     669             : {
     670             :         struct dns_tree *tree;
     671             : 
     672         525 :         tree = talloc_zero(mem_ctx, struct dns_tree);
     673         525 :         if (tree == NULL) {
     674           0 :                 return NULL;
     675             :         }
     676             : 
     677         525 :         tree->name = talloc_strdup(tree, name);
     678         525 :         if (tree->name == NULL) {
     679           0 :                 talloc_free(tree);
     680           0 :                 return NULL;
     681             :         }
     682             : 
     683         525 :         tree->data = data;
     684             : 
     685         525 :         return tree;
     686             : }
     687             : 
     688             : 
     689             : /* Add a child one level below */
     690          24 : static struct dns_tree *dns_tree_add(struct dns_tree *tree, const char *name, void *data)
     691             : {
     692             :         struct dns_tree *node;
     693             : 
     694          24 :         node = talloc_zero(tree, struct dns_tree);
     695          24 :         if (node == NULL) {
     696           0 :                 return NULL;
     697             :         }
     698             : 
     699          24 :         node->name = talloc_strdup(tree, name);
     700          24 :         if (node->name == NULL) {
     701           0 :                 talloc_free(node);
     702           0 :                 return NULL;
     703             :         }
     704          24 :         node->level = tree->level + 1;
     705          24 :         node->num_children = 0;
     706          24 :         node->children = NULL;
     707          24 :         node->data = data;
     708             : 
     709          24 :         if (tree->num_children == 0) {
     710           7 :                 tree->children = talloc_zero(tree, struct dns_tree *);
     711             :         } else {
     712          17 :                 tree->children = talloc_realloc(tree, tree->children, struct dns_tree *,
     713             :                                                 tree->num_children+1);
     714             :         }
     715          24 :         if (tree->children == NULL) {
     716           0 :                 talloc_free(node);
     717           0 :                 return NULL;
     718             :         }
     719          24 :         tree->children[tree->num_children] = node;
     720          24 :         tree->num_children++;
     721             : 
     722          24 :         return node;
     723             : }
     724             : 
     725             : /* Find a node that matches the name components */
     726          21 : 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          21 :         *match_count = -1;
     732             : 
     733          21 :         if (strcmp(tree->name, "@") == 0) {
     734          11 :                 start = 0;
     735             :         } else {
     736          10 :                 if (strcasecmp(tree->name, nlist[ncount-1]) != 0) {
     737           0 :                         return NULL;
     738             :                 }
     739          10 :                 start = 1;
     740          10 :                 *match_count = 0;
     741             :         }
     742             : 
     743          21 :         node = tree;
     744          31 :         for (i=start; i<ncount; i++) {
     745          31 :                 if (node->num_children == 0) {
     746           4 :                         break;
     747             :                 }
     748          27 :                 next = NULL;
     749          72 :                 for (j=0; j<node->num_children; j++) {
     750          55 :                         if (strcasecmp(nlist[(ncount-1)-i], node->children[j]->name) == 0) {
     751          10 :                                 next = node->children[j];
     752          10 :                                 *match_count = i;
     753          10 :                                 break;
     754             :                         }
     755             :                 }
     756          27 :                 if (next == NULL) {
     757          17 :                         break;
     758             :                 } else {
     759          10 :                         node = next;
     760             :                 }
     761             :         }
     762             : 
     763          21 :         return node;
     764             : }
     765             : 
     766             : /* Build a 2-level tree for resulting dns names */
     767         525 : 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         525 :         rootcount = dns_split_name_components(mem_ctx, name, &nlist);
     776         525 :         if (rootcount <= 0) {
     777           0 :                 return NULL;
     778             :         }
     779             : 
     780         525 :         root = dns_tree_init(mem_ctx, nlist[rootcount-1], NULL);
     781         525 :         if (root == NULL) {
     782           0 :                 talloc_free(nlist);
     783           0 :                 return NULL;
     784             :         }
     785             : 
     786         525 :         tree = root;
     787         528 :         for (i=rootcount-2; i>=0; i--) {
     788           3 :                 tree = dns_tree_add(tree, nlist[i], NULL);
     789           3 :                 if (tree == NULL) {
     790           0 :                         goto failed;
     791             :                 }
     792             :         }
     793             : 
     794         525 :         base = tree;
     795             : 
     796             :         /* Add all names in the result in a tree */
     797        1069 :         for (i=0; i<res->count; i++) {
     798         544 :                 ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
     799         544 :                 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         544 :                 if (strcasecmp(ptr, name) == 0) {
     810         523 :                         base->data = res->msgs[i];
     811         523 :                         continue;
     812             :                 }
     813             : 
     814          21 :                 ncount = dns_split_name_components(root, ptr, &nlist);
     815          21 :                 if (ncount < 0) {
     816           0 :                         goto failed;
     817             :                 }
     818             : 
     819             :                 /* Find matching node */
     820          21 :                 tree = dns_tree_find(root, ncount, nlist, &match_count);
     821          21 :                 if (tree == NULL) {
     822           0 :                         goto failed;
     823             :                 }
     824             : 
     825             :                 /* If the node is on leaf, then add record data */
     826          21 :                 if (match_count+1 == ncount) {
     827           0 :                         tree->data = res->msgs[i];
     828             :                 }
     829             : 
     830             :                 /* Add missing name components */
     831          42 :                 for (level=match_count+1; level<ncount; level++) {
     832          21 :                         if (tree->level == rootcount+1) {
     833           0 :                                 break;
     834             :                         }
     835          21 :                         if (level == ncount-1) {
     836          21 :                                 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          21 :                         if (node == NULL) {
     841           0 :                                 goto failed;
     842             :                         }
     843          21 :                         tree = node;
     844             :                 }
     845             : 
     846          21 :                 talloc_free(nlist);
     847             :         }
     848             : 
     849             :         /* Mark the base record, so it can be found easily */
     850         525 :         base->level = -1;
     851             : 
     852         525 :         return root;
     853             : 
     854           0 : failed:
     855           0 :         talloc_free(nlist);
     856           0 :         talloc_free(root);
     857           0 :         return NULL;
     858             : }
     859             : 
     860             : 
     861         340 : static void _dns_add_name(TALLOC_CTX *mem_ctx, const char *name, char ***add_names, int *add_count)
     862             : {
     863             :         int i;
     864         340 :         char **ptr = *add_names;
     865         340 :         int count = *add_count;
     866             : 
     867         464 :         for (i=0; i<count; i++) {
     868         142 :                 if (strcasecmp(ptr[i], name) == 0) {
     869          18 :                         return;
     870             :                 }
     871             :         }
     872             : 
     873         322 :         ptr = talloc_realloc(mem_ctx, ptr, char *, count+1);
     874         322 :         if (ptr == NULL) {
     875           0 :                 return;
     876             :         }
     877             : 
     878         322 :         ptr[count] = talloc_strdup(mem_ctx, name);
     879         322 :         if (ptr[count] == NULL) {
     880           0 :                 talloc_free(ptr);
     881           0 :                 return;
     882             :         }
     883             : 
     884         322 :         *add_names = ptr;
     885         322 :         *add_count = count+1;
     886             : }
     887             : 
     888             : 
     889         676 : static void dns_find_additional_names(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *rec, char ***add_names, int *add_count)
     890             : {
     891         676 :         if (add_names == NULL) {
     892          13 :                 return;
     893             :         }
     894             : 
     895         663 :         switch (rec->wType) {
     896             : 
     897          88 :         case DNS_TYPE_NS:
     898          88 :                 _dns_add_name(mem_ctx, rec->data.ns, add_names, add_count);
     899          88 :                 break;
     900             : 
     901          59 :         case DNS_TYPE_CNAME:
     902          59 :                 _dns_add_name(mem_ctx, rec->data.cname, add_names, add_count);
     903          59 :                 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          72 :         case DNS_TYPE_MX:
     910          72 :                 _dns_add_name(mem_ctx, rec->data.mx.nameTarget, add_names, add_count);
     911          72 :                 break;
     912             : 
     913         121 :         case DNS_TYPE_SRV:
     914         121 :                 _dns_add_name(mem_ctx, rec->data.srv.nameTarget, add_names, add_count);
     915         121 :                 break;
     916             : 
     917         323 :         default:
     918         323 :                 break;
     919             :         }
     920             : }
     921             : 
     922             : 
     923         560 : 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         560 :         if (recs->count == 0) {
     940         526 :                 recs->rec = talloc_zero(recs, struct DNS_RPC_RECORDS);
     941             :         } else {
     942          34 :                 recs->rec = talloc_realloc(recs, recs->rec, struct DNS_RPC_RECORDS, recs->count+1);
     943             :         }
     944         560 :         if (recs->rec == NULL) {
     945           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     946             :         }
     947         560 :         i = recs->count;
     948         560 :         recs->rec[i].wLength = 0;
     949         560 :         recs->rec[i].wRecordCount = 0;
     950         560 :         recs->rec[i].dwChildCount = num_children;
     951         560 :         recs->rec[i].dwFlags = 0;
     952             : 
     953             :         /* The base records returned with empty name */
     954             :         /* Children records returned with names */
     955         560 :         if (branch_name == NULL) {
     956         526 :                 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, "");
     957         526 :                 recs->rec[i].dnsNodeName.len = 0;
     958             :         } else {
     959          34 :                 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, branch_name);
     960          34 :                 recs->rec[i].dnsNodeName.len = strlen(branch_name);
     961             :         }
     962         560 :         recs->rec[i].records = talloc_zero_array(recs, struct DNS_RPC_RECORD, 0);
     963         560 :         recs->count++;
     964             : 
     965             :         /* Allow empty records */
     966         560 :         if (msg == NULL) {
     967           2 :                 return WERR_OK;
     968             :         }
     969             : 
     970             :         /* Do not return RR records, if the node has children */
     971         558 :         if (branch_name != NULL && num_children > 0) {
     972           0 :                 return WERR_OK;
     973             :         }
     974             : 
     975         558 :         ptr = ldb_msg_find_attr_as_string(msg, "name", NULL);
     976         558 :         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         558 :         el = ldb_msg_find_element(msg, "dnsRecord");
     983         558 :         if (el == NULL || el->values == 0) {
     984           0 :                 return WERR_OK;
     985             :         }
     986             : 
     987             :         /* Add RR records */
     988        3120 :         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        1016 :                 ndr_err = ndr_pull_struct_blob(&el->values[j], mem_ctx, &dnsp_rec,
     994             :                                         (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
     995        1016 :                 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        1016 :                 if (record_type == DNS_TYPE_ALL || dnsp_rec.wType == record_type) {
    1002         678 :                         found = false;
    1003             : 
    1004         678 :                         if (select_flag & DNS_RPC_VIEW_AUTHORITY_DATA) {
    1005         652 :                                 if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1006         575 :                                         found = true;
    1007          77 :                                 } 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          75 :                                         if (branch_name == NULL) {
    1014          75 :                                                 found = true;
    1015             :                                         }
    1016             :                                 }
    1017             :                         }
    1018         678 :                         if (select_flag & DNS_RPC_VIEW_CACHE_DATA) {
    1019           0 :                                 if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1020           0 :                                         found = true;
    1021             :                                 }
    1022             :                         }
    1023         678 :                         if (select_flag & DNS_RPC_VIEW_GLUE_DATA) {
    1024           0 :                                 if (dnsp_rec.rank == DNS_RANK_GLUE) {
    1025           0 :                                         found = true;
    1026             :                                 }
    1027             :                         }
    1028         678 :                         if (select_flag & DNS_RPC_VIEW_ROOT_HINT_DATA) {
    1029          26 :                                 if (dnsp_rec.rank == DNS_RANK_ROOT_HINT) {
    1030          26 :                                         found = true;
    1031             :                                 }
    1032             :                         }
    1033             : 
    1034         678 :                         if (found) {
    1035         676 :                                 recs->rec[i].records = talloc_realloc(recs,
    1036             :                                                         recs->rec[i].records,
    1037             :                                                         struct DNS_RPC_RECORD,
    1038             :                                                         recs->rec[i].wRecordCount+1);
    1039         676 :                                 if (recs->rec[i].records == NULL) {
    1040           0 :                                         return WERR_NOT_ENOUGH_MEMORY;
    1041             :                                 }
    1042             : 
    1043         676 :                                 dns_rec = &recs->rec[i].records[recs->rec[i].wRecordCount];
    1044         676 :                                 dnsp_to_dns_copy(recs, &dnsp_rec, dns_rec);
    1045             : 
    1046             :                                 /* Fix record flags */
    1047         676 :                                 if (strcmp(ptr, "@") == 0) {
    1048          14 :                                         dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
    1049             : 
    1050          14 :                                         if (dnsp_rec.rank == DNS_RANK_ZONE) {
    1051           1 :                                                 dns_rec->dwFlags |= DNS_RPC_FLAG_AUTH_ZONE_ROOT;
    1052             :                                         }
    1053             :                                 }
    1054             : 
    1055         676 :                                 if (dns_rec->dwFlags == DNS_RANK_NS_GLUE) {
    1056          75 :                                         dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
    1057             :                                 }
    1058             : 
    1059         676 :                                 recs->rec[i].wRecordCount++;
    1060             : 
    1061         676 :                                 dns_find_additional_names(mem_ctx, &dnsp_rec, add_names, add_count);
    1062             :                         }
    1063             :                 }
    1064             :         }
    1065             : 
    1066         558 :         return WERR_OK;
    1067             : }
    1068             : 
    1069             : 
    1070          67 : 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          67 :         name1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
    1077          67 :         name2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
    1078          67 :         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          67 :         ptr1 = strrchr(name1, '.');
    1085          67 :         if (ptr1 == NULL) {
    1086          39 :                 ptr1 = name1;
    1087             :         } else {
    1088          28 :                 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          28 :                 if (*ptr1 == '.') {
    1098          28 :                         ptr1 = &ptr1[1];
    1099             :                 }
    1100             :         }
    1101             : 
    1102          67 :         ptr2 = strrchr(name2, '.');
    1103          67 :         if (ptr2 == NULL) {
    1104          39 :                 ptr2 = name2;
    1105             :         } else {
    1106          28 :                 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          28 :                 if (*ptr2 == '.') {
    1116          28 :                         ptr2 = &ptr2[1];
    1117             :                 }
    1118             :         }
    1119             : 
    1120          67 :         return strcasecmp(ptr1, ptr2);
    1121             : }

Generated by: LCOV version 1.13