Home | History | Annotate | Line # | Download | only in dns
      1  1.1  christos /*	$NetBSD: order.c,v 1.1 2024/02/18 20:57:33 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  1.1  christos  *
      6  1.1  christos  * SPDX-License-Identifier: MPL-2.0
      7  1.1  christos  *
      8  1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      9  1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  1.1  christos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  1.1  christos  *
     12  1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     13  1.1  christos  * information regarding copyright ownership.
     14  1.1  christos  */
     15  1.1  christos 
     16  1.1  christos /*! \file */
     17  1.1  christos 
     18  1.1  christos #include <stdbool.h>
     19  1.1  christos 
     20  1.1  christos #include <isc/magic.h>
     21  1.1  christos #include <isc/mem.h>
     22  1.1  christos #include <isc/refcount.h>
     23  1.1  christos #include <isc/types.h>
     24  1.1  christos #include <isc/util.h>
     25  1.1  christos 
     26  1.1  christos #include <dns/fixedname.h>
     27  1.1  christos #include <dns/name.h>
     28  1.1  christos #include <dns/order.h>
     29  1.1  christos #include <dns/rdataset.h>
     30  1.1  christos #include <dns/types.h>
     31  1.1  christos 
     32  1.1  christos typedef struct dns_order_ent dns_order_ent_t;
     33  1.1  christos struct dns_order_ent {
     34  1.1  christos 	dns_fixedname_t name;
     35  1.1  christos 	dns_rdataclass_t rdclass;
     36  1.1  christos 	dns_rdatatype_t rdtype;
     37  1.1  christos 	unsigned int mode;
     38  1.1  christos 	ISC_LINK(dns_order_ent_t) link;
     39  1.1  christos };
     40  1.1  christos 
     41  1.1  christos struct dns_order {
     42  1.1  christos 	unsigned int magic;
     43  1.1  christos 	isc_refcount_t references;
     44  1.1  christos 	ISC_LIST(dns_order_ent_t) ents;
     45  1.1  christos 	isc_mem_t *mctx;
     46  1.1  christos };
     47  1.1  christos 
     48  1.1  christos #define DNS_ORDER_MAGIC	       ISC_MAGIC('O', 'r', 'd', 'r')
     49  1.1  christos #define DNS_ORDER_VALID(order) ISC_MAGIC_VALID(order, DNS_ORDER_MAGIC)
     50  1.1  christos 
     51  1.1  christos isc_result_t
     52  1.1  christos dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) {
     53  1.1  christos 	dns_order_t *order;
     54  1.1  christos 
     55  1.1  christos 	REQUIRE(orderp != NULL && *orderp == NULL);
     56  1.1  christos 
     57  1.1  christos 	order = isc_mem_get(mctx, sizeof(*order));
     58  1.1  christos 
     59  1.1  christos 	ISC_LIST_INIT(order->ents);
     60  1.1  christos 
     61  1.1  christos 	/* Implicit attach. */
     62  1.1  christos 	isc_refcount_init(&order->references, 1);
     63  1.1  christos 
     64  1.1  christos 	order->mctx = NULL;
     65  1.1  christos 	isc_mem_attach(mctx, &order->mctx);
     66  1.1  christos 	order->magic = DNS_ORDER_MAGIC;
     67  1.1  christos 	*orderp = order;
     68  1.1  christos 	return (ISC_R_SUCCESS);
     69  1.1  christos }
     70  1.1  christos 
     71  1.1  christos isc_result_t
     72  1.1  christos dns_order_add(dns_order_t *order, const dns_name_t *name,
     73  1.1  christos 	      dns_rdatatype_t rdtype, dns_rdataclass_t rdclass,
     74  1.1  christos 	      unsigned int mode) {
     75  1.1  christos 	dns_order_ent_t *ent;
     76  1.1  christos 
     77  1.1  christos 	REQUIRE(DNS_ORDER_VALID(order));
     78  1.1  christos 	REQUIRE(mode == DNS_RDATASETATTR_RANDOMIZE ||
     79  1.1  christos 		mode == DNS_RDATASETATTR_FIXEDORDER ||
     80  1.1  christos 		mode == DNS_RDATASETATTR_CYCLIC ||
     81  1.1  christos 		mode == DNS_RDATASETATTR_NONE);
     82  1.1  christos 
     83  1.1  christos 	ent = isc_mem_get(order->mctx, sizeof(*ent));
     84  1.1  christos 
     85  1.1  christos 	dns_fixedname_init(&ent->name);
     86  1.1  christos 	dns_name_copynf(name, dns_fixedname_name(&ent->name));
     87  1.1  christos 	ent->rdtype = rdtype;
     88  1.1  christos 	ent->rdclass = rdclass;
     89  1.1  christos 	ent->mode = mode;
     90  1.1  christos 	ISC_LINK_INIT(ent, link);
     91  1.1  christos 	ISC_LIST_INITANDAPPEND(order->ents, ent, link);
     92  1.1  christos 	return (ISC_R_SUCCESS);
     93  1.1  christos }
     94  1.1  christos 
     95  1.1  christos static bool
     96  1.1  christos match(const dns_name_t *name1, const dns_name_t *name2) {
     97  1.1  christos 	if (dns_name_iswildcard(name2)) {
     98  1.1  christos 		return (dns_name_matcheswildcard(name1, name2));
     99  1.1  christos 	}
    100  1.1  christos 	return (dns_name_equal(name1, name2));
    101  1.1  christos }
    102  1.1  christos 
    103  1.1  christos unsigned int
    104  1.1  christos dns_order_find(dns_order_t *order, const dns_name_t *name,
    105  1.1  christos 	       dns_rdatatype_t rdtype, dns_rdataclass_t rdclass) {
    106  1.1  christos 	dns_order_ent_t *ent;
    107  1.1  christos 	REQUIRE(DNS_ORDER_VALID(order));
    108  1.1  christos 
    109  1.1  christos 	for (ent = ISC_LIST_HEAD(order->ents); ent != NULL;
    110  1.1  christos 	     ent = ISC_LIST_NEXT(ent, link))
    111  1.1  christos 	{
    112  1.1  christos 		if (ent->rdtype != rdtype && ent->rdtype != dns_rdatatype_any) {
    113  1.1  christos 			continue;
    114  1.1  christos 		}
    115  1.1  christos 		if (ent->rdclass != rdclass &&
    116  1.1  christos 		    ent->rdclass != dns_rdataclass_any)
    117  1.1  christos 		{
    118  1.1  christos 			continue;
    119  1.1  christos 		}
    120  1.1  christos 		if (match(name, dns_fixedname_name(&ent->name))) {
    121  1.1  christos 			return (ent->mode);
    122  1.1  christos 		}
    123  1.1  christos 	}
    124  1.1  christos 	return (DNS_RDATASETATTR_NONE);
    125  1.1  christos }
    126  1.1  christos 
    127  1.1  christos void
    128  1.1  christos dns_order_attach(dns_order_t *source, dns_order_t **target) {
    129  1.1  christos 	REQUIRE(DNS_ORDER_VALID(source));
    130  1.1  christos 	REQUIRE(target != NULL && *target == NULL);
    131  1.1  christos 	isc_refcount_increment(&source->references);
    132  1.1  christos 	*target = source;
    133  1.1  christos }
    134  1.1  christos 
    135  1.1  christos void
    136  1.1  christos dns_order_detach(dns_order_t **orderp) {
    137  1.1  christos 	REQUIRE(orderp != NULL && DNS_ORDER_VALID(*orderp));
    138  1.1  christos 	dns_order_t *order;
    139  1.1  christos 	order = *orderp;
    140  1.1  christos 	*orderp = NULL;
    141  1.1  christos 
    142  1.1  christos 	if (isc_refcount_decrement(&order->references) == 1) {
    143  1.1  christos 		isc_refcount_destroy(&order->references);
    144  1.1  christos 		order->magic = 0;
    145  1.1  christos 		dns_order_ent_t *ent;
    146  1.1  christos 		while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) {
    147  1.1  christos 			ISC_LIST_UNLINK(order->ents, ent, link);
    148  1.1  christos 			isc_mem_put(order->mctx, ent, sizeof(*ent));
    149  1.1  christos 		}
    150  1.1  christos 		isc_mem_putanddetach(&order->mctx, order, sizeof(*order));
    151  1.1  christos 	}
    152  1.1  christos }
    153