rpz.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011-2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/buffer.h>
00025 #include <isc/mem.h>
00026 #include <isc/net.h>
00027 #include <isc/netaddr.h>
00028 #include <isc/print.h>
00029 #include <isc/stdlib.h>
00030 #include <isc/string.h>
00031 #include <isc/util.h>
00032 
00033 #include <dns/db.h>
00034 #include <dns/fixedname.h>
00035 #include <dns/log.h>
00036 #include <dns/rdata.h>
00037 #include <dns/rdataset.h>
00038 #include <dns/rdatastruct.h>
00039 #include <dns/result.h>
00040 #include <dns/rbt.h>
00041 #include <dns/rpz.h>
00042 #include <dns/view.h>
00043 
00044 
00045 /*
00046  * Parallel radix trees for databases of response policy IP addresses
00047  *
00048  * The radix or patricia trees are somewhat specialized to handle response
00049  * policy addresses by representing the two sets of IP addresses and name
00050  * server IP addresses in a single tree.  One set of IP addresses is
00051  * for rpz-ip policies or policies triggered by addresses in A or
00052  * AAAA records in responses.
00053  * The second set is for rpz-nsip policies or policies triggered by addresses
00054  * in A or AAAA records for NS records that are authorities for responses.
00055  *
00056  * Each leaf indicates that an IP address is listed in the IP address or the
00057  * name server IP address policy sub-zone (or both) of the corresponding
00058  * response response zone.  The policy data such as a CNAME or an A record
00059  * is kept in the policy zone.  After an IP address has been found in a radix
00060  * tree, the node in the policy zone's database is found by converting
00061  * the IP address to a domain name in a canonical form.
00062  *
00063  *
00064  * The response policy zone canonical form of an IPv6 address is one of:
00065  *      prefix.W.W.W.W.W.W.W.W
00066  *      prefix.WORDS.zz
00067  *      prefix.WORDS.zz.WORDS
00068  *      prefix.zz.WORDS
00069  *  where
00070  *      prefix  is the prefix length of the IPv6 address between 1 and 128
00071  *      W       is a number between 0 and 65535
00072  *      WORDS   is one or more numbers W separated with "."
00073  *      zz      corresponds to :: in the standard IPv6 text representation
00074  *
00075  * The canonical form of IPv4 addresses is:
00076  *      prefix.B.B.B.B
00077  *  where
00078  *      prefix  is the prefix length of the address between 1 and 32
00079  *      B       is a number between 0 and 255
00080  *
00081  * Names for IPv4 addresses are distinguished from IPv6 addresses by having
00082  * 5 labels all of which are numbers, and a prefix between 1 and 32.
00083  */
00084 
00085 
00086 /*
00087  * Use a private definition of IPv6 addresses because s6_addr32 is not
00088  * always defined and our IPv6 addresses are in non-standard byte order
00089  */
00090 typedef isc_uint32_t            dns_rpz_cidr_word_t;
00091 #define DNS_RPZ_CIDR_WORD_BITS  ((int)sizeof(dns_rpz_cidr_word_t)*8)
00092 #define DNS_RPZ_CIDR_KEY_BITS   ((int)sizeof(dns_rpz_cidr_key_t)*8)
00093 #define DNS_RPZ_CIDR_WORDS      (128/DNS_RPZ_CIDR_WORD_BITS)
00094 typedef struct {
00095         dns_rpz_cidr_word_t     w[DNS_RPZ_CIDR_WORDS];
00096 } dns_rpz_cidr_key_t;
00097 
00098 #define ADDR_V4MAPPED           0xffff
00099 #define KEY_IS_IPV4(prefix,ip) ((prefix) >= 96 && (ip)->w[0] == 0 &&    \
00100                                 (ip)->w[1] == 0 && (ip)->w[2] == ADDR_V4MAPPED)
00101 
00102 #define DNS_RPZ_WORD_MASK(b) ((b) == 0 ? (dns_rpz_cidr_word_t)(-1)      \
00103                               : ((dns_rpz_cidr_word_t)(-1)              \
00104                                  << (DNS_RPZ_CIDR_WORD_BITS - (b))))
00105 
00106 /*
00107  * Get bit #n from the array of words of an IP address.
00108  */
00109 #define DNS_RPZ_IP_BIT(ip, n) (1 & ((ip)->w[(n)/DNS_RPZ_CIDR_WORD_BITS] >>  \
00110                                     (DNS_RPZ_CIDR_WORD_BITS                 \
00111                                      - 1 - ((n) % DNS_RPZ_CIDR_WORD_BITS))))
00112 
00113 /*
00114  * A triplet of arrays of bits flagging the existence of
00115  * client-IP, IP, and NSIP policy triggers.
00116  */
00117 typedef struct dns_rpz_addr_zbits dns_rpz_addr_zbits_t;
00118 struct dns_rpz_addr_zbits {
00119         dns_rpz_zbits_t         client_ip;
00120         dns_rpz_zbits_t         ip;
00121         dns_rpz_zbits_t         nsip;
00122 };
00123 
00124 /*
00125  * A CIDR or radix tree node.
00126  */
00127 struct dns_rpz_cidr_node {
00128         dns_rpz_cidr_node_t     *parent;
00129         dns_rpz_cidr_node_t     *child[2];
00130         dns_rpz_cidr_key_t      ip;
00131         dns_rpz_prefix_t        prefix;
00132         dns_rpz_addr_zbits_t    set;
00133         dns_rpz_addr_zbits_t    sum;
00134 };
00135 
00136 /*
00137  * The data in a RBT node has two pairs of bits for policy zones.
00138  * One pair is for the corresponding name of the node such as example.com
00139  * and the other pair is for a wildcard child such as *.example.com.
00140  */
00141 /*
00142  * A pair of arrays of bits flagging the existence of
00143  * QNAME and NSDNAME policy triggers.
00144  */
00145 typedef struct dns_rpz_nm_zbits dns_rpz_nm_zbits_t;
00146 struct dns_rpz_nm_zbits {
00147         dns_rpz_zbits_t         qname;
00148         dns_rpz_zbits_t         ns;
00149 };
00150 
00151 typedef struct dns_rpz_nm_data dns_rpz_nm_data_t;
00152 struct dns_rpz_nm_data {
00153         dns_rpz_nm_zbits_t      set;
00154         dns_rpz_nm_zbits_t      wild;
00155 };
00156 
00157 #if 0
00158 /*
00159  * Catch a name while debugging.
00160  */
00161 static void
00162 catch_name(const dns_name_t *src_name, const char *tgt, const char *str) {
00163         dns_fixedname_t tgt_namef;
00164         dns_name_t *tgt_name;
00165 
00166         dns_fixedname_init(&tgt_namef);
00167         tgt_name = dns_fixedname_name(&tgt_namef);
00168         dns_name_fromstring(tgt_name, tgt, DNS_NAME_DOWNCASE, NULL);
00169         if (dns_name_equal(src_name, tgt_name)) {
00170                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
00171                               DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
00172                               "rpz hit failed: %s %s", str, tgt);
00173         }
00174 }
00175 #endif
00176 
00177 const char *
00178 dns_rpz_type2str(dns_rpz_type_t type) {
00179         switch (type) {
00180         case DNS_RPZ_TYPE_CLIENT_IP:
00181                 return ("CLIENT-IP");
00182         case DNS_RPZ_TYPE_QNAME:
00183                 return ("QNAME");
00184         case DNS_RPZ_TYPE_IP:
00185                 return ("IP");
00186         case DNS_RPZ_TYPE_NSIP:
00187                 return ("NSIP");
00188         case DNS_RPZ_TYPE_NSDNAME:
00189                 return ("NSDNAME");
00190         case DNS_RPZ_TYPE_BAD:
00191                 break;
00192         }
00193         FATAL_ERROR(__FILE__, __LINE__, "impossible rpz type %d", type);
00194         return ("impossible");
00195 }
00196 
00197 dns_rpz_policy_t
00198 dns_rpz_str2policy(const char *str) {
00199         static struct {
00200                 const char *str;
00201                 dns_rpz_policy_t policy;
00202         } tbl[] = {
00203                 {"given",       DNS_RPZ_POLICY_GIVEN},
00204                 {"disabled",    DNS_RPZ_POLICY_DISABLED},
00205                 {"passthru",    DNS_RPZ_POLICY_PASSTHRU},
00206                 {"drop",        DNS_RPZ_POLICY_DROP},
00207                 {"tcp-only",    DNS_RPZ_POLICY_TCP_ONLY},
00208                 {"nxdomain",    DNS_RPZ_POLICY_NXDOMAIN},
00209                 {"nodata",      DNS_RPZ_POLICY_NODATA},
00210                 {"cname",       DNS_RPZ_POLICY_CNAME},
00211                 {"no-op",       DNS_RPZ_POLICY_PASSTHRU},   /* old passthru */
00212         };
00213         unsigned int n;
00214 
00215         if (str == NULL)
00216                 return (DNS_RPZ_POLICY_ERROR);
00217         for (n = 0; n < sizeof(tbl)/sizeof(tbl[0]); ++n) {
00218                 if (!strcasecmp(tbl[n].str, str))
00219                         return (tbl[n].policy);
00220         }
00221         return (DNS_RPZ_POLICY_ERROR);
00222 }
00223 
00224 const char *
00225 dns_rpz_policy2str(dns_rpz_policy_t policy) {
00226         const char *str;
00227 
00228         switch (policy) {
00229         case DNS_RPZ_POLICY_PASSTHRU:
00230                 str = "PASSTHRU";
00231                 break;
00232         case DNS_RPZ_POLICY_DROP:
00233                 str = "DROP";
00234                 break;
00235         case DNS_RPZ_POLICY_TCP_ONLY:
00236                 str = "TCP-ONLY";
00237                 break;
00238         case DNS_RPZ_POLICY_NXDOMAIN:
00239                 str = "NXDOMAIN";
00240                 break;
00241         case DNS_RPZ_POLICY_NODATA:
00242                 str = "NODATA";
00243                 break;
00244         case DNS_RPZ_POLICY_RECORD:
00245                 str = "Local-Data";
00246                 break;
00247         case DNS_RPZ_POLICY_CNAME:
00248         case DNS_RPZ_POLICY_WILDCNAME:
00249                 str = "CNAME";
00250                 break;
00251         case DNS_RPZ_POLICY_MISS:
00252                 str = "MISS";
00253                 break;
00254         default:
00255                 str = "";
00256                 POST(str);
00257                 INSIST(0);
00258         }
00259         return (str);
00260 }
00261 
00262 static int
00263 zbit_to_num(dns_rpz_zbits_t zbit) {
00264         dns_rpz_num_t rpz_num;
00265 
00266         INSIST(zbit != 0);
00267         rpz_num = 0;
00268 #if DNS_RPZ_MAX_ZONES > 32
00269         if ((zbit & 0xffffffff00000000L) != 0) {
00270                 zbit >>= 32;
00271                 rpz_num += 32;
00272         }
00273 #endif
00274         if ((zbit & 0xffff0000) != 0) {
00275                 zbit >>= 16;
00276                 rpz_num += 16;
00277         }
00278         if ((zbit & 0xff00) != 0) {
00279                 zbit >>= 8;
00280                 rpz_num += 8;
00281         }
00282         if ((zbit & 0xf0) != 0) {
00283                 zbit >>= 4;
00284                 rpz_num += 4;
00285         }
00286         if ((zbit & 0xc) != 0) {
00287                 zbit >>= 2;
00288                 rpz_num += 2;
00289         }
00290         if ((zbit & 2) != 0)
00291                 ++rpz_num;
00292         return (rpz_num);
00293 }
00294 
00295 /*
00296  * Make a set of bit masks given one or more bits and their type.
00297  */
00298 static void
00299 make_addr_set(dns_rpz_addr_zbits_t *tgt_set, dns_rpz_zbits_t zbits,
00300               dns_rpz_type_t type)
00301 {
00302         switch (type) {
00303         case DNS_RPZ_TYPE_CLIENT_IP:
00304                 tgt_set->client_ip = zbits;
00305                 tgt_set->ip = 0;
00306                 tgt_set->nsip = 0;
00307                 break;
00308         case DNS_RPZ_TYPE_IP:
00309                 tgt_set->client_ip = 0;
00310                 tgt_set->ip = zbits;
00311                 tgt_set->nsip = 0;
00312                 break;
00313         case DNS_RPZ_TYPE_NSIP:
00314                 tgt_set->client_ip = 0;
00315                 tgt_set->ip = 0;
00316                 tgt_set->nsip = zbits;
00317                 break;
00318         default:
00319                 INSIST(0);
00320                 break;
00321         }
00322 }
00323 
00324 static void
00325 make_nm_set(dns_rpz_nm_zbits_t *tgt_set,
00326             dns_rpz_num_t rpz_num, dns_rpz_type_t type)
00327 {
00328         switch (type) {
00329         case DNS_RPZ_TYPE_QNAME:
00330                 tgt_set->qname = DNS_RPZ_ZBIT(rpz_num);
00331                 tgt_set->ns = 0;
00332                 break;
00333         case DNS_RPZ_TYPE_NSDNAME:
00334                 tgt_set->qname = 0;
00335                 tgt_set->ns = DNS_RPZ_ZBIT(rpz_num);
00336                 break;
00337         default:
00338                 INSIST(0);
00339                 break;
00340         }
00341 }
00342 
00343 /*
00344  * Mark a node and all of its parents as having client-IP, IP, or NSIP data
00345  */
00346 static void
00347 set_sum_pair(dns_rpz_cidr_node_t *cnode) {
00348         dns_rpz_cidr_node_t *child;
00349         dns_rpz_addr_zbits_t sum;
00350 
00351         do {
00352                 sum = cnode->set;
00353 
00354                 child = cnode->child[0];
00355                 if (child != NULL) {
00356                         sum.client_ip |= child->sum.client_ip;
00357                         sum.ip |= child->sum.ip;
00358                         sum.nsip |= child->sum.nsip;
00359                 }
00360 
00361                 child = cnode->child[1];
00362                 if (child != NULL) {
00363                         sum.client_ip |= child->sum.client_ip;
00364                         sum.ip |= child->sum.ip;
00365                         sum.nsip |= child->sum.nsip;
00366                 }
00367 
00368                 if (cnode->sum.client_ip == sum.client_ip &&
00369                     cnode->sum.ip == sum.ip &&
00370                     cnode->sum.nsip == sum.nsip)
00371                         break;
00372                 cnode->sum = sum;
00373                 cnode = cnode->parent;
00374         } while (cnode != NULL);
00375 }
00376 
00377 static void
00378 fix_qname_skip_recurse(dns_rpz_zones_t *rpzs) {
00379         dns_rpz_zbits_t zbits;
00380 
00381         /*
00382          * Get a mask covering all policy zones that are not subordinate to
00383          * other policy zones containing triggers that require that the
00384          * qname be resolved before they can be checked.
00385          */
00386         if (rpzs->p.qname_wait_recurse) {
00387                 zbits = 0;
00388         } else {
00389                 zbits = (rpzs->have.ipv4 || rpzs->have.ipv6 ||
00390                          rpzs->have.nsdname ||
00391                          rpzs->have.nsipv4 || rpzs->have.nsipv6);
00392                 if (zbits == 0) {
00393                         zbits = DNS_RPZ_ALL_ZBITS;
00394                 } else {
00395                         zbits = DNS_RPZ_ZMASK(zbit_to_num(zbits));
00396                 }
00397         }
00398         rpzs->have.qname_skip_recurse = zbits;
00399 
00400         rpzs->have.client_ip = rpzs->have.client_ipv4 | rpzs->have.client_ipv6;
00401         rpzs->have.ip = rpzs->have.ipv4 | rpzs->have.ipv6;
00402         rpzs->have.nsip = rpzs->have.nsipv4 | rpzs->have.nsipv6;
00403 }
00404 
00405 static void
00406 adj_trigger_cnt(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
00407                 dns_rpz_type_t rpz_type,
00408                 const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
00409                 isc_boolean_t inc)
00410 {
00411         int *cnt;
00412         dns_rpz_zbits_t *have;
00413 
00414         switch (rpz_type) {
00415         case DNS_RPZ_TYPE_CLIENT_IP:
00416                 REQUIRE(tgt_ip != NULL);
00417                 if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
00418                         cnt = &rpzs->triggers[rpz_num].client_ipv4;
00419                         have = &rpzs->have.client_ipv4;
00420                 } else {
00421                         cnt = &rpzs->triggers[rpz_num].client_ipv6;
00422                         have = &rpzs->have.client_ipv6;
00423                 }
00424                 break;
00425         case DNS_RPZ_TYPE_QNAME:
00426                 cnt = &rpzs->triggers[rpz_num].qname;
00427                 have = &rpzs->have.qname;
00428                 break;
00429         case DNS_RPZ_TYPE_IP:
00430                 REQUIRE(tgt_ip != NULL);
00431                 if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
00432                         cnt = &rpzs->triggers[rpz_num].ipv4;
00433                         have = &rpzs->have.ipv4;
00434                 } else {
00435                         cnt = &rpzs->triggers[rpz_num].ipv6;
00436                         have = &rpzs->have.ipv6;
00437                 }
00438                 break;
00439         case DNS_RPZ_TYPE_NSDNAME:
00440                 cnt = &rpzs->triggers[rpz_num].nsdname;
00441                 have = &rpzs->have.nsdname;
00442                 break;
00443         case DNS_RPZ_TYPE_NSIP:
00444                 REQUIRE(tgt_ip != NULL);
00445                 if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
00446                         cnt = &rpzs->triggers[rpz_num].nsipv4;
00447                         have = &rpzs->have.nsipv4;
00448                 } else {
00449                         cnt = &rpzs->triggers[rpz_num].nsipv6;
00450                         have = &rpzs->have.nsipv6;
00451                 }
00452                 break;
00453         default:
00454                 INSIST(0);
00455         }
00456 
00457         if (inc) {
00458                 if (++*cnt == 1) {
00459                         *have |= DNS_RPZ_ZBIT(rpz_num);
00460                         fix_qname_skip_recurse(rpzs);
00461                 }
00462         } else {
00463                 REQUIRE(*cnt > 0);
00464                 if (--*cnt == 0) {
00465                         *have &= ~DNS_RPZ_ZBIT(rpz_num);
00466                         fix_qname_skip_recurse(rpzs);
00467                 }
00468         }
00469 }
00470 
00471 static dns_rpz_cidr_node_t *
00472 new_node(dns_rpz_zones_t *rpzs,
00473          const dns_rpz_cidr_key_t *ip, dns_rpz_prefix_t prefix,
00474          const dns_rpz_cidr_node_t *child)
00475 {
00476         dns_rpz_cidr_node_t *new;
00477         int i, words, wlen;
00478 
00479         new = isc_mem_get(rpzs->mctx, sizeof(*new));
00480         if (new == NULL)
00481                 return (NULL);
00482         memset(new, 0, sizeof(*new));
00483 
00484         if (child != NULL)
00485                 new->sum = child->sum;
00486 
00487         new->prefix = prefix;
00488         words = prefix / DNS_RPZ_CIDR_WORD_BITS;
00489         wlen = prefix % DNS_RPZ_CIDR_WORD_BITS;
00490         i = 0;
00491         while (i < words) {
00492                 new->ip.w[i] = ip->w[i];
00493                 ++i;
00494         }
00495         if (wlen != 0) {
00496                 new->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen);
00497                 ++i;
00498         }
00499         while (i < DNS_RPZ_CIDR_WORDS)
00500                 new->ip.w[i++] = 0;
00501 
00502         return (new);
00503 }
00504 
00505 static void
00506 badname(int level, dns_name_t *name, const char *str1, const char *str2) {
00507         char namebuf[DNS_NAME_FORMATSIZE];
00508 
00509         /*
00510          * bin/tests/system/rpz/tests.sh looks for "invalid rpz".
00511          */
00512         if (level < DNS_RPZ_DEBUG_QUIET &&
00513             isc_log_wouldlog(dns_lctx, level)) {
00514                 dns_name_format(name, namebuf, sizeof(namebuf));
00515                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
00516                               DNS_LOGMODULE_RBTDB, level,
00517                               "invalid rpz IP address \"%s\"%s%s",
00518                               namebuf, str1, str2);
00519         }
00520 }
00521 
00522 /*
00523  * Convert an IP address from radix tree binary (host byte order) to
00524  * to its canonical response policy domain name without the origin of the
00525  * policy zone.
00526  */
00527 static isc_result_t
00528 ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
00529         dns_name_t *base_name, dns_name_t *ip_name)
00530 {
00531 #ifndef INET6_ADDRSTRLEN
00532 #define INET6_ADDRSTRLEN 46
00533 #endif
00534         int w[DNS_RPZ_CIDR_WORDS*2];
00535         char str[1+8+1+INET6_ADDRSTRLEN+1];
00536         isc_buffer_t buffer;
00537         isc_result_t result;
00538         isc_boolean_t zeros;
00539         int i, n, len;
00540 
00541         if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
00542                 len = snprintf(str, sizeof(str), "%d.%d.%d.%d.%d",
00543                                tgt_prefix - 96,
00544                                tgt_ip->w[3] & 0xff,
00545                                (tgt_ip->w[3]>>8) & 0xff,
00546                                (tgt_ip->w[3]>>16) & 0xff,
00547                                (tgt_ip->w[3]>>24) & 0xff);
00548                 if (len < 0 || len > (int)sizeof(str))
00549                         return (ISC_R_FAILURE);
00550         } else {
00551                 for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) {
00552                         w[i*2+1] = ((tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] >> 16)
00553                                     & 0xffff);
00554                         w[i*2] = tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] & 0xffff;
00555                 }
00556                 zeros = ISC_FALSE;
00557                 len = snprintf(str, sizeof(str), "%d", tgt_prefix);
00558                 if (len == -1)
00559                         return (ISC_R_FAILURE);
00560                 i = 0;
00561                 while (i < DNS_RPZ_CIDR_WORDS * 2) {
00562                         if (w[i] != 0 || zeros ||
00563                             i >= DNS_RPZ_CIDR_WORDS * 2 - 1 ||
00564                             w[i+1] != 0) {
00565                                 INSIST((size_t)len <= sizeof(str));
00566                                 n = snprintf(&str[len], sizeof(str) - len,
00567                                              ".%x", w[i++]);
00568                                 if (n < 0)
00569                                         return (ISC_R_FAILURE);
00570                                 len += n;
00571                         } else {
00572                                 zeros = ISC_TRUE;
00573                                 INSIST((size_t)len <= sizeof(str));
00574                                 n = snprintf(&str[len], sizeof(str) - len,
00575                                              ".zz");
00576                                 if (n < 0)
00577                                         return (ISC_R_FAILURE);
00578                                 len += n;
00579                                 i += 2;
00580                                 while (i < DNS_RPZ_CIDR_WORDS * 2 && w[i] == 0)
00581                                         ++i;
00582                         }
00583                         if (len >= (int)sizeof(str))
00584                                 return (ISC_R_FAILURE);
00585                 }
00586         }
00587 
00588         isc_buffer_init(&buffer, str, sizeof(str));
00589         isc_buffer_add(&buffer, len);
00590         result = dns_name_fromtext(ip_name, &buffer, base_name, 0, NULL);
00591         return (result);
00592 }
00593 
00594 /*
00595  * Determine the type a of a name in a response policy zone.
00596  */
00597 static dns_rpz_type_t
00598 type_from_name(dns_rpz_zone_t *rpz, dns_name_t *name) {
00599 
00600         if (dns_name_issubdomain(name, &rpz->ip))
00601                 return (DNS_RPZ_TYPE_IP);
00602 
00603         if (dns_name_issubdomain(name, &rpz->client_ip))
00604                 return (DNS_RPZ_TYPE_CLIENT_IP);
00605 
00606 #ifdef ENABLE_RPZ_NSIP
00607         if (dns_name_issubdomain(name, &rpz->nsip))
00608                 return (DNS_RPZ_TYPE_NSIP);
00609 #endif
00610 
00611 #ifdef ENABLE_RPZ_NSDNAME
00612         if (dns_name_issubdomain(name, &rpz->nsdname))
00613                 return (DNS_RPZ_TYPE_NSDNAME);
00614 #endif
00615 
00616         return (DNS_RPZ_TYPE_QNAME);
00617 }
00618 
00619 /*
00620  * Convert an IP address from canonical response policy domain name form
00621  * to radix tree binary (host byte order) for adding or deleting IP or NSIP
00622  * data.
00623  */
00624 static isc_result_t
00625 name2ipkey(int log_level,
00626            const dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
00627            dns_rpz_type_t rpz_type, dns_name_t *src_name,
00628            dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t *tgt_prefix,
00629            dns_rpz_addr_zbits_t *new_set)
00630 {
00631         dns_rpz_zone_t *rpz;
00632         char ip_str[DNS_NAME_FORMATSIZE];
00633         dns_offsets_t ip_name_offsets;
00634         dns_fixedname_t ip_name2f;
00635         dns_name_t ip_name, *ip_name2;
00636         const char *prefix_str, *cp, *end;
00637         char *cp2;
00638         int ip_labels;
00639         dns_rpz_prefix_t prefix;
00640         unsigned long prefix_num, l;
00641         isc_result_t result;
00642         int i;
00643 
00644         REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
00645         rpz = rpzs->zones[rpz_num];
00646         REQUIRE(rpz != NULL);
00647 
00648         make_addr_set(new_set, DNS_RPZ_ZBIT(rpz_num), rpz_type);
00649 
00650         ip_labels = dns_name_countlabels(src_name);
00651         if (rpz_type == DNS_RPZ_TYPE_QNAME)
00652                 ip_labels -= dns_name_countlabels(&rpz->origin);
00653         else
00654                 ip_labels -= dns_name_countlabels(&rpz->nsdname);
00655         if (ip_labels < 2) {
00656                 badname(log_level, src_name, "; too short", "");
00657                 return (ISC_R_FAILURE);
00658         }
00659         dns_name_init(&ip_name, ip_name_offsets);
00660         dns_name_getlabelsequence(src_name, 0, ip_labels, &ip_name);
00661 
00662         /*
00663          * Get text for the IP address
00664          */
00665         dns_name_format(&ip_name, ip_str, sizeof(ip_str));
00666         end = &ip_str[strlen(ip_str)+1];
00667         prefix_str = ip_str;
00668 
00669         prefix_num = strtoul(prefix_str, &cp2, 10);
00670         if (*cp2 != '.') {
00671                 badname(log_level, src_name,
00672                         "; invalid leading prefix length", "");
00673                 return (ISC_R_FAILURE);
00674         }
00675         *cp2 = '\0';
00676         if (prefix_num < 1U || prefix_num > 128U) {
00677                 badname(log_level, src_name,
00678                         "; invalid prefix length of ", prefix_str);
00679                 return (ISC_R_FAILURE);
00680         }
00681         cp = cp2+1;
00682 
00683         if (--ip_labels == 4 && !strchr(cp, 'z')) {
00684                 /*
00685                  * Convert an IPv4 address
00686                  * from the form "prefix.w.z.y.x"
00687                  */
00688                 if (prefix_num > 32U) {
00689                         badname(log_level, src_name,
00690                                 "; invalid IPv4 prefix length of ", prefix_str);
00691                         return (ISC_R_FAILURE);
00692                 }
00693                 prefix_num += 96;
00694                 *tgt_prefix = (dns_rpz_prefix_t)prefix_num;
00695                 tgt_ip->w[0] = 0;
00696                 tgt_ip->w[1] = 0;
00697                 tgt_ip->w[2] = ADDR_V4MAPPED;
00698                 tgt_ip->w[3] = 0;
00699                 for (i = 0; i < 32; i += 8) {
00700                         l = strtoul(cp, &cp2, 10);
00701                         if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) {
00702                                 if (*cp2 == '.')
00703                                         *cp2 = '\0';
00704                                 badname(log_level, src_name,
00705                                         "; invalid IPv4 octet ", cp);
00706                                 return (ISC_R_FAILURE);
00707                         }
00708                         tgt_ip->w[3] |= l << i;
00709                         cp = cp2 + 1;
00710                 }
00711         } else {
00712                 /*
00713                  * Convert a text IPv6 address.
00714                  */
00715                 *tgt_prefix = (dns_rpz_prefix_t)prefix_num;
00716                 for (i = 0;
00717                      ip_labels > 0 && i < DNS_RPZ_CIDR_WORDS * 2;
00718                      ip_labels--) {
00719                         if (cp[0] == 'z' && cp[1] == 'z' &&
00720                             (cp[2] == '.' || cp[2] == '\0') &&
00721                             i <= 6) {
00722                                 do {
00723                                         if ((i & 1) == 0)
00724                                             tgt_ip->w[3-i/2] = 0;
00725                                         ++i;
00726                                 } while (ip_labels + i <= 8);
00727                                 cp += 3;
00728                         } else {
00729                                 l = strtoul(cp, &cp2, 16);
00730                                 if (l > 0xffffu ||
00731                                     (*cp2 != '.' && *cp2 != '\0')) {
00732                                         if (*cp2 == '.')
00733                                             *cp2 = '\0';
00734                                         badname(log_level, src_name,
00735                                                 "; invalid IPv6 word ", cp);
00736                                         return (ISC_R_FAILURE);
00737                                 }
00738                                 if ((i & 1) == 0)
00739                                         tgt_ip->w[3-i/2] = l;
00740                                 else
00741                                         tgt_ip->w[3-i/2] |= l << 16;
00742                                 i++;
00743                                 cp = cp2 + 1;
00744                         }
00745                 }
00746         }
00747         if (cp != end) {
00748                 badname(log_level, src_name, "", "");
00749                 return (ISC_R_FAILURE);
00750         }
00751 
00752         /*
00753          * Check for 1s after the prefix length.
00754          */
00755         prefix = (dns_rpz_prefix_t)prefix_num;
00756         while (prefix < DNS_RPZ_CIDR_KEY_BITS) {
00757                 dns_rpz_cidr_word_t aword;
00758 
00759                 i = prefix % DNS_RPZ_CIDR_WORD_BITS;
00760                 aword = tgt_ip->w[prefix / DNS_RPZ_CIDR_WORD_BITS];
00761                 if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) {
00762                         badname(log_level, src_name,
00763                                 "; too small prefix length of ", prefix_str);
00764                         return (ISC_R_FAILURE);
00765                 }
00766                 prefix -= i;
00767                 prefix += DNS_RPZ_CIDR_WORD_BITS;
00768         }
00769 
00770         /*
00771          * Convert the address back to a canonical domain name
00772          * to ensure that the original name is in canonical form.
00773          */
00774         dns_fixedname_init(&ip_name2f);
00775         ip_name2 = dns_fixedname_name(&ip_name2f);
00776         result = ip2name(tgt_ip, (dns_rpz_prefix_t)prefix_num, NULL, ip_name2);
00777         if (result != ISC_R_SUCCESS || !dns_name_equal(&ip_name, ip_name2)) {
00778                 badname(log_level, src_name, "; not canonical", "");
00779                 return (ISC_R_FAILURE);
00780         }
00781 
00782         return (ISC_R_SUCCESS);
00783 }
00784 
00785 /*
00786  * Get trigger name and data bits for adding or deleting summary NSDNAME
00787  * or QNAME data.
00788  */
00789 static void
00790 name2data(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
00791           dns_rpz_type_t rpz_type, const dns_name_t *src_name,
00792           dns_name_t *trig_name, dns_rpz_nm_data_t *new_data)
00793 {
00794         dns_rpz_zone_t *rpz;
00795         dns_offsets_t tmp_name_offsets;
00796         dns_name_t tmp_name;
00797         unsigned int prefix_len, n;
00798 
00799         REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
00800         rpz = rpzs->zones[rpz_num];
00801         REQUIRE(rpz != NULL);
00802 
00803         /*
00804          * Handle wildcards by putting only the parent into the
00805          * summary RBT.  The summary database only causes a check of the
00806          * real policy zone where wildcards will be handled.
00807          */
00808         if (dns_name_iswildcard(src_name)) {
00809                 prefix_len = 1;
00810                 memset(&new_data->set, 0, sizeof(new_data->set));
00811                 make_nm_set(&new_data->wild, rpz_num, rpz_type);
00812         } else {
00813                 prefix_len = 0;
00814                 make_nm_set(&new_data->set, rpz_num, rpz_type);
00815                 memset(&new_data->wild, 0, sizeof(new_data->wild));
00816         }
00817 
00818         dns_name_init(&tmp_name, tmp_name_offsets);
00819         n = dns_name_countlabels(src_name);
00820         n -= prefix_len;
00821         if (rpz_type == DNS_RPZ_TYPE_QNAME)
00822                 n -= dns_name_countlabels(&rpz->origin);
00823         else
00824                 n -= dns_name_countlabels(&rpz->nsdname);
00825         dns_name_getlabelsequence(src_name, prefix_len, n, &tmp_name);
00826         (void)dns_name_concatenate(&tmp_name, dns_rootname, trig_name, NULL);
00827 }
00828 
00829 /*
00830  * Find the first differing bit in a key (IP address) word.
00831  */
00832 static inline int
00833 ffs_keybit(dns_rpz_cidr_word_t w) {
00834         int bit;
00835 
00836         bit = DNS_RPZ_CIDR_WORD_BITS-1;
00837         if ((w & 0xffff0000) != 0) {
00838                 w >>= 16;
00839                 bit -= 16;
00840         }
00841         if ((w & 0xff00) != 0) {
00842                 w >>= 8;
00843                 bit -= 8;
00844         }
00845         if ((w & 0xf0) != 0) {
00846                 w >>= 4;
00847                 bit -= 4;
00848         }
00849         if ((w & 0xc) != 0) {
00850                 w >>= 2;
00851                 bit -= 2;
00852         }
00853         if ((w & 2) != 0)
00854                 --bit;
00855         return (bit);
00856 }
00857 
00858 /*
00859  * Find the first differing bit in two keys (IP addresses).
00860  */
00861 static int
00862 diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1,
00863           const dns_rpz_cidr_key_t *key2, dns_rpz_prefix_t prefix2)
00864 {
00865         dns_rpz_cidr_word_t delta;
00866         dns_rpz_prefix_t maxbit, bit;
00867         int i;
00868 
00869         bit = 0;
00870         maxbit = ISC_MIN(prefix1, prefix2);
00871 
00872         /*
00873          * find the first differing words
00874          */
00875         for (i = 0;
00876              bit < maxbit;
00877              i++, bit += DNS_RPZ_CIDR_WORD_BITS) {
00878                 delta = key1->w[i] ^ key2->w[i];
00879                 if (delta != 0) {
00880                         bit += ffs_keybit(delta);
00881                         break;
00882                 }
00883         }
00884         return (ISC_MIN(bit, maxbit));
00885 }
00886 
00887 /*
00888  * Given a hit while searching the radix trees,
00889  * clear all bits for higher numbered zones.
00890  */
00891 static inline dns_rpz_zbits_t
00892 trim_zbits(dns_rpz_zbits_t zbits, dns_rpz_zbits_t found) {
00893         dns_rpz_zbits_t x;
00894 
00895         /*
00896          * Isolate the first or smallest numbered hit bit.
00897          * Make a mask of that bit and all smaller numbered bits.
00898          */
00899         x = zbits & found;
00900         x &= (~x + 1);
00901         x = (x << 1) - 1;
00902         return (zbits &= x);
00903 }
00904 
00905 /*
00906  * Search a radix tree for an IP address for ordinary lookup
00907  *      or for a CIDR block adding or deleting an entry
00908  *
00909  * Return ISC_R_SUCCESS, DNS_R_PARTIALMATCH, ISC_R_NOTFOUND,
00910  *          and *found=longest match node
00911  *      or with create==ISC_TRUE, ISC_R_EXISTS or ISC_R_NOMEMORY
00912  */
00913 static isc_result_t
00914 search(dns_rpz_zones_t *rpzs,
00915        const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
00916        const dns_rpz_addr_zbits_t *tgt_set, isc_boolean_t create,
00917        dns_rpz_cidr_node_t **found)
00918 {
00919         dns_rpz_cidr_node_t *cur, *parent, *child, *new_parent, *sibling;
00920         dns_rpz_addr_zbits_t set;
00921         int cur_num, child_num;
00922         dns_rpz_prefix_t dbit;
00923         isc_result_t find_result;
00924 
00925         set = *tgt_set;
00926         find_result = ISC_R_NOTFOUND;
00927         *found = NULL;
00928         cur = rpzs->cidr;
00929         parent = NULL;
00930         cur_num = 0;
00931         for (;;) {
00932                 if (cur == NULL) {
00933                         /*
00934                          * No child so we cannot go down.
00935                          * Quit with whatever we already found
00936                          * or add the target as a child of the current parent.
00937                          */
00938                         if (!create)
00939                                 return (find_result);
00940                         child = new_node(rpzs, tgt_ip, tgt_prefix, NULL);
00941                         if (child == NULL)
00942                                 return (ISC_R_NOMEMORY);
00943                         if (parent == NULL)
00944                                 rpzs->cidr = child;
00945                         else
00946                                 parent->child[cur_num] = child;
00947                         child->parent = parent;
00948                         child->set.client_ip |= tgt_set->client_ip;
00949                         child->set.ip |= tgt_set->ip;
00950                         child->set.nsip |= tgt_set->nsip;
00951                         set_sum_pair(child);
00952                         *found = cur;
00953                         return (ISC_R_SUCCESS);
00954                 }
00955 
00956                 if ((cur->sum.client_ip & set.client_ip) == 0 &&
00957                     (cur->sum.ip & set.ip) == 0 &&
00958                     (cur->sum.nsip & set.nsip) == 0) {
00959                         /*
00960                          * This node has no relevant data
00961                          * and is in none of the target trees.
00962                          * Pretend it does not exist if we are not adding.
00963                          *
00964                          * If we are adding, continue down to eventually add
00965                          * a node and mark/put this node in the correct tree.
00966                          */
00967                         if (!create)
00968                                 return (find_result);
00969                 }
00970 
00971                 dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->prefix);
00972                 /*
00973                  * dbit <= tgt_prefix and dbit <= cur->prefix always.
00974                  * We are finished searching if we matched all of the target.
00975                  */
00976                 if (dbit == tgt_prefix) {
00977                         if (tgt_prefix == cur->prefix) {
00978                                 /*
00979                                  * The node's key matches the target exactly.
00980                                  */
00981                                 if ((cur->set.client_ip & set.client_ip) != 0 ||
00982                                     (cur->set.ip & set.ip) != 0 ||
00983                                     (cur->set.nsip & set.nsip) != 0) {
00984                                         /*
00985                                          * It is the answer if it has data.
00986                                          */
00987                                         *found = cur;
00988                                         if (create) {
00989                                             find_result = ISC_R_EXISTS;
00990                                         } else {
00991                                             find_result = ISC_R_SUCCESS;
00992                                         }
00993                                 } else if (create) {
00994                                         /*
00995                                          * The node lacked relevant data,
00996                                          * but will have it now.
00997                                          */
00998                                         cur->set.client_ip |= tgt_set->client_ip;
00999                                         cur->set.ip |= tgt_set->ip;
01000                                         cur->set.nsip |= tgt_set->nsip;
01001                                         set_sum_pair(cur);
01002                                         *found = cur;
01003                                         find_result = ISC_R_SUCCESS;
01004                                 }
01005                                 return (find_result);
01006                         }
01007 
01008                         /*
01009                          * We know tgt_prefix < cur->prefix which means that
01010                          * the target is shorter than the current node.
01011                          * Add the target as the current node's parent.
01012                          */
01013                         if (!create)
01014                                 return (find_result);
01015 
01016                         new_parent = new_node(rpzs, tgt_ip, tgt_prefix, cur);
01017                         if (new_parent == NULL)
01018                                 return (ISC_R_NOMEMORY);
01019                         new_parent->parent = parent;
01020                         if (parent == NULL)
01021                                 rpzs->cidr = new_parent;
01022                         else
01023                                 parent->child[cur_num] = new_parent;
01024                         child_num = DNS_RPZ_IP_BIT(&cur->ip, tgt_prefix+1);
01025                         new_parent->child[child_num] = cur;
01026                         cur->parent = new_parent;
01027                         new_parent->set = *tgt_set;
01028                         set_sum_pair(new_parent);
01029                         *found = new_parent;
01030                         return (ISC_R_SUCCESS);
01031                 }
01032 
01033                 if (dbit == cur->prefix) {
01034                         if ((cur->set.client_ip & set.client_ip) != 0 ||
01035                             (cur->set.ip & set.ip) != 0 ||
01036                             (cur->set.nsip & set.nsip) != 0) {
01037                                 /*
01038                                  * We have a partial match between of all of the
01039                                  * current node but only part of the target.
01040                                  * Continue searching for other hits in the
01041                                  * same or lower numbered trees.
01042                                  */
01043                                 find_result = DNS_R_PARTIALMATCH;
01044                                 *found = cur;
01045                                 set.client_ip = trim_zbits(set.ip,
01046                                                         cur->set.client_ip);
01047                                 set.ip = trim_zbits(set.ip,
01048                                                     cur->set.ip);
01049                                 set.nsip = trim_zbits(set.nsip,
01050                                                       cur->set.nsip);
01051                         }
01052                         parent = cur;
01053                         cur_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
01054                         cur = cur->child[cur_num];
01055                         continue;
01056                 }
01057 
01058 
01059                 /*
01060                  * dbit < tgt_prefix and dbit < cur->prefix,
01061                  * so we failed to match both the target and the current node.
01062                  * Insert a fork of a parent above the current node and
01063                  * add the target as a sibling of the current node
01064                  */
01065                 if (!create)
01066                         return (find_result);
01067 
01068                 sibling = new_node(rpzs, tgt_ip, tgt_prefix, NULL);
01069                 if (sibling == NULL)
01070                         return (ISC_R_NOMEMORY);
01071                 new_parent = new_node(rpzs, tgt_ip, dbit, cur);
01072                 if (new_parent == NULL) {
01073                         isc_mem_put(rpzs->mctx, sibling, sizeof(*sibling));
01074                         return (ISC_R_NOMEMORY);
01075                 }
01076                 new_parent->parent = parent;
01077                 if (parent == NULL)
01078                         rpzs->cidr = new_parent;
01079                 else
01080                         parent->child[cur_num] = new_parent;
01081                 child_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
01082                 new_parent->child[child_num] = sibling;
01083                 new_parent->child[1-child_num] = cur;
01084                 cur->parent = new_parent;
01085                 sibling->parent = new_parent;
01086                 sibling->set = *tgt_set;
01087                 set_sum_pair(sibling);
01088                 *found = sibling;
01089                 return (ISC_R_SUCCESS);
01090         }
01091 }
01092 
01093 /*
01094  * Add an IP address to the radix tree.
01095  */
01096 static isc_result_t
01097 add_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
01098          dns_rpz_type_t rpz_type, dns_name_t *src_name)
01099 {
01100         dns_rpz_cidr_key_t tgt_ip;
01101         dns_rpz_prefix_t tgt_prefix;
01102         dns_rpz_addr_zbits_t set;
01103         dns_rpz_cidr_node_t *found;
01104         isc_result_t result;
01105 
01106         result = name2ipkey(DNS_RPZ_ERROR_LEVEL, rpzs, rpz_num, rpz_type,
01107                             src_name, &tgt_ip, &tgt_prefix, &set);
01108         /*
01109          * Log complaints about bad owner names but let the zone load.
01110          */
01111         if (result != ISC_R_SUCCESS)
01112                 return (ISC_R_SUCCESS);
01113 
01114         result = search(rpzs, &tgt_ip, tgt_prefix, &set, ISC_TRUE, &found);
01115         if (result != ISC_R_SUCCESS) {
01116                 char namebuf[DNS_NAME_FORMATSIZE];
01117 
01118                 /*
01119                  * Do not worry if the radix tree already exists,
01120                  * because diff_apply() likes to add nodes before deleting.
01121                  */
01122                 if (result == ISC_R_EXISTS)
01123                         return (ISC_R_SUCCESS);
01124 
01125                 /*
01126                  * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
01127                  */
01128                 dns_name_format(src_name, namebuf, sizeof(namebuf));
01129                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
01130                               DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
01131                               "rpz add_cidr(%s) failed: %s",
01132                               namebuf, isc_result_totext(result));
01133                 return (result);
01134         }
01135 
01136         adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, ISC_TRUE);
01137         return (result);
01138 }
01139 
01140 static isc_result_t
01141 add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name,
01142          const dns_rpz_nm_data_t *new_data)
01143 {
01144         dns_rbtnode_t *nmnode;
01145         dns_rpz_nm_data_t *nm_data;
01146         isc_result_t result;
01147 
01148         nmnode = NULL;
01149         result = dns_rbt_addnode(rpzs->rbt, trig_name, &nmnode);
01150         switch (result) {
01151         case ISC_R_SUCCESS:
01152         case ISC_R_EXISTS:
01153                 nm_data = nmnode->data;
01154                 if (nm_data == NULL) {
01155                         nm_data = isc_mem_get(rpzs->mctx, sizeof(*nm_data));
01156                         if (nm_data == NULL)
01157                                 return (ISC_R_NOMEMORY);
01158                         *nm_data = *new_data;
01159                         nmnode->data = nm_data;
01160                         return (ISC_R_SUCCESS);
01161                 }
01162                 break;
01163         default:
01164                 return (result);
01165         }
01166 
01167         /*
01168          * Do not count bits that are already present
01169          */
01170         if ((nm_data->set.qname & new_data->set.qname) != 0 ||
01171             (nm_data->set.ns & new_data->set.ns) != 0 ||
01172             (nm_data->wild.qname & new_data->wild.qname) != 0 ||
01173             (nm_data->wild.ns & new_data->wild.ns) != 0)
01174                 return (ISC_R_EXISTS);
01175 
01176         nm_data->set.qname |= new_data->set.qname;
01177         nm_data->set.ns |= new_data->set.ns;
01178         nm_data->wild.qname |= new_data->wild.qname;
01179         nm_data->wild.ns |= new_data->wild.ns;
01180         return (ISC_R_SUCCESS);
01181 }
01182 
01183 static isc_result_t
01184 add_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
01185          dns_rpz_type_t rpz_type, dns_name_t *src_name)
01186 {
01187         dns_rpz_nm_data_t new_data;
01188         dns_fixedname_t trig_namef;
01189         dns_name_t *trig_name;
01190         isc_result_t result;
01191 
01192         /*
01193          * No need for a summary database of names with only 1 policy zone.
01194          */
01195         if (rpzs->p.num_zones <= 1) {
01196                 adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_TRUE);
01197                 return (ISC_R_SUCCESS);
01198         }
01199 
01200         dns_fixedname_init(&trig_namef);
01201         trig_name = dns_fixedname_name(&trig_namef);
01202         name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &new_data);
01203 
01204         result = add_nm(rpzs, trig_name, &new_data);
01205 
01206         /*
01207          * Do not worry if the node already exists,
01208          * because diff_apply() likes to add nodes before deleting.
01209          */
01210         if (result == ISC_R_EXISTS)
01211                 return (ISC_R_SUCCESS);
01212         if (result == ISC_R_SUCCESS)
01213                 adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_TRUE);
01214         return (result);
01215 }
01216 
01217 /*
01218  * Callback to free the data for a node in the summary RBT database.
01219  */
01220 static void
01221 rpz_node_deleter(void *nm_data, void *mctx) {
01222         isc_mem_put(mctx, nm_data, sizeof(dns_rpz_nm_data_t));
01223 }
01224 
01225 /*
01226  * Get ready for a new set of policy zones.
01227  */
01228 isc_result_t
01229 dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx) {
01230         dns_rpz_zones_t *new;
01231         isc_result_t result;
01232 
01233         REQUIRE(rpzsp != NULL && *rpzsp == NULL);
01234 
01235         *rpzsp = NULL;
01236 
01237         new = isc_mem_get(mctx, sizeof(*new));
01238         if (new == NULL)
01239                 return (ISC_R_NOMEMORY);
01240         memset(new, 0, sizeof(*new));
01241 
01242         result = isc_mutex_init(&new->search_lock);
01243         if (result != ISC_R_SUCCESS) {
01244                 isc_mem_put(mctx, new, sizeof(*new));
01245                 return (result);
01246         }
01247 
01248         result = isc_mutex_init(&new->maint_lock);
01249         if (result != ISC_R_SUCCESS) {
01250                 DESTROYLOCK(&new->search_lock);
01251                 isc_mem_put(mctx, new, sizeof(*new));
01252                 return (result);
01253         }
01254 
01255         result = isc_refcount_init(&new->refs, 1);
01256         if (result != ISC_R_SUCCESS) {
01257                 DESTROYLOCK(&new->maint_lock);
01258                 DESTROYLOCK(&new->search_lock);
01259                 isc_mem_put(mctx, new, sizeof(*new));
01260                 return (result);
01261         }
01262 
01263         result = dns_rbt_create(mctx, rpz_node_deleter, mctx, &new->rbt);
01264         if (result != ISC_R_SUCCESS) {
01265                 isc_refcount_decrement(&new->refs, NULL);
01266                 isc_refcount_destroy(&new->refs);
01267                 DESTROYLOCK(&new->maint_lock);
01268                 DESTROYLOCK(&new->search_lock);
01269                 isc_mem_put(mctx, new, sizeof(*new));
01270                 return (result);
01271         }
01272 
01273         isc_mem_attach(mctx, &new->mctx);
01274 
01275         *rpzsp = new;
01276         return (ISC_R_SUCCESS);
01277 }
01278 
01279 /*
01280  * Free the radix tree of a response policy database.
01281  */
01282 static void
01283 cidr_free(dns_rpz_zones_t *rpzs) {
01284         dns_rpz_cidr_node_t *cur, *child, *parent;
01285 
01286         cur = rpzs->cidr;
01287         while (cur != NULL) {
01288                 /* Depth first. */
01289                 child = cur->child[0];
01290                 if (child != NULL) {
01291                         cur = child;
01292                         continue;
01293                 }
01294                 child = cur->child[1];
01295                 if (child != NULL) {
01296                         cur = child;
01297                         continue;
01298                 }
01299 
01300                 /* Delete this leaf and go up. */
01301                 parent = cur->parent;
01302                 if (parent == NULL)
01303                         rpzs->cidr = NULL;
01304                 else
01305                         parent->child[parent->child[1] == cur] = NULL;
01306                 isc_mem_put(rpzs->mctx, cur, sizeof(*cur));
01307                 cur = parent;
01308         }
01309 }
01310 
01311 /*
01312  * Discard a response policy zone blob
01313  * before discarding the overall rpz structure.
01314  */
01315 static void
01316 rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) {
01317         dns_rpz_zone_t *rpz;
01318         unsigned int refs;
01319 
01320         rpz = *rpzp;
01321         *rpzp = NULL;
01322         isc_refcount_decrement(&rpz->refs, &refs);
01323         if (refs != 0)
01324                 return;
01325         isc_refcount_destroy(&rpz->refs);
01326 
01327         if (dns_name_dynamic(&rpz->origin))
01328                 dns_name_free(&rpz->origin, rpzs->mctx);
01329         if (dns_name_dynamic(&rpz->client_ip))
01330                 dns_name_free(&rpz->client_ip, rpzs->mctx);
01331         if (dns_name_dynamic(&rpz->ip))
01332                 dns_name_free(&rpz->ip, rpzs->mctx);
01333         if (dns_name_dynamic(&rpz->nsdname))
01334                 dns_name_free(&rpz->nsdname, rpzs->mctx);
01335         if (dns_name_dynamic(&rpz->nsip))
01336                 dns_name_free(&rpz->nsip, rpzs->mctx);
01337         if (dns_name_dynamic(&rpz->passthru))
01338                 dns_name_free(&rpz->passthru, rpzs->mctx);
01339         if (dns_name_dynamic(&rpz->drop))
01340                 dns_name_free(&rpz->drop, rpzs->mctx);
01341         if (dns_name_dynamic(&rpz->tcp_only))
01342                 dns_name_free(&rpz->tcp_only, rpzs->mctx);
01343         if (dns_name_dynamic(&rpz->cname))
01344                 dns_name_free(&rpz->cname, rpzs->mctx);
01345 
01346         isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz));
01347 }
01348 
01349 void
01350 dns_rpz_attach_rpzs(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **rpzsp) {
01351         REQUIRE(rpzsp != NULL && *rpzsp == NULL);
01352         isc_refcount_increment(&rpzs->refs, NULL);
01353         *rpzsp = rpzs;
01354 }
01355 
01356 /*
01357  * Forget a view's policy zones.
01358  */
01359 void
01360 dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
01361         dns_rpz_zones_t *rpzs;
01362         dns_rpz_zone_t *rpz;
01363         dns_rpz_num_t rpz_num;
01364         unsigned int refs;
01365 
01366         REQUIRE(rpzsp != NULL);
01367         rpzs = *rpzsp;
01368         REQUIRE(rpzs != NULL);
01369 
01370         *rpzsp = NULL;
01371         isc_refcount_decrement(&rpzs->refs, &refs);
01372 
01373         /*
01374          * Forget the last of view's rpz machinery after the last reference.
01375          */
01376         if (refs == 0) {
01377                 for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) {
01378                         rpz = rpzs->zones[rpz_num];
01379                         rpzs->zones[rpz_num] = NULL;
01380                         if (rpz != NULL)
01381                                 rpz_detach(&rpz, rpzs);
01382                 }
01383 
01384                 cidr_free(rpzs);
01385                 dns_rbt_destroy(&rpzs->rbt);
01386                 DESTROYLOCK(&rpzs->maint_lock);
01387                 DESTROYLOCK(&rpzs->search_lock);
01388                 isc_refcount_destroy(&rpzs->refs);
01389                 isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
01390         }
01391 }
01392 
01393 /*
01394  * Create empty summary database to load one zone.
01395  * The RBTDB write tree lock must be held.
01396  */
01397 isc_result_t
01398 dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp,
01399                   dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num)
01400 {
01401         dns_rpz_zones_t *load_rpzs;
01402         dns_rpz_zone_t *rpz;
01403         dns_rpz_zbits_t tgt;
01404         isc_result_t result;
01405 
01406         REQUIRE(rpz_num < rpzs->p.num_zones);
01407         rpz = rpzs->zones[rpz_num];
01408         REQUIRE(rpz != NULL);
01409 
01410         /*
01411          * When reloading a zone, there are usually records among the summary
01412          * data for the zone.  Some of those records might be deleted by the
01413          * reloaded zone data.  To deal with that case:
01414          *    reload the new zone data into a new blank summary database
01415          *    if the reload fails, discard the new summary database
01416          *    if the new zone data is acceptable, copy the records for the
01417          *      other zones into the new summary database and replace the
01418          *      old summary database with the new.
01419          *
01420          * At the first attempt to load a zone, there is no summary data
01421          * for the zone and so no records that need to be deleted.
01422          * This is also the most common case of policy zone loading.
01423          * Most policy zone maintenance should be by incremental changes
01424          * and so by the addition and deletion of individual records.
01425          * Detect that case and load records the first time into the
01426          * operational summary database
01427          */
01428         tgt = DNS_RPZ_ZBIT(rpz_num);
01429         LOCK(&rpzs->maint_lock);
01430         LOCK(&rpzs->search_lock);
01431         if ((rpzs->load_begun & tgt) == 0) {
01432                 /*
01433                  * There is no existing version of the target zone.
01434                  */
01435                 rpzs->load_begun |= tgt;
01436                 dns_rpz_attach_rpzs(rpzs, load_rpzsp);
01437                 UNLOCK(&rpzs->search_lock);
01438                 UNLOCK(&rpzs->maint_lock);
01439 
01440         } else {
01441                 UNLOCK(&rpzs->search_lock);
01442                 UNLOCK(&rpzs->maint_lock);
01443 
01444                 result = dns_rpz_new_zones(load_rpzsp, rpzs->mctx);
01445                 if (result != ISC_R_SUCCESS)
01446                         return (result);
01447                 load_rpzs = *load_rpzsp;
01448                 load_rpzs->p.num_zones = rpzs->p.num_zones;
01449                 load_rpzs->total_triggers = rpzs->total_triggers;
01450                 memmove(load_rpzs->triggers, rpzs->triggers,
01451                         sizeof(load_rpzs->triggers));
01452                 memset(&load_rpzs->triggers[rpz_num], 0,
01453                        sizeof(load_rpzs->triggers[rpz_num]));
01454                 load_rpzs->zones[rpz_num] = rpz;
01455                 isc_refcount_increment(&rpz->refs, NULL);
01456         }
01457 
01458         return (ISC_R_SUCCESS);
01459 }
01460 
01461 static void
01462 fix_triggers(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
01463         dns_rpz_num_t n;
01464         dns_rpz_triggers_t old_totals;
01465         dns_rpz_zbits_t zbit;
01466         char namebuf[DNS_NAME_FORMATSIZE];
01467 
01468 #       define SET_TRIG(n, zbit, type)                                  \
01469         if (rpzs->triggers[n].type == 0) {                              \
01470                 rpzs->have.type &= ~zbit;                               \
01471         } else {                                                        \
01472                 rpzs->total_triggers.type += rpzs->triggers[n].type;    \
01473                 rpzs->have.type |= zbit;                                \
01474         }
01475 
01476         memmove(&old_totals, &rpzs->total_triggers, sizeof(old_totals));
01477         memset(&rpzs->total_triggers, 0, sizeof(rpzs->total_triggers));
01478         for (n = 0; n < rpzs->p.num_zones; ++n) {
01479                 zbit = DNS_RPZ_ZBIT(n);
01480                 SET_TRIG(n, zbit, client_ipv4);
01481                 SET_TRIG(n, zbit, client_ipv6);
01482                 SET_TRIG(n, zbit, qname);
01483                 SET_TRIG(n, zbit, ipv4);
01484                 SET_TRIG(n, zbit, ipv6);
01485                 SET_TRIG(n, zbit, nsdname);
01486                 SET_TRIG(n, zbit, nsipv4);
01487                 SET_TRIG(n, zbit, nsipv6);
01488         }
01489 
01490         fix_qname_skip_recurse(rpzs);
01491 
01492         dns_name_format(&rpzs->zones[rpz_num]->origin,
01493                         namebuf, sizeof(namebuf));
01494         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
01495                       DNS_LOGMODULE_RBTDB, DNS_RPZ_INFO_LEVEL,
01496                       "(re)loading policy zone '%s' changed from"
01497                       " %d to %d qname, %d to %d nsdname,"
01498                       " %d to %d IP, %d to %d NSIP entries",
01499                       namebuf,
01500                       old_totals.qname, rpzs->total_triggers.qname,
01501                       old_totals.nsdname, rpzs->total_triggers.nsdname,
01502                       old_totals.ipv4 + old_totals.ipv6,
01503                       rpzs->total_triggers.ipv4 + rpzs->total_triggers.ipv6,
01504                       old_totals.nsipv4 + old_totals.nsipv6,
01505                       rpzs->total_triggers.nsipv4 + rpzs->total_triggers.nsipv6);
01506 
01507 #       undef SET_TRIG
01508 }
01509 
01510 /*
01511  * Finish loading one zone.
01512  * The RBTDB write tree lock must be held.
01513  */
01514 isc_result_t
01515 dns_rpz_ready(dns_rpz_zones_t *rpzs,
01516               dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num)
01517 {
01518         dns_rpz_zones_t *load_rpzs;
01519         const dns_rpz_cidr_node_t *cnode, *next_cnode, *parent_cnode;
01520         dns_rpz_cidr_node_t *found;
01521         dns_rpz_zbits_t new_bit;
01522         dns_rpz_addr_zbits_t new_ip;
01523         dns_rbt_t *rbt;
01524         dns_rbtnodechain_t chain;
01525         dns_rbtnode_t *nmnode;
01526         dns_rpz_nm_data_t *nm_data, new_data;
01527         dns_fixedname_t labelf, originf, namef;
01528         dns_name_t *label, *origin, *name;
01529         isc_result_t result;
01530 
01531         INSIST(rpzs != NULL);
01532         LOCK(&rpzs->maint_lock);
01533         load_rpzs = *load_rpzsp;
01534         INSIST(load_rpzs != NULL);
01535 
01536         if (load_rpzs == rpzs) {
01537                 /*
01538                  * This is a successful initial zone loading,
01539                  * perhaps for a new instance of a view.
01540                  */
01541                 fix_triggers(rpzs, rpz_num);
01542                 UNLOCK(&rpzs->maint_lock);
01543                 dns_rpz_detach_rpzs(load_rpzsp);
01544                 return (ISC_R_SUCCESS);
01545         }
01546 
01547         LOCK(&load_rpzs->maint_lock);
01548         LOCK(&load_rpzs->search_lock);
01549 
01550         /*
01551          * Unless there is only one policy zone, copy the other policy zones
01552          * from the old policy structure to the new summary databases.
01553          */
01554         if (rpzs->p.num_zones > 1) {
01555                 new_bit = ~DNS_RPZ_ZBIT(rpz_num);
01556 
01557                 /*
01558                  * Copy to the radix tree.
01559                  */
01560                 for (cnode = rpzs->cidr; cnode != NULL; cnode = next_cnode) {
01561                         new_ip.ip = cnode->set.ip & new_bit;
01562                         new_ip.client_ip = cnode->set.client_ip & new_bit;
01563                         new_ip.nsip = cnode->set.nsip & new_bit;
01564                         if (new_ip.client_ip != 0 ||
01565                             new_ip.ip != 0 ||
01566                             new_ip.nsip != 0) {
01567                                 result = search(load_rpzs,
01568                                                 &cnode->ip, cnode->prefix,
01569                                                 &new_ip, ISC_TRUE, &found);
01570                                 if (result == ISC_R_NOMEMORY)
01571                                         goto unlock_and_detach;
01572                                 INSIST(result == ISC_R_SUCCESS);
01573                         }
01574                         /*
01575                          * Do down and to the left as far as possible.
01576                          */
01577                         next_cnode = cnode->child[0];
01578                         if (next_cnode != NULL)
01579                                 continue;
01580                         /*
01581                          * Go up until we find a branch to the right where
01582                          * we previously took the branch to the left.
01583                          */
01584                         for (;;) {
01585                                 parent_cnode = cnode->parent;
01586                                 if (parent_cnode == NULL)
01587                                         break;
01588                                 if (parent_cnode->child[0] == cnode) {
01589                                         next_cnode = parent_cnode->child[1];
01590                                         if (next_cnode != NULL)
01591                                             break;
01592                                 }
01593                                 cnode = parent_cnode;
01594                         }
01595                 }
01596 
01597                 /*
01598                  * Copy to the summary RBT.
01599                  */
01600                 dns_fixedname_init(&namef);
01601                 name = dns_fixedname_name(&namef);
01602                 dns_fixedname_init(&labelf);
01603                 label = dns_fixedname_name(&labelf);
01604                 dns_fixedname_init(&originf);
01605                 origin = dns_fixedname_name(&originf);
01606                 dns_rbtnodechain_init(&chain, NULL);
01607                 result = dns_rbtnodechain_first(&chain, rpzs->rbt, NULL, NULL);
01608                 while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
01609                         result = dns_rbtnodechain_current(&chain, label, origin,
01610                                                         &nmnode);
01611                         INSIST(result == ISC_R_SUCCESS);
01612                         nm_data = nmnode->data;
01613                         if (nm_data != NULL) {
01614                                 new_data.set.qname = (nm_data->set.qname &
01615                                                       new_bit);
01616                                 new_data.set.ns = nm_data->set.ns & new_bit;
01617                                 new_data.wild.qname = (nm_data->wild.qname &
01618                                                        new_bit);
01619                                 new_data.wild.ns = nm_data->wild.ns & new_bit;
01620                                 if (new_data.set.qname != 0 ||
01621                                     new_data.set.ns != 0 ||
01622                                     new_data.wild.qname != 0 ||
01623                                     new_data.wild.ns != 0) {
01624                                         result = dns_name_concatenate(label,
01625                                                         origin, name, NULL);
01626                                         INSIST(result == ISC_R_SUCCESS);
01627                                         result = add_nm(load_rpzs, name,
01628                                                         &new_data);
01629                                         if (result != ISC_R_SUCCESS)
01630                                                 goto unlock_and_detach;
01631                                 }
01632                         }
01633                         result = dns_rbtnodechain_next(&chain, NULL, NULL);
01634                 }
01635                 if (result != ISC_R_NOMORE && result != ISC_R_NOTFOUND) {
01636                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
01637                                       DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
01638                                       "dns_rpz_ready(): unexpected %s",
01639                                       isc_result_totext(result));
01640                         goto unlock_and_detach;
01641                 }
01642         }
01643 
01644         fix_triggers(load_rpzs, rpz_num);
01645 
01646         /*
01647          * Exchange the summary databases.
01648          */
01649         LOCK(&rpzs->search_lock);
01650 
01651         found = rpzs->cidr;
01652         rpzs->cidr = load_rpzs->cidr;
01653         load_rpzs->cidr = found;
01654 
01655         rbt = rpzs->rbt;
01656         rpzs->rbt = load_rpzs->rbt;
01657         load_rpzs->rbt = rbt;
01658 
01659         rpzs->total_triggers = load_rpzs->total_triggers;
01660         rpzs->have = load_rpzs->have;
01661 
01662         UNLOCK(&rpzs->search_lock);
01663 
01664         result = ISC_R_SUCCESS;
01665 
01666  unlock_and_detach:
01667         UNLOCK(&rpzs->maint_lock);
01668         UNLOCK(&load_rpzs->search_lock);
01669         UNLOCK(&load_rpzs->maint_lock);
01670         dns_rpz_detach_rpzs(load_rpzsp);
01671         return (result);
01672 }
01673 
01674 /*
01675  * Add an IP address to the radix tree or a name to the summary database.
01676  */
01677 isc_result_t
01678 dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *src_name)
01679 {
01680         dns_rpz_zone_t *rpz;
01681         dns_rpz_type_t rpz_type;
01682         isc_result_t result = ISC_R_FAILURE;
01683 
01684         REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
01685         rpz = rpzs->zones[rpz_num];
01686         REQUIRE(rpz != NULL);
01687 
01688         rpz_type = type_from_name(rpz, src_name);
01689 
01690         LOCK(&rpzs->maint_lock);
01691         LOCK(&rpzs->search_lock);
01692 
01693         switch (rpz_type) {
01694         case DNS_RPZ_TYPE_QNAME:
01695         case DNS_RPZ_TYPE_NSDNAME:
01696                 result = add_name(rpzs, rpz_num, rpz_type, src_name);
01697                 break;
01698         case DNS_RPZ_TYPE_CLIENT_IP:
01699         case DNS_RPZ_TYPE_IP:
01700         case DNS_RPZ_TYPE_NSIP:
01701                 result = add_cidr(rpzs, rpz_num, rpz_type, src_name);
01702                 break;
01703         case DNS_RPZ_TYPE_BAD:
01704                 break;
01705         }
01706 
01707         UNLOCK(&rpzs->search_lock);
01708         UNLOCK(&rpzs->maint_lock);
01709         return (result);
01710 }
01711 
01712 /*
01713  * Remove an IP address from the radix tree.
01714  */
01715 static void
01716 del_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
01717          dns_rpz_type_t rpz_type, dns_name_t *src_name)
01718 {
01719         isc_result_t result;
01720         dns_rpz_cidr_key_t tgt_ip;
01721         dns_rpz_prefix_t tgt_prefix;
01722         dns_rpz_addr_zbits_t tgt_set;
01723         dns_rpz_cidr_node_t *tgt, *parent, *child;
01724 
01725         /*
01726          * Do not worry about invalid rpz IP address names.  If we
01727          * are here, then something relevant was added and so was
01728          * valid.  Invalid names here are usually internal RBTDB nodes.
01729          */
01730         result = name2ipkey(DNS_RPZ_DEBUG_QUIET, rpzs, rpz_num, rpz_type,
01731                             src_name, &tgt_ip, &tgt_prefix, &tgt_set);
01732         if (result != ISC_R_SUCCESS)
01733                 return;
01734 
01735         result = search(rpzs, &tgt_ip, tgt_prefix, &tgt_set, ISC_FALSE, &tgt);
01736         if (result != ISC_R_SUCCESS) {
01737                 INSIST(result == ISC_R_NOTFOUND ||
01738                        result == DNS_R_PARTIALMATCH);
01739                 /*
01740                  * Do not worry about missing summary RBT nodes that probably
01741                  * correspond to RBTDB nodes that were implicit RBT nodes
01742                  * that were later added for (often empty) wildcards
01743                  * and then to the RBTDB deferred cleanup list.
01744                  */
01745                 return;
01746         }
01747 
01748         /*
01749          * Mark the node and its parents to reflect the deleted IP address.
01750          * Do not count bits that are already clear for internal RBTDB nodes.
01751          */
01752         tgt_set.client_ip &= tgt->set.client_ip;
01753         tgt_set.ip &= tgt->set.ip;
01754         tgt_set.nsip &= tgt->set.nsip;
01755         tgt->set.client_ip &= ~tgt_set.client_ip;
01756         tgt->set.ip &= ~tgt_set.ip;
01757         tgt->set.nsip &= ~tgt_set.nsip;
01758         set_sum_pair(tgt);
01759 
01760         adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, ISC_FALSE);
01761 
01762         /*
01763          * We might need to delete 2 nodes.
01764          */
01765         do {
01766                 /*
01767                  * The node is now useless if it has no data of its own
01768                  * and 0 or 1 children.  We are finished if it is not useless.
01769                  */
01770                 if ((child = tgt->child[0]) != NULL) {
01771                         if (tgt->child[1] != NULL)
01772                                 break;
01773                 } else {
01774                         child = tgt->child[1];
01775                 }
01776                 if (tgt->set.client_ip != 0 ||
01777                     tgt->set.ip != 0 ||
01778                     tgt->set.nsip != 0)
01779                         break;
01780 
01781                 /*
01782                  * Replace the pointer to this node in the parent with
01783                  * the remaining child or NULL.
01784                  */
01785                 parent = tgt->parent;
01786                 if (parent == NULL) {
01787                         rpzs->cidr = child;
01788                 } else {
01789                         parent->child[parent->child[1] == tgt] = child;
01790                 }
01791                 /*
01792                  * If the child exists fix up its parent pointer.
01793                  */
01794                 if (child != NULL)
01795                         child->parent = parent;
01796                 isc_mem_put(rpzs->mctx, tgt, sizeof(*tgt));
01797 
01798                 tgt = parent;
01799         } while (tgt != NULL);
01800 }
01801 
01802 static void
01803 del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
01804          dns_rpz_type_t rpz_type, dns_name_t *src_name)
01805 {
01806         char namebuf[DNS_NAME_FORMATSIZE];
01807         dns_fixedname_t trig_namef;
01808         dns_name_t *trig_name;
01809         dns_rbtnode_t *nmnode;
01810         dns_rpz_nm_data_t *nm_data, del_data;
01811         isc_result_t result;
01812 
01813         /*
01814          * No need for a summary database of names with only 1 policy zone.
01815          */
01816         if (rpzs->p.num_zones <= 1) {
01817                 adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_FALSE);
01818                 return;
01819         }
01820 
01821         dns_fixedname_init(&trig_namef);
01822         trig_name = dns_fixedname_name(&trig_namef);
01823         name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &del_data);
01824 
01825         nmnode = NULL;
01826         result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL, 0,
01827                                   NULL, NULL);
01828         if (result != ISC_R_SUCCESS) {
01829                 /*
01830                  * Do not worry about missing summary RBT nodes that probably
01831                  * correspond to RBTDB nodes that were implicit RBT nodes
01832                  * that were later added for (often empty) wildcards
01833                  * and then to the RBTDB deferred cleanup list.
01834                  */
01835                 if (result == ISC_R_NOTFOUND ||
01836                     result == DNS_R_PARTIALMATCH)
01837                         return;
01838                 dns_name_format(src_name, namebuf, sizeof(namebuf));
01839                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
01840                               DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
01841                               "rpz del_name(%s) node search failed: %s",
01842                               namebuf, isc_result_totext(result));
01843                 return;
01844         }
01845 
01846         nm_data = nmnode->data;
01847         INSIST(nm_data != NULL);
01848 
01849         /*
01850          * Do not count bits that next existed for RBT nodes that would we
01851          * would not have found in a summary for a single RBTDB tree.
01852          */
01853         del_data.set.qname &= nm_data->set.qname;
01854         del_data.set.ns &= nm_data->set.ns;
01855         del_data.wild.qname &= nm_data->wild.qname;
01856         del_data.wild.ns &= nm_data->wild.ns;
01857 
01858         nm_data->set.qname &= ~del_data.set.qname;
01859         nm_data->set.ns &= ~del_data.set.ns;
01860         nm_data->wild.qname &= ~del_data.wild.qname;
01861         nm_data->wild.ns &= ~del_data.wild.ns;
01862 
01863         if (nm_data->set.qname == 0 && nm_data->set.ns == 0 &&
01864             nm_data->wild.qname == 0 && nm_data->wild.ns == 0) {
01865                 result = dns_rbt_deletenode(rpzs->rbt, nmnode, ISC_FALSE);
01866                 if (result != ISC_R_SUCCESS) {
01867                         /*
01868                          * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
01869                          */
01870                         dns_name_format(src_name, namebuf, sizeof(namebuf));
01871                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
01872                                       DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
01873                                       "rpz del_name(%s) node delete failed: %s",
01874                                       namebuf, isc_result_totext(result));
01875                 }
01876         }
01877 
01878         adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_FALSE);
01879 }
01880 
01881 /*
01882  * Remove an IP address from the radix tree or a name from the summary database.
01883  */
01884 void
01885 dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
01886                dns_name_t *src_name) {
01887         dns_rpz_zone_t *rpz;
01888         dns_rpz_type_t rpz_type;
01889 
01890         REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
01891         rpz = rpzs->zones[rpz_num];
01892         REQUIRE(rpz != NULL);
01893 
01894         rpz_type = type_from_name(rpz, src_name);
01895 
01896         LOCK(&rpzs->maint_lock);
01897         LOCK(&rpzs->search_lock);
01898 
01899         switch (rpz_type) {
01900         case DNS_RPZ_TYPE_QNAME:
01901         case DNS_RPZ_TYPE_NSDNAME:
01902                 del_name(rpzs, rpz_num, rpz_type, src_name);
01903                 break;
01904         case DNS_RPZ_TYPE_CLIENT_IP:
01905         case DNS_RPZ_TYPE_IP:
01906         case DNS_RPZ_TYPE_NSIP:
01907                 del_cidr(rpzs, rpz_num, rpz_type, src_name);
01908                 break;
01909         case DNS_RPZ_TYPE_BAD:
01910                 break;
01911         }
01912 
01913         UNLOCK(&rpzs->search_lock);
01914         UNLOCK(&rpzs->maint_lock);
01915 }
01916 
01917 /*
01918  * Search the summary radix tree to get a relative owner name in a
01919  * policy zone relevant to a triggering IP address.
01920  *      rpz_type and zbits limit the search for IP address netaddr
01921  *      return the policy zone's number or DNS_RPZ_INVALID_NUM
01922  *      ip_name is the relative owner name found and
01923  *      *prefixp is its prefix length.
01924  */
01925 dns_rpz_num_t
01926 dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
01927                 dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr,
01928                 dns_name_t *ip_name, dns_rpz_prefix_t *prefixp)
01929 {
01930         dns_rpz_cidr_key_t tgt_ip;
01931         dns_rpz_addr_zbits_t tgt_set;
01932         dns_rpz_cidr_node_t *found;
01933         isc_result_t result;
01934         dns_rpz_num_t rpz_num;
01935         int i;
01936 
01937         /*
01938          * Convert IP address to CIDR tree key.
01939          */
01940         if (netaddr->family == AF_INET) {
01941                 tgt_ip.w[0] = 0;
01942                 tgt_ip.w[1] = 0;
01943                 tgt_ip.w[2] = ADDR_V4MAPPED;
01944                 tgt_ip.w[3] = ntohl(netaddr->type.in.s_addr);
01945                 switch (rpz_type) {
01946                 case DNS_RPZ_TYPE_CLIENT_IP:
01947                         zbits &= rpzs->have.client_ipv4;
01948                         break;
01949                 case DNS_RPZ_TYPE_IP:
01950                         zbits &= rpzs->have.ipv4;
01951                         break;
01952                 case DNS_RPZ_TYPE_NSIP:
01953                         zbits &= rpzs->have.nsipv4;
01954                         break;
01955                 default:
01956                         INSIST(0);
01957                         break;
01958                 }
01959         } else if (netaddr->family == AF_INET6) {
01960                 dns_rpz_cidr_key_t src_ip6;
01961 
01962                 /*
01963                  * Given the int aligned struct in_addr member of netaddr->type
01964                  * one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *,
01965                  * but some people object.
01966                  */
01967                 memmove(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w));
01968                 for (i = 0; i < 4; i++) {
01969                         tgt_ip.w[i] = ntohl(src_ip6.w[i]);
01970                 }
01971                 switch (rpz_type) {
01972                 case DNS_RPZ_TYPE_CLIENT_IP:
01973                         zbits &= rpzs->have.client_ipv6;
01974                         break;
01975                 case DNS_RPZ_TYPE_IP:
01976                         zbits &= rpzs->have.ipv6;
01977                         break;
01978                 case DNS_RPZ_TYPE_NSIP:
01979                         zbits &= rpzs->have.nsipv6;
01980                         break;
01981                 default:
01982                         INSIST(0);
01983                         break;
01984                 }
01985         } else {
01986                 return (DNS_RPZ_INVALID_NUM);
01987         }
01988 
01989         if (zbits == 0)
01990                 return (DNS_RPZ_INVALID_NUM);
01991         make_addr_set(&tgt_set, zbits, rpz_type);
01992 
01993         LOCK(&rpzs->search_lock);
01994         result = search(rpzs, &tgt_ip, 128, &tgt_set, ISC_FALSE, &found);
01995         if (result == ISC_R_NOTFOUND) {
01996                 /*
01997                  * There are no eligible zones for this IP address.
01998                  */
01999                 UNLOCK(&rpzs->search_lock);
02000                 return (DNS_RPZ_INVALID_NUM);
02001         }
02002 
02003         /*
02004          * Construct the trigger name for the longest matching trigger
02005          * in the first eligible zone with a match.
02006          */
02007         *prefixp = found->prefix;
02008         switch (rpz_type) {
02009         case DNS_RPZ_TYPE_CLIENT_IP:
02010                 rpz_num = zbit_to_num(found->set.client_ip & tgt_set.client_ip);
02011                 break;
02012         case DNS_RPZ_TYPE_IP:
02013                 rpz_num = zbit_to_num(found->set.ip & tgt_set.ip);
02014                 break;
02015         case DNS_RPZ_TYPE_NSIP:
02016                 rpz_num = zbit_to_num(found->set.nsip & tgt_set.nsip);
02017                 break;
02018         default:
02019                 INSIST(0);
02020                 break;
02021         }
02022         result = ip2name(&found->ip, found->prefix, dns_rootname, ip_name);
02023         UNLOCK(&rpzs->search_lock);
02024         if (result != ISC_R_SUCCESS) {
02025                 /*
02026                  * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
02027                  */
02028                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
02029                               DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
02030                               "rpz ip2name() failed: %s",
02031                               isc_result_totext(result));
02032                 return (DNS_RPZ_INVALID_NUM);
02033         }
02034         return (rpz_num);
02035 }
02036 
02037 /*
02038  * Search the summary radix tree for policy zones with triggers matching
02039  * a name.
02040  */
02041 dns_rpz_zbits_t
02042 dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
02043                   dns_rpz_zbits_t zbits, dns_name_t *trig_name)
02044 {
02045         char namebuf[DNS_NAME_FORMATSIZE];
02046         dns_rbtnode_t *nmnode;
02047         const dns_rpz_nm_data_t *nm_data;
02048         dns_rpz_zbits_t found_zbits;
02049         isc_result_t result;
02050 
02051         if (zbits == 0)
02052                 return (0);
02053 
02054         found_zbits = 0;
02055 
02056         LOCK(&rpzs->search_lock);
02057 
02058         nmnode = NULL;
02059         result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL,
02060                                   DNS_RBTFIND_EMPTYDATA, NULL, NULL);
02061         switch (result) {
02062         case ISC_R_SUCCESS:
02063                 nm_data = nmnode->data;
02064                 if (nm_data != NULL) {
02065                         if (rpz_type == DNS_RPZ_TYPE_QNAME)
02066                                 found_zbits = nm_data->set.qname;
02067                         else
02068                                 found_zbits = nm_data->set.ns;
02069                 }
02070                 nmnode = nmnode->parent;
02071                 /* fall thru */
02072         case DNS_R_PARTIALMATCH:
02073                 while (nmnode != NULL) {
02074                         nm_data = nmnode->data;
02075                         if (nm_data != NULL) {
02076                                 if (rpz_type == DNS_RPZ_TYPE_QNAME)
02077                                         found_zbits |= nm_data->wild.qname;
02078                                 else
02079                                         found_zbits |= nm_data->wild.ns;
02080                         }
02081                         nmnode = nmnode->parent;
02082                 }
02083                 break;
02084 
02085         case ISC_R_NOTFOUND:
02086                 break;
02087 
02088         default:
02089                 /*
02090                  * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
02091                  */
02092                 dns_name_format(trig_name, namebuf, sizeof(namebuf));
02093                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
02094                               DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
02095                               "dns_rpz_find_name(%s) failed: %s",
02096                               namebuf, isc_result_totext(result));
02097                 break;
02098         }
02099 
02100         UNLOCK(&rpzs->search_lock);
02101         return (zbits & found_zbits);
02102 }
02103 
02104 /*
02105  * Translate CNAME rdata to a QNAME response policy action.
02106  */
02107 dns_rpz_policy_t
02108 dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
02109                      dns_name_t *selfname)
02110 {
02111         dns_rdata_t rdata = DNS_RDATA_INIT;
02112         dns_rdata_cname_t cname;
02113         isc_result_t result;
02114 
02115         result = dns_rdataset_first(rdataset);
02116         INSIST(result == ISC_R_SUCCESS);
02117         dns_rdataset_current(rdataset, &rdata);
02118         result = dns_rdata_tostruct(&rdata, &cname, NULL);
02119         INSIST(result == ISC_R_SUCCESS);
02120         dns_rdata_reset(&rdata);
02121 
02122         /*
02123          * CNAME . means NXDOMAIN
02124          */
02125         if (dns_name_equal(&cname.cname, dns_rootname))
02126                 return (DNS_RPZ_POLICY_NXDOMAIN);
02127 
02128         if (dns_name_iswildcard(&cname.cname)) {
02129                 /*
02130                  * CNAME *. means NODATA
02131                  */
02132                 if (dns_name_countlabels(&cname.cname) == 2)
02133                         return (DNS_RPZ_POLICY_NODATA);
02134 
02135                 /*
02136                  * A qname of www.evil.com and a policy of
02137                  *      *.evil.com    CNAME   *.garden.net
02138                  * gives a result of
02139                  *      evil.com    CNAME   evil.com.garden.net
02140                  */
02141                 if (dns_name_countlabels(&cname.cname) > 2)
02142                         return (DNS_RPZ_POLICY_WILDCNAME);
02143         }
02144 
02145         /*
02146          * CNAME rpz-tcp-only. means "send truncated UDP responses."
02147          */
02148         if (dns_name_equal(&cname.cname, &rpz->tcp_only))
02149                 return (DNS_RPZ_POLICY_TCP_ONLY);
02150 
02151         /*
02152          * CNAME rpz-drop. means "do not respond."
02153          */
02154         if (dns_name_equal(&cname.cname, &rpz->drop))
02155                 return (DNS_RPZ_POLICY_DROP);
02156 
02157         /*
02158          * CNAME rpz-passthru. means "do not rewrite."
02159          */
02160         if (dns_name_equal(&cname.cname, &rpz->passthru))
02161                 return (DNS_RPZ_POLICY_PASSTHRU);
02162 
02163         /*
02164          * 128.1.0.127.rpz-ip CNAME  128.1.0.0.127. is obsolete PASSTHRU
02165          */
02166         if (selfname != NULL && dns_name_equal(&cname.cname, selfname))
02167                 return (DNS_RPZ_POLICY_PASSTHRU);
02168 
02169         /*
02170          * Any other rdata gives a response consisting of the rdata.
02171          */
02172         return (DNS_RPZ_POLICY_RECORD);
02173 }

Generated on Tue Apr 28 17:41:01 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha