auto
  *   ˆl–Ãa¾”ji?u@?pÜŠbÑ¿Ãƒq§]_†I|¥�+ÁÆ M    /*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_ACL_H
#define DNS_ACL_H 1

/*****
***** Module Info
*****/

/*! \file dns/acl.h
 * \brief
 * Address match list handling.
 */

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/netaddr.h>
#include <isc/refcount.h>

#include <dns/geoip.h>
#include <dns/iptable.h>
#include <dns/name.h>
#include <dns/types.h>

/***
 *** Types
 ***/

typedef enum {
	dns_aclelementtype_ipprefix,
	dns_aclelementtype_keyname,
	dns_aclelementtype_nestedacl,
	dns_aclelementtype_localhost,
	dns_aclelementtype_localnets,
#if defined(HAVE_GEOIP2)
	dns_aclelementtype_geoip,
#endif /* HAVE_GEOIP2 */
	dns_aclelementtype_any
} dns_aclelementtype_t;

typedef struct dns_aclipprefix dns_aclipprefix_t;

struct dns_aclipprefix {
	isc_netaddr_t address; /* IP4/IP6 */
	unsigned int  prefixlen;
};

struct dns_aclelement {
	dns_aclelementtype_t type;
	bool		     negative;
	dns_name_t	     keyname;
#if defined(HAVE_GEOIP2)
	dns_geoip_elem_t geoip_elem;
#endif /* HAVE_GEOIP2 */
	dns_acl_t *nestedacl;
	int	   node_num;
};

#define dns_acl_node_count(acl) acl->iptable->radix->num_added_node

struct dns_acl {
	unsigned int	  magic;
	isc_mem_t	  *mctx;
	isc_refcount_t	  refcount;
	dns_iptable_t    *iptable;
	dns_aclelement_t *elements;
	bool		  has_negatives;
	unsigned int	  alloc;	 /*%< Elements allocated */
	unsigned int	  length;	 /*%< Elements initialized */
	char	     *name;		 /*%< Temporary use only */
	ISC_LINK(dns_acl_t) nextincache; /*%< Ditto */
};

struct dns_aclenv {
	dns_acl_t *localhost;
	dns_acl_t *localnets;
	bool	   match_mapped;
#if defined(HAVE_GEOIP2)
	dns_geoip_databases_t *geoip;
#endif /* HAVE_GEOIP2 */
};

#define DNS_ACL_MAGIC	 ISC_MAGIC('D', 'a', 'c', 'l')
#define DNS_ACL_VALID(a) ISC_MAGIC_VALID(a, DNS_ACL_MAGIC)

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

isc_result_t
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
/*%<
 * Create a new ACL, including an IP table and an array with room
 * for 'n' ACL elements.  The elements are uninitialized and the
 * length is 0.
 */

isc_result_t
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target);
/*%<
 * Create a new ACL that matches everything.
 */

isc_result_t
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target);
/*%<
 * Create a new ACL that matches nothing.
 */

bool
dns_acl_isany(dns_acl_t *acl);
/*%<
 * Test whether ACL is set to "{ any; }"
 */

bool
dns_acl_isnone(dns_acl_t *acl);
/*%<
 * Test whether ACL is set to "{ none; }"
 */

isc_result_t
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, bool pos);
/*%<
 * Merge the contents of one ACL into another.  Call dns_iptable_merge()
 * for the IP tables, then concatenate the element arrays.
 *
 * If pos is set to false, then the nested ACL is to be negated.  This
 * means reverse the sense of each *positive* element or IP table node,
 * but leave negatives alone, so as to prevent a double-negative causing
 * an unexpected positive match in the parent ACL.
 */

void
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
/*%<
 * Attach to acl 'source'.
 *
 * Requires:
 *\li	'source' to be a valid acl.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_acl_detach(dns_acl_t **aclp);
/*%<
 * Detach the acl. On final detach the acl must not be linked on any
 * list.
 *
 * Requires:
 *\li	'*aclp' to be a valid acl.
 *
 * Insists:
 *\li	'*aclp' is not linked on final detach.
 */

bool
dns_acl_isinsecure(const dns_acl_t *a);
/*%<
 * Return #true iff the acl 'a' is considered insecure, that is,
 * if it contains IP addresses other than those of the local host.
 * This is intended for applications such as printing w