/*
* 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.
*/
/*
* Define the interface from a DNS resolver to the Response Policy Zone
* library, librpz.
*
* This file should be included only the interface functions between the
* resolver and librpz to avoid name space pollution.
*
* Copyright (c) 2016-2017 Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* version 1.2.12
*/
#ifndef LIBRPZ_H
#define LIBRPZ_H
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <sys/types.h>
/*
* Allow either ordinary or dlopen() linking.
*/
#ifdef LIBRPZ_INTERNAL
#define LIBDEF(t, s) extern t s;
#define LIBDEF_F(f) LIBDEF(librpz_##f##_t, librpz_##f)
#else /* ifdef LIBRPZ_INTERNAL */
#define LIBDEF(t, s)
#define LIBDEF_F(f)
#endif /* ifdef LIBRPZ_INTERNAL */
/*
* Response Policy Zone triggers.
* Comparisons of trigger precedences require
* LIBRPZ_TRIG_CLIENT_IP < LIBRPZ_TRIG_QNAME < LIBRPZ_TRIG_IP
* < LIBRPZ_TRIG_NSDNAME < LIBRPZ_TRIG_NSIP}
*/
typedef enum {
LIBRPZ_TRIG_BAD = 0,
LIBRPZ_TRIG_CLIENT_IP = 1,
LIBRPZ_TRIG_QNAME = 2,
LIBRPZ_TRIG_IP = 3,
LIBRPZ_TRIG_NSDNAME = 4,
LIBRPZ_TRIG_NSIP = 5
} librpz_trig_t;
#define LIBRPZ_TRIG_SIZE 3 /* sizeof librpz_trig_t in bits */
typedef uint8_t librpz_tbit_t; /* one bit for each of the TRIGS_NUM
* trigger types */
/*
* Response Policy Zone Actions or policies
*/
typedef enum {
LIBRPZ_POLICY_UNDEFINED = 0, /* an empty entry or no decision yet */
LIBRPZ_POLICY_DELETED = 1, /* placeholder for a deleted policy */
LIBRPZ_POLICY_PASSTHRU = 2, /* 'passthru': do not rewrite */
LIBRPZ_POLICY_DROP = 3, /* 'drop': do not respond */
LIBRPZ_POLICY_TCP_ONLY = 4, /* 'tcp-only': answer UDP with TC=1 */
LIBRPZ_POLICY_NXDOMAIN = 5, /* 'nxdomain': answer with NXDOMAIN */
LIBRPZ_POLICY_NODATA = 6, /* 'nodata': answer with ANCOUNT=0 */
LIBRPZ_POLICY_RECORD = 7, /* rewrite with the policy's RR */
/* only in client configurations to override the zone */
LIBRPZ_POLICY_GIVEN, /* 'given': what policy record says */
LIBRPZ_POLICY_DISABLED, /* at most log */
LIBRPZ_POLICY_CNAME, /* answer with 'cname x' */
} librpz_policy_t;
#define LIBRPZ_POLICY_BITS 4
/*
* Special policies that appear as targets of CNAMEs
* NXDOMAIN is signaled by a CNAME with a "." target.
* NODATA is signaled by a CNAME with a "*." target.
*/
#define LIBRPZ_RPZ_PREFIX "rpz-"
#define LIBRPZ_RPZ_PASSTHRU LIBRPZ_RPZ_PREFIX "passthru"
#define LIBRPZ_RPZ_DROP LIBRPZ_RPZ_PREFIX "drop"
#define LIBRPZ_RPZ_TCP_ONLY LIBRPZ_RPZ_PREFIX "tcp-only"
typedef uint16_t librpz_dznum_t; /* dnsrpzd zone # in [0,DZNUM_MAX] */
typedef uint8_t librpz_cznum_t; /* client zone # in [0,CZNUM_MAX] */
/*
* CIDR block
*/
typedef struct librpz_prefix {
union {
struct in_addr in;
struct in6_addr in6;
} addr;
uint8_t family;
uint8_t len;
} librpz_prefix_t;
/*
* A domain
*/
typedef uint8_t librpz_dsize_t;
typedef struct librpz_domain {
librpz_dsize_t size; /* of only .d */
uint8_t d[0]; /* variable length wire format */
} librpz_domain_t;
/*
* A maximal domain buffer
*/
typedef struct librpz_domain_buf {
librpz_dsize_t size;
uint8_t d[NS_MAXCDNAME];
} librpz_domain_buf_t;
/*
* A resource record without the owner name.
* C compilers say that sizeof(librpz_rr_t)=12 instead of 10.
*/
typedef struct {
uint16_t type; /* network byte order */
uint16_t class; /* network byte order */
uint32_t ttl; /* network byte order */
uint16_t rdlength; /* network byte order */
uint8_t rdata[0]; /* variable length */
} librpz_rr_t;
/*
* The database file might be mapped with different starting addresses
* by concurrent clients (resolvers), and so all pointers are offsets.
*/
typedef uint32_t librpz_idx_t;
#define LIBRPZ_IDX_NULL 0
#define LIBRPZ_IDX_MIN 1
#define LIBRPZ_IDX_BAD ((librpz_idx_t)-1)
/**
* Partial decoded results of a set of RPZ queries for a single DNS response
* or iteration through the mapped file.
*/
typedef int16_t librpz_result_id_t;
typedef struct librpz_result {
librpz_idx_t next_rr;
librpz_result_id_t hit_id; /* trigger ID from resolver */
librpz_policy_t zpolicy; /* policy from zone */
librpz_policy_t policy; /* adjusted by client configuration */
librpz_dznum_t dznum; /* dnsrpzd zone number */
librpz_cznum_t cznum; /* librpz client zone number */
librpz_trig_t trig : LIBRPZ_TRIG_SIZE;
bool log : 1; /* log rewrite given librpz_log_level
* */
} librpz_result_t;
/**
* librpz trace or log levels.
*/
typedef enum {
LIBRPZ_LOG_FATAL = 0, /* always print fatal errors */
LIBRPZ_LOG_ERROR = 1, /* errors have this level */
LIBRPZ_LOG_TRACE1 = 2, /* big events such as dnsrpzd starts */
LIBRPZ_LOG_TRACE2 = 3, /* smaller dnsrpzd zone transfers */
LIBRPZ_LOG_TRACE3 = 4, /* librpz hits */
LIBRPZ_LOG_TRACE4 = 5, /* librpz lookups */
LIBRPZ_LOG_INVALID = 999,
} librpz_log_level_t;
typedef librpz_log_level_t(librpz_log_level_val_t)(librpz_log_level_t level);
LIBDEF_F(log_level_val)
/**
* Logging function that can be supplied by the resolver.
* @param level is one of librpz_log_level_t
* @param ctx is for use by the resolver's logging system.
* NULL mean a context-free message.
*/
typedef void(librpz_log_fnc_t)(librpz_log_level_t level, void *ctx,
const char *buf);
/**
* Point librpz logging functions to the resolver's choice.
*/
typedef void(librpz_set_log_t)(librpz_log_fnc_t *new_log, const char *prog_nm);
LIBDEF_F(set_log)
/**
* librpz error messages are put in these buffers.
* Use a structure instead of naked char* to let the compiler check the length.
* A function defined with "foo(char buf[120])" can be called with
* "char sbuf[2]; foo(sbuf)" and suffer a buffer overrun.
*/
typedef struct {
char c[120];
} librpz_emsg_t;
#ifdef LIBRPZ_HAVE_ATTR
#define LIBRPZ_UNUSED __attribute__((unused))
#define LIBRPZ_PF(f, l) __attribute__((format(printf, f, l)))
#define LIBRPZ_NORET __attribute__((__noreturn__))
#else /* ifdef LIBRPZ_HAVE_ATTR */
#define LIBRPZ_UNUSED
#define LIBRPZ_PF(f, l)
#define LIBRPZ_NORET
#endif /* ifdef LIBRPZ_HAVE_ATTR */
#ifdef HAVE_BUILTIN_EXPECT
#define LIBRPZ_LIKELY(c) __builtin_expect(!!(c), 1)
#define LIBRPZ_UNLIKELY(c) __builtin_expect(!!(c), 0)
#else /* ifdef HAVE_BUILTIN_EXPECT */
#define LIBRPZ_LIKELY(c) (c)
#define LIBRPZ_UNLIKELY(c) (c)
#endif /* ifdef HAVE_BUILTIN_EXPECT */
typedef bool(librpz_parse_log_opt_t)(librpz_emsg_t *emsg, const char *arg);
LIBDEF_F(parse_log_opt)
typedef void(librpz_vpemsg_t)(librpz_emsg_t *emsg, const char *p, va_list args);
LIBDEF_F(vpemsg)
typedef void(librpz_pemsg_t)(librpz_emsg_t *emsg, const char *p, ...)
LIBRPZ_PF(2, 3);
LIBDEF_F(pemsg)
typedef void(librpz_vlog_t)(librpz_log_level_t level, void *ctx, const char *p,
va_list args);
LIBDEF_F(vlog)
typedef void(librpz_log_t)(librpz_log_level_t level, void *ctx, const char *p,
...) LIBRPZ_PF(3, 4);
LIBDEF_F(log)
typedef void(librpz_fatal_t)(int ex_code, const char *p, ...) LIBRPZ_PF(2, 3);
extern void
librpz_fatal(int ex_code, const char *p, ...) LIBRPZ_PF(2, 3) LIBRPZ_NORET;
typedef void(librpz_rpz_assert_t)(const char *file, unsigned line,
const char *p, ...) LIBRPZ_PF(3, 4);
extern void
librpz_rpz_assert(const char *file, unsigned line, const char *p, ...)
LIBRPZ_PF(3, 4) LIBRPZ_NORET;
typedef void(librpz_rpz_vassert_t)(const char *file, uint line, const char *p,
va_list args);
extern void
librpz_rpz_vassert(const char *file, uint line, const char *p,
va_list args) LIBRPZ_NORET;
/*
* As far as clients are concerned, all relative pointers or indexes in a
* version of the mapped file except trie node parent pointers remain valid
* forever. A client must release a version so that it can be garbage
* collected by the file system. When dnsrpzd needs to expand the file,
* it copies the old file to a new, larger file. Clients can continue
* using the old file.
*
* Versions can also appear in a single file. Old nodes and trie values
* within the file are not destroyed until all clients using the version
* that contained the old values release the version.
*
* A client is marked as using version by connecting to the daemon. It is
* marked as using all subsequent versions. A client releases all versions
* by closing the connection or a range of versions by updating is slot
* in the shared memory version table.
*
* As far as clients are concerned, there are the following possible librpz
* failures:
* - malloc() or other fatal internal librpz problems indicated by
* a failing return from a librpz function
* All operations will fail until client handle is destroyed and
* recreated with librpz_client_detach() and librpz_client_create().
* - corrupt database detected by librpz code, corrupt database detected
* by dnsrpzd, or disconnection from the daemon.
* Current operations will fail.
*
* Clients assume that the file has already been unlinked before
* the corrupt flag is set so that they do not race with the server
* over the corruption of a single file. A client that finds the
* corrupt set knows that dnsrpzd has already crashed with
* abort() and is restarting. The client can re-connect to dnsrpzd
* and retransmit its configuration, backing off as usual if anything
* goes wrong.
*
* Searches of the database by a client do not need locks against dnsrpzd or
* other clients, but a lock is used to protect changes to the connection
* by competing threads in the client. The client provides functions
* to serialize the concurrent use of any single client handle.
* Functions that do nothing are appropriate for applications that are
* not "threaded" or that do not share client handles among threads.
* Otherwise, functions must be provided to librpz_clientcreate().
* Something like the following works with pthreads:
*
* static void
* lock(void *mutex) { assert(pthread_mutex_lock(mutex) == 0); }
*
* static void
* unlock(void *mutex) { assert(pthread_mutex_unlock(mutex) == 0); }
*
* static void
* mutex_destroy(void *mutex) { assert(pthread_mutex_destroy(mutex) == 0); }
*
*
*
* At every instant, all of the data and pointers in the mapped file are valid.
* Changes to trie node or other data are always made so that it and
* all pointers in and to it remain valid for a time. Old versions are
* eventually discarded.
*
* Dnsrpzd periodically defines a new version by setting aside all changes
* made since the previous version was defined. Subsequent changes
* made (only!) by dnsrpzd will be part of the next version.
*
* To discard an old version, dnsrpzd must know that all clients have stopped
* using that version. Clients do that by using part of the mapped file
* to tell dnsrpzd the oldest version that each client is using.
* Dnsrpzd assigns each connecting client an entry in the cversions array
* in the mapped file. The client puts version numbers into that entry
* to signal to dnsrpzd which versions that can be discarded.
* Dnsrpzd is free, as far as that client is concerned, to discard all
* numerically smaller versions. A client can disclaim all versions with
* the version number VERSIONS_ALL or 0.
*
* The race between a client changing its entry and dnsrpzd discarding a
* version is resolved by allowing dnsrpzd to discard all versions
* smaller or equal to the client's version number. If dnsrpzd is in
* the midst of discarding or about to discard version N when the
* client asserts N, no harm is done. The client depends only on
* the consistency of version N+1.
*
* This version mechanism depends in part on not being exercised too frequently
* Version numbers are 32 bits long and dnsrpzd creates new versions
* at most once every 30 seconds.
*/
/*
* Lock functions for concurrent use of a single librpz_client_t client handle.
*/
typedef void(librpz_mutex_t)(void *mutex);
/*
* List of connections to dnsrpzd daemons.
*/
typedef struct librpz_clist librpz_clist_t;
/*
* Client's handle on dnsrpzd.
*/
typedef struct librpz_client librpz_client_t;
/**
* Create the list of connections to the dnsrpzd daemon.
* @param[out] emsg: error message
* @param lock: start exclusive access to the client handle
* @param unlock: end exclusive access to the client handle
* @param mutex_destroy: release the lock
* @param mutex: pointer to the lock for the client handle
* @param log_ctx: NULL or resolver's context log messages
*/
typedef librpz_clist_t *(librpz_clist_create_t)(librpz_emsg_t *emsg,
librpz_mutex_t *lock,
librpz_mutex_t *unlock,
librpz_mutex_t *mutex_destroy,
void *mutex, void *log_ctx);
LIBDEF_F(clist_create)
/**
* Release the list of dnsrpzd connections.
*/
typedef void(librpz_clist_detach_t)(librpz_clist_t **clistp);
LIBDEF_F(clist_detach)
/**
* Create a librpz client handle.
* @param[out] emsg: error message
* @param clist: of dnsrpzd connections
* @param cstr: string of configuration settings separated by ';' or '\n'
* @param use_expired: true to not ignore expired zones
* @return client handle or NULL if the handle could not be created
*/
typedef librpz_client_t *(librpz_client_create_t)(librpz_emsg_t *emsg,
librpz_clist_t *clist,
const char *cstr,
bool use_expired);
LIBDEF_F(client_create)
/**
* Start (if necessary) dnsrpzd and connect to it.
* @param[out] emsg: error message
* @param client handle
* @param optional: true if it is ok if starting the daemon is not allowed
*/
typedef bool(librpz_connect_t)(librpz_emsg_t *emsg, librpz_client_t *client,
bool optional);
LIBDEF_F(connect)
/**
* Start to destroy a librpz client handle.
* It will not be destroyed until the last set of RPZ queries represented
* by a librpz_rsp_t ends.
* @param client handle to be released
* @return false on error
*/
typedef void(librpz_client_detach_t)(librpz_client_t **clientp);
LIBDEF_F(client_detach)
/**
* State for a set of RPZ queries for a single DNS response
* or for listing the database.
*/
typedef struct librpz_rsp librpz_rsp_t;
/**
* Start a set of RPZ queries for a single DNS response.
* @param[out] emsg: error message for false return or *rspp=NULL
* @param[out] rspp created context or NULL
* @param[out] min_ns_dotsp: NULL or pointer to configured MIN-NS-DOTS value
* @param client state
* @param have_rd: RD=1 in the DNS request
* @param have_do: DO=1 in the DNS request
* @return false on error
*/
typedef bool(librpz_rsp_create_t)(librpz_emsg_t *emsg, librpz_rsp_t **rspp,
int *min_ns_dotsp, librpz_client_t *client,
bool have_rd, bool have_do);
LIBDEF_F(rsp_create)
/**
* Finish RPZ work for a DNS response.
*/
typedef void(librpz_rsp_detach_t)(librpz_rsp_t **rspp);
LIBDEF_F(rsp_detach)
/**
* Get the final, accumulated result of a set of RPZ queries.
* Yield LIBRPZ_POLICY_UNDEFINED if
* - there were no hits,
* - there was a dispositive hit, be we have not recursed and are required
* to recurse so that evil DNS authorities will not know we are using RPZ
* - we have a hit and have recursed, but later data such as NSIP could
* override
* @param[out] emsg
* @param[out] result describes the hit
* or result->policy=LIBRPZ_POLICY_UNDEFINED without a hit
* @param[out] result: current policy rewrite values
* @param recursed: recursion has now been done even if it was not done
* when the hit was found
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_result_t)(librpz_emsg_t *emsg, librpz_result_t *result,
bool recursed, const librpz_rsp_t *rsp);
LIBDEF_F(rsp_result)
/**
* Might looking for a trigger be worthwhile?
* @param trig: look for this type of trigger
* @param ipv6: true if trig is LIBRPZ_TRIG_CLIENT_IP, LIBRPZ_TRIG_IP,
* or LIBRPZ_TRIG_NSIP and the IP address is IPv6
* @return: true if looking could be worthwhile
*/
typedef bool(librpz_have_trig_t)(librpz_trig_t trig, bool ipv6,
const librpz_rsp_t *rsp);
LIBDEF_F(have_trig)
/**
* Might looking for NSDNAME and NSIP triggers be worthwhile?
* @return: true if looking could be worthwhile
*/
typedef bool(librpz_have_ns_trig_t)(const librpz_rsp_t *rsp);
LIBDEF_F(have_ns_trig)
/**
* Convert the found client IP trie key to a CIDR block
* @param[out] emsg
* @param[out] prefix trigger
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_clientip_prefix_t)(librpz_emsg_t *emsg,
librpz_prefix_t *prefix,
librpz_rsp_t *rsp);
LIBDEF_F(rsp_clientip_prefix)
/**
* Compute the owner name of the found or result trie key, usually to log it.
* An IP address key might be returned as 8.0.0.0.127.rpz-client-ip.
* example.com. might be a qname trigger. example.com.rpz-nsdname. could
* be an NSDNAME trigger.
* @param[out] emsg
* @param[out] owner domain
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_domain_t)(librpz_emsg_t *emsg,
librpz_domain_buf_t *owner,
librpz_rsp_t *rsp);
LIBDEF_F(rsp_domain)
/**
* Get the next RR of the LIBRPZ_POLICY_RECORD result after an initial use of
* librpz_rsp_result() or librpz_itr_node() or after a previous use of
* librpz_rsp_rr(). The RR is in uncompressed wire format including type,
* class, ttl and length in network byte order.
* @param[out] emsg
* @param[out] typep: optional host byte order record type or ns_t_invalid (0)
* @param[out] classp: class such as ns_c_in
* @param[out] ttlp: TTL
* @param[out] rrp: optional malloc() buffer containing the next RR or
* NULL after the last RR
* @param[out] result: current policy rewrite values
* @param qname: used construct a wildcard CNAME
* @param qname_size
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_rr_t)(librpz_emsg_t *emsg, uint16_t *typep,
uint16_t *classp, uint32_t *ttlp,
librpz_rr_t **rrp, librpz_result_t *result,
const uint8_t *qname, size_t qname_size,
librpz_rsp_t *rsp);
LIBDEF_F(rsp_rr)
/**
* Get the next RR of the LIBRPZ_POLICY_RECORD result.
* @param[out] emsg
* @param[out] ttlp: TTL
* @param[out] rrp: malloc() buffer with SOA RR without owner name
* @param[out] result: current policy rewrite values
* @param[out] origin: SOA owner name
* @param[out] origin_size
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_soa_t)(librpz_emsg_t *emsg, uint32_t *ttlp,
librpz_rr_t **rrp, librpz_domain_buf_t *origin,
librpz_result_t *result, librpz_rsp_t *rsp);
LIBDEF_F(rsp_soa)
/**
* Get the SOA serial number for a policy zone to compare with a known value
* to check whether a zone transfer is complete.
*/
typedef bool(librpz_soa_serial_t)(librpz_emsg_t *emsg, uint32_t *serialp,
const char *domain_nm, librpz_rsp_t *rsp);
LIBDEF_F(soa_serial)
/**
* Save the current policy checking state.
* @param[out] emsg
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_push_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
LIBDEF_F(rsp_push)
#define LIBRPZ_RSP_STACK_DEPTH 3
/**
* Restore the previous policy checking state.
* @param[out] emsg
* @param[out] result: NULL or restored policy rewrite values
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_pop_t)(librpz_emsg_t *emsg, librpz_result_t *result,
librpz_rsp_t *rsp);
LIBDEF_F(rsp_pop)
/**
* Discard the most recently save policy checking state.
* @param[out] emsg
* @param[out] result: NULL or restored policy rewrite values
* @return false on error
*/
typedef bool(librpz_rsp_pop_discard_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
LIBDEF_F(rsp_pop_discard)
/**
* Disable a zone.
* @param[out] emsg
* @param znum
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_rsp_forget_zone_t)(librpz_emsg_t *emsg, librpz_cznum_t znum,
librpz_rsp_t *rsp);
LIBDEF_F(rsp_forget_zone)
/**
* Apply RPZ to an IP address.
* @param[out] emsg
* @param addr: address to check
* @param ipv6: true for 16 byte IPv6 instead of 4 byte IPv4
* @param trig LIBRPZ_TRIG_CLIENT_IP, LIBRPZ_TRIG_IP, or LIBRPZ_TRIG_NSIP
* @param hit_id: caller chosen
* @param recursed: recursion has been done
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_ck_ip_t)(librpz_emsg_t *emsg, const void *addr, uint family,
librpz_trig_t trig, librpz_result_id_t hit_id,
bool recursed, librpz_rsp_t *rsp);
LIBDEF_F(ck_ip)
/**
* Apply RPZ to a wire-format domain.
* @param[out] emsg
* @param domain in wire format
* @param domain_size
* @param trig LIBRPZ_TRIG_QNAME or LIBRPZ_TRIG_NSDNAME
* @param hit_id: caller chosen
* @param recursed: recursion has been done
* @param[in,out] rsp state from librpz_itr_start()
* @return false on error
*/
typedef bool(librpz_ck_domain_t)(librpz_emsg_t *emsg, const uint8_t *domain,
size_t domain_size, librpz_trig_t trig,
librpz_result_id_t hit_id, bool recursed,
librpz_rsp_t *rsp);
LIBDEF_F(ck_domain)
/**
* Ask dnsrpzd to refresh a zone.
* @param[out] emsg error message
* @param librpz_domain_t domain to refresh
* @param client context
* @return false after error
*/
typedef bool(librpz_zone_refresh_t)(librpz_emsg_t *emsg, const char *domain,
librpz_rsp_t *rsp);
LIBDEF_F(zone_refresh)
/**
* Get a string describing the database
* @param license: include the license
* @param cfiles: include the configuration file names
* @param listens: include the local notify IP addresses
* @param[out] emsg error message if the result is null
* @param client context
* @return malloc'ed string or NULL after error
*/
typedef char *(librpz_db_info_t)(librpz_emsg_t *emsg, bool license, bool cfiles,
bool listens, librpz_rsp_t *rsp);
LIBDEF_F(db_info)
/**
* Start a context for listing the nodes and/or zones in the mapped file
* @param[out] emsg: error message for false return or *rspp=NULL
* @param[out] rspp: created context or NULL
* @param client context
* @return false after error
*/
typedef bool(librpz_itr_start_t)(librpz_emsg_t *emsg, librpz_rsp_t **rspp,
librpz_client_t *client);
LIBDEF_F(itr_start)
/**
* Get mapped file memory allocation statistics.
* @param[out] emsg: error message
* @param rsp state from librpz_itr_start()
* @return malloc'ed string or NULL after error
*/
typedef char *(librpz_mf_stats_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
LIBDEF_F(mf_stats)
/**
* Get versions currently used by clients.
* @param[out] emsg: error message
* @param[in,out] rsp: state from librpz_itr_start()
* @return malloc'ed string or NULL after error
*/
typedef char *(librpz_vers_stats_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
LIBDEF_F(vers_stats)
/**
* Allocate a string describing the next zone or "" after the last zone.
* @param[out] emsg
* @param all_zones to list all instead of only requested zones
* @param[in,out] rsp state from librpz_rsp_start()
* @return malloc'ed string or NULL after error
*/
typedef char *(librpz_itr_zone_t)(librpz_emsg_t *emsg, bool all_zones,
librpz_rsp_t *rsp);
LIBDEF_F(itr_zone)
/**
* Describe the next trie node while dumping the database.
* @param[out] emsg
* @param[out] result describes node
* or result->policy=LIBRPZ_POLICY_UNDEFINED after the last node.
* @param all_zones to list all instead of only requested zones
* @param[in,out] rsp state from librpz_itr_start()
* @return: false on error
*/
typedef bool(librpz_itr_node_t)(librpz_emsg_t *emsg, librpz_result_t *result,
bool all_zones, librpz_rsp_t *rsp);
LIBDEF_F(itr_node)
/**
* RPZ policy to string with a backup buffer of POLICY2STR_SIZE size
*/
typedef const char *(librpz_policy2str_t)(librpz_policy_t policy, char *buf,
size_t buf_size);
#define POLICY2STR_SIZE sizeof("policy xxxxxx")
LIBDEF_F(policy2str)
/**
* Trigger type to string.
*/
typedef const char *(librpz_trig2str_t)(librpz_trig_t trig);
LIBDEF_F(trig2str)
/**
* Convert a number of seconds to a zone file duration string
*/
typedef const char *(librpz_secs2str_t)(time_t secs, char *buf,
size_t buf_size);
#define SECS2STR_SIZE sizeof("1234567w7d24h59m59s")
LIBDEF_F(secs2str)
/**
* Parse a duration with 's', 'm', 'h', 'd', and 'w' units.
*/
typedef bool(librpz_str2secs_t)(librpz_emsg_t *emsg, time_t *val,
const char *str0);
LIBDEF_F(str2secs)
/**
* Translate selected rtypes to strings
*/
typedef const char *(librpz_rtype2str_t)(uint type, char *buf, size_t buf_size);
#define RTYPE2STR_SIZE sizeof("type xxxxx")
LIBDEF_F(rtype2str)
/**
* Local version of ns_name_ntop() for portability.
*/
typedef int(librpz_domain_ntop_t)(const u_char *src, char *dst, size_t dstsiz);
LIBDEF_F(domain_ntop)
/**
* Local version of ns_name_pton().
*/
typedef int(librpz_domain_pton2_t)(const char *src, u_char *dst, size_t dstsiz,
size_t *dstlen, bool lower);
LIBDEF_F(domain_pton2)
typedef union socku socku_t;
typedef socku_t *(librpz_mk_inet_su_t)(socku_t *su, const struct in_addr *addrp,
in_port_t port);
LIBDEF_F(mk_inet_su)
typedef socku_t *(librpz_mk_inet6_su_t)(socku_t *su,
const struct in6_addr *addrp,
uint32_t scope_id, in_port_t port);
LIBDEF_F(mk_inet6_su)
typedef bool(librpz_str2su_t)(socku_t *sup, const char *str);
LIBDEF_F(str2su)
typedef char *(librpz_su2str_t)(char *str, size_t str_len, const socku_t *su);
LIBDEF_F(su2str)
#define SU2STR_SIZE (INET6_ADDRSTRLEN + 1 + 6 + 1)
/**
* default path to dnsrpzd
*/
LIBDEF(const char *, librpz_dnsrpzd_path)
#undef LIBDEF
/*
* This is the dlopen() interface to librpz.
*/
typedef const struct {
const char *dnsrpzd_path;
const char *version;
librpz_parse_log_opt_t *parse_log_opt;
librpz_log_level_val_t *log_level_val;
librpz_set_log_t *set_log;
librpz_vpemsg_t *vpemsg;
librpz_pemsg_t *pemsg;
librpz_vlog_t *vlog;
librpz_log_t *log;
librpz_fatal_t *fatal LIBRPZ_NORET;
librpz_rpz_assert_t *rpz_assert LIBRPZ_NORET;
librpz_rpz_vassert_t *rpz_vassert LIBRPZ_NORET;
librpz_clist_create_t *clist_create;
librpz_clist_detach_t *clist_detach;
librpz_client_create_t *client_create;
librpz_connect_t *connect;
librpz_client_detach_t *client_detach;
librpz_rsp_create_t *rsp_create;
librpz_rsp_detach_t *rsp_detach;
librpz_rsp_result_t *rsp_result;
librpz_have_trig_t *have_trig;
librpz_have_ns_trig_t *have_ns_trig;
librpz_rsp_clientip_prefix_t *rsp_clientip_prefix;
librpz_rsp_domain_t *rsp_domain;
librpz_rsp_rr_t *rsp_rr;
librpz_rsp_soa_t *rsp_soa;
librpz_soa_serial_t *soa_serial;
librpz_rsp_push_t *rsp_push;
librpz_rsp_pop_t *rsp_pop;
librpz_rsp_pop_discard_t *rsp_pop_discard;
librpz_rsp_forget_zone_t *rsp_forget_zone;
librpz_ck_ip_t *ck_ip;
librpz_ck_domain_t *ck_domain;
librpz_zone_refresh_t *zone_refresh;
librpz_db_info_t *db_info;
librpz_itr_start_t *itr_start;
librpz_mf_stats_t *mf_stats;
librpz_vers_stats_t *vers_stats;
librpz_itr_zone_t *itr_zone;
librpz_itr_node_t *itr_node;
librpz_policy2str_t *policy2str;
librpz_trig2str_t *trig2str;
librpz_secs2str_t *secs2str;
librpz_str2secs_t *str2secs;
librpz_rtype2str_t *rtype2str;
librpz_domain_ntop_t *domain_ntop;
librpz_domain_pton2_t *domain_pton2;
librpz_mk_inet_su_t *mk_inet_su;
librpz_mk_inet6_su_t *mk_inet6_su;
librpz_str2su_t *str2su;
librpz_su2str_t *su2str;
} librpz_0_t;
extern librpz_0_t librpz_def_0;
/*
* Future versions can be upward compatible by defining LIBRPZ_DEF as
* librpz_X_t.
*/
#define LIBRPZ_DEF librpz_def_0
#define LIBRPZ_DEF_STR "librpz_def_0"
typedef librpz_0_t librpz_t;
extern librpz_t *librpz;
#if LIBRPZ_LIB_OPEN == 2
#include <dlfcn.h>
/**
* link-load librpz
* @param[out] emsg: error message
* @param[in,out] dl_handle: NULL or pointer to new dlopen handle
* @param[in] path: librpz.so path
* @return address of interface structure or NULL on failure
*/
static inline librpz_t *
librpz_lib_open(librpz_emsg_t *emsg, void **dl_handle, const char *path) {
void *handle;
librpz_t *new_librpz;
emsg->c[0] = '\0';
/*
* Close a previously opened handle on librpz.so.
*/
if (dl_handle != NULL && *dl_handle != NULL) {
if (dlclose(*dl_handle) != 0) {
snprintf(emsg->c, sizeof(librpz_emsg_t),
"dlopen(NULL): %s", dlerror());
return (NULL);
}
*dl_handle = NULL;
}
/*
* First try the main executable of the process in case it was
* linked to librpz.
* Do not worry if we cannot search the main executable of the process.
*/
handle = dlopen(NULL, RTLD_NOW | RTLD_LOCAL);
if (handle != NULL) {
new_librpz = dlsym(handle, LIBRPZ_DEF_STR);
if (new_librpz != NULL) {
if (dl_handle != NULL) {
*dl_handle = handle;
}
return (new_librpz);
}
if (dlclose(handle) != 0) {
snprintf(emsg->c, sizeof(librpz_emsg_t),
"dlsym(NULL, " LIBRPZ_DEF_STR "): %s",
dlerror());
return (NULL);
}
}
if (path == NULL || path[0] == '\0') {
snprintf(emsg->c, sizeof(librpz_emsg_t),
"librpz not linked and no dlopen() path provided");
return (NULL);
}
handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
if (handle == NULL) {
snprintf(emsg->c, sizeof(librpz_emsg_t), "dlopen(%s): %s", path,
dlerror());
return (NULL);
}
new_librpz = dlsym(handle, LIBRPZ_DEF_STR);
if (new_librpz != NULL) {
if (dl_handle != NULL) {
*dl_handle = handle;
}
return (new_librpz);
}
snprintf(emsg->c, sizeof(librpz_emsg_t),
"dlsym(%s, " LIBRPZ_DEF_STR "): %s", path, dlerror());
dlclose(handle);
return (NULL);
}
#elif defined(LIBRPZ_LIB_OPEN)
/*
* Statically link to the librpz.so DSO on systems without dlopen()
*/
static inline librpz_t *
librpz_lib_open(librpz_emsg_t *emsg, void **dl_handle, const char *path) {
(void)(path);
if (dl_handle != NULL) {
*dl_handle = NULL;
}
#if LIBRPZ_LIB_OPEN == 1
emsg->c[0] = '\0';
return (&LIBRPZ_DEF);
#else /* if LIBRPZ_LIB_OPEN == 1 */
snprintf(emsg->c, sizeof(librpz_emsg_t),
"librpz not available via ./configure");
return (NULL);
#endif /* LIBRPZ_LIB_OPEN */
}
#endif /* LIBRPZ_LIB_OPEN */
#endif /* LIBRPZ_H */
Mr. DellatioNx196 GaLers xh3LL Backd00r 1.0, Coded By Mr. DellatioNx196 - Bogor BlackHat