dns64.c File Reference

This file contains a module that performs DNS64 query processing. More...

#include "config.h"
#include "dns64/dns64.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "util/config_file.h"
#include "util/data/msgreply.h"
#include "util/fptr_wlist.h"
#include "util/net_help.h"
#include "util/regional.h"
#include "util/storage/dnstree.h"
#include "util/data/dname.h"
#include "sldns/str2wire.h"

Data Structures

struct  dns64_qstate
 Per-query module-specific state. More...
 
struct  dns64_env
 This structure contains module configuration information. More...
 

Macros

#define MAX_PTR_QNAME_IPV4   30
 Maximum length of a domain name in a PTR query in the .in-addr.arpa tree.
 
#define swap(t, a, b)   do {t x = a; a = b; b = x;} while(0)
 Generic macro for swapping two variables. More...
 

Enumerations

enum  dns64_state { DNS64_INTERNAL_QUERY , DNS64_NEW_QUERY , DNS64_SUBQUERY_FINISHED }
 State of DNS64 processing for a query. More...
 

Functions

static void reverse (char *begin, char *end)
 Reverses a string. More...
 
static int uitoa (unsigned n, char *s)
 Convert an unsigned integer to a string. More...
 
static uint32_t extract_ipv4 (const uint8_t ipv6[], size_t ipv6_len, const int offset)
 Extract an IPv4 address embedded in the IPv6 address ipv6 at offset offset (in bits). More...
 
static size_t ipv4_to_ptr (uint32_t ipv4, char ptr[], size_t nm_len)
 Builds the PTR query name corresponding to an IPv4 address. More...
 
static int ptr_to_ipv6 (const char *ptr, uint8_t ipv6[], size_t ipv6_len)
 Converts an IPv6-related domain name string from a PTR query into an IPv6 address represented as a 128-bit array. More...
 
static void synthesize_aaaa (const uint8_t prefix_addr[], size_t prefix_addr_len, int prefix_net, const uint8_t a[], size_t a_len, uint8_t aaaa[], size_t aaaa_len)
 Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix. More...
 
static int dns64_insert_ignore_aaaa (struct dns64_env *dns64_env, char *str)
 insert ignore_aaaa element into the tree More...
 
static int dns64_apply_cfg (struct dns64_env *dns64_env, struct config_file *cfg)
 This function applies the configuration found in the parsed configuration file cfg to this instance of the dns64 module. More...
 
int dns64_init (struct module_env *env, int id)
 Initializes this instance of the dns64 module. More...
 
static void free_ignore_aaaa_node (rbnode_type *node, void *ATTR_UNUSED(arg))
 free ignore AAAA elements
 
void dns64_deinit (struct module_env *env, int id)
 Deinitializes this instance of the dns64 module. More...
 
static enum module_ext_state handle_ipv6_ptr (struct module_qstate *qstate, int id)
 Handle PTR queries for IPv6 addresses. More...
 
static enum module_ext_state generate_type_A_query (struct module_qstate *qstate, int id)
 
static int dns64_always_synth_for_qname (struct module_qstate *qstate, int id)
 See if query name is in the always synth config. More...
 
static enum module_ext_state handle_event_pass (struct module_qstate *qstate, int id)
 Handles the "pass" event for a query. More...
 
static enum module_ext_state handle_event_moddone (struct module_qstate *qstate, int id)
 Handles the "done" event for a query. More...
 
void dns64_operate (struct module_qstate *qstate, enum module_ev event, int id, struct outbound_entry *outbound)
 This is the module's main() function. More...
 
static void dns64_synth_aaaa_data (const struct ub_packed_rrset_key *fk, const struct packed_rrset_data *fd, struct ub_packed_rrset_key *dk, struct packed_rrset_data **dd_out, struct regional *region, struct dns64_env *dns64_env)
 
static void dns64_adjust_a (int id, struct module_qstate *super, struct module_qstate *qstate)
 Synthesize an AAAA RR set from an A sub-query's answer and add it to the original empty response. More...
 
static void dns64_adjust_ptr (struct module_qstate *qstate, struct module_qstate *super)
 Generate a response for the original IPv6 PTR query based on an IPv4 PTR sub-query's response. More...
 
void dns64_inform_super (struct module_qstate *qstate, int id, struct module_qstate *super)
 This function is called when a sub-query finishes to inform the parent query. More...
 
void dns64_clear (struct module_qstate *qstate, int id)
 Clear module-specific data from query state. More...
 
size_t dns64_get_mem (struct module_env *env, int id)
 Returns the amount of global memory that this module uses, not including per-query data. More...
 
struct module_func_blockdns64_get_funcblock (void)
 Function for returning the above function block. More...
 

Variables

static const char DEFAULT_DNS64_PREFIX [] = "64:ff9b::/96"
 This is the default DNS64 prefix that is used when the dns64 module is listed in module-config but when the dns64-prefix variable is not present.
 
static struct module_func_block dns64_block
 The dns64 function block. More...
 

Detailed Description

This file contains a module that performs DNS64 query processing.

Macro Definition Documentation

◆ swap

#define swap (   t,
  a,
 
)    do {t x = a; a = b; b = x;} while(0)

Generic macro for swapping two variables.

Parameters
tType of the variables. (e.g. int)
aFirst variable.
bSecond variable.
Warning
Do not attempt something foolish such as swap(int,a++,b++)!

Enumeration Type Documentation

◆ dns64_state

State of DNS64 processing for a query.

Enumerator
DNS64_INTERNAL_QUERY 

Internally-generated query, no DNS64 processing.

DNS64_NEW_QUERY 

Query for which we're the first module in line.

DNS64_SUBQUERY_FINISHED 

Query for which we generated a sub-query, and for which this sub-query is finished.

Function Documentation

◆ reverse()

static void reverse ( char *  begin,
char *  end 
)
static

Reverses a string.

Parameters
beginPoints to the first character of the string.
endPoints one past the last character of the string.

References swap.

Referenced by lookup(), massage_qname(), massage_type(), and uitoa().

◆ uitoa()

static int uitoa ( unsigned  n,
char *  s 
)
static

Convert an unsigned integer to a string.

The point of this function is that of being faster than sprintf().

Parameters
nThe number to be converted.
sThe result will be written here. Must be large enough, be careful!
Returns
The number of characters written.

References reverse().

Referenced by ipv4_to_ptr().

◆ extract_ipv4()

static uint32_t extract_ipv4 ( const uint8_t  ipv6[],
size_t  ipv6_len,
const int  offset 
)
static

Extract an IPv4 address embedded in the IPv6 address ipv6 at offset offset (in bits).

Note that bits are not necessarily aligned on bytes so we need to be careful.

Parameters
ipv6IPv6 address represented as a 128-bit array in big-endian order.
ipv6_lenlength of the ipv6 byte array.
offsetIndex of the MSB of the IPv4 address embedded in the IPv6 address.

References log_assert.

◆ ipv4_to_ptr()

static size_t ipv4_to_ptr ( uint32_t  ipv4,
char  ptr[],
size_t  nm_len 
)
static

Builds the PTR query name corresponding to an IPv4 address.

For example, given the number 3,464,175,361, this will build the string "\03206\03123\0231\011\07in-addr\04arpa".

Parameters
ipv4IPv4 address represented as an unsigned 32-bit number.
ptrThe result will be written here. Must be large enough, be careful!
nm_lenlength of the ptr buffer.
Returns
The number of characters written.

References log_assert, MAX_PTR_QNAME_IPV4, and uitoa().

◆ ptr_to_ipv6()

static int ptr_to_ipv6 ( const char *  ptr,
uint8_t  ipv6[],
size_t  ipv6_len 
)
static

Converts an IPv6-related domain name string from a PTR query into an IPv6 address represented as a 128-bit array.

Parameters
ptrThe domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa")
ipv6The result will be written here, in network byte order.
ipv6_lenlength of the ipv6 byte array.
Returns
1 on success, 0 on failure.

References log_assert.

◆ synthesize_aaaa()

static void synthesize_aaaa ( const uint8_t  prefix_addr[],
size_t  prefix_addr_len,
int  prefix_net,
const uint8_t  a[],
size_t  a_len,
uint8_t  aaaa[],
size_t  aaaa_len 
)
static

Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix.

Parameters
prefix_addrDNS64 prefix address.
prefix_addr_lenlength of the prefix_addr buffer.
prefix_netCIDR length of the DNS64 prefix. Must be between 0 and 96.
aIPv4 address.
a_lenlength of the a buffer.
aaaaIPv6 address. The result will be written here.
aaaa_lenlength of the aaaa buffer.

References log_assert.

◆ dns64_insert_ignore_aaaa()

static int dns64_insert_ignore_aaaa ( struct dns64_env dns64_env,
char *  str 
)
static

insert ignore_aaaa element into the tree

Parameters
dns64_envmodule env.
strstring with domain name.
Returns
false on failure.

Referenced by dns64_apply_cfg().

◆ dns64_apply_cfg()

static int dns64_apply_cfg ( struct dns64_env dns64_env,
struct config_file cfg 
)
static

This function applies the configuration found in the parsed configuration file cfg to this instance of the dns64 module.

Currently only the DNS64 prefix (a.k.a. Pref64) is configurable.

Parameters
dns64_envModule-specific global parameters.
cfgParsed configuration file.

References addr_is_ip6(), DEFAULT_DNS64_PREFIX, config_file::dns64_ignore_aaaa, dns64_insert_ignore_aaaa(), dns64_env::ignore_aaaa, log_err(), name_tree_init_parents(), netblockstrtoaddr(), config_strlist::next, dns64_env::prefix_addr, dns64_env::prefix_addrlen, dns64_env::prefix_net, config_strlist::str, VERB_ALGO, and verbose().

Referenced by dns64_init().

◆ dns64_init()

int dns64_init ( struct module_env env,
int  id 
)

Initializes this instance of the dns64 module.

dns64 init

Parameters
envGlobal state of all module instances.
idThis instance's ID number.

References module_env::cfg, dns64_apply_cfg(), dns64_env::ignore_aaaa, log_err(), module_env::modinfo, and name_tree_init().

Referenced by fptr_whitelist_mod_init().

◆ dns64_deinit()

void dns64_deinit ( struct module_env env,
int  id 
)

Deinitializes this instance of the dns64 module.

dns64 deinit

Parameters
envGlobal state of all module instances.
idThis instance's ID number.

References free_ignore_aaaa_node(), dns64_env::ignore_aaaa, module_env::modinfo, and traverse_postorder().

Referenced by fptr_whitelist_mod_deinit().

◆ handle_ipv6_ptr()

static enum module_ext_state handle_ipv6_ptr ( struct module_qstate qstate,
int  id 
)
static

Handle PTR queries for IPv6 addresses.

If the address belongs to the DNS64 prefix, we must do a PTR query for the corresponding IPv4 address instead.

Parameters
qstateQuery state structure.
idThis module instance's ID number.
Returns
The new state of the query.

◆ dns64_always_synth_for_qname()

static int dns64_always_synth_for_qname ( struct module_qstate qstate,
int  id 
)
static

See if query name is in the always synth config.

The ignore-aaaa list has names for which the AAAA for the domain is ignored and the A is always used to create the answer.

Parameters
qstatequery state.
idmodule id.
Returns
true if the name is covered by ignore-aaaa.

References dname_count_labels(), module_qstate::env, dns64_env::ignore_aaaa, name_tree_node::labs, module_env::modinfo, name_tree_lookup(), name_tree_node::node, query_info::qclass, module_qstate::qinfo, query_info::qname, and query_info::qname_len.

◆ handle_event_pass()

static enum module_ext_state handle_event_pass ( struct module_qstate qstate,
int  id 
)
static

Handles the "pass" event for a query.

This event is received when a new query is received by this module. The query may have been generated internally by another module, in which case we don't want to do any special processing (this is an interesting discussion topic), or it may be brand new, e.g. received over a socket, in which case we do want to apply DNS64 processing.

Parameters
qstateA structure representing the state of the query that has just received the "pass" event.
idThis module's instance ID.
Returns
The new state of the query.

Referenced by dns64_operate().

◆ handle_event_moddone()

static enum module_ext_state handle_event_moddone ( struct module_qstate qstate,
int  id 
)
static

Handles the "done" event for a query.

We need to analyze the response and maybe issue a new sub-query for the A record.

Parameters
qstateA structure representing the state of the query that has just received the "pass" event.
idThis module's instance ID.
Returns
The new state of the query.

Referenced by dns64_operate().

◆ dns64_operate()

void dns64_operate ( struct module_qstate qstate,
enum module_ev  event,
int  id,
struct outbound_entry outbound 
)

This is the module's main() function.

dns64 operate on a query

It gets called each time a query receives an event which we may need to handle. We respond by updating the state of the query.

Parameters
qstateStructure containing the state of the query.
eventEvent that has just been received.
idThis module's instance ID.
outboundState of a DNS query on an authoritative server. We never do our own queries ourselves (other modules do it for us), so this is unused.

References DNS64_INTERNAL_QUERY, DNS64_NEW_QUERY, module_qstate::ext_state, handle_event_moddone(), handle_event_pass(), log_err(), log_query_info(), module_qstate::minfo, module_error, module_event_moddone, module_event_new, module_event_pass, module_finished, module_qstate::no_cache_store, module_qstate::qinfo, module_qstate::region, regional_alloc(), dns64_qstate::started_no_cache_store, dns64_qstate::state, strextstate(), strmodulevent(), VERB_QUERY, and verbose().

Referenced by fptr_whitelist_mod_operate().

◆ dns64_adjust_a()

static void dns64_adjust_a ( int  id,
struct module_qstate super,
struct module_qstate qstate 
)
static

◆ dns64_adjust_ptr()

static void dns64_adjust_ptr ( struct module_qstate qstate,
struct module_qstate super 
)
static

Generate a response for the original IPv6 PTR query based on an IPv4 PTR sub-query's response.

Parameters
qstateIPv4 PTR sub-query.
superOriginal IPv6 PTR query.

References packed_rrset_key::dname, packed_rrset_key::dname_len, dns_msg::qinfo, module_qstate::qinfo, query_info::qname, query_info::qname_len, module_qstate::region, regional_alloc(), dns_msg::rep, reply_find_answer_rrset(), reply_info_copy(), module_qstate::return_msg, ub_packed_rrset_key::rk, VERB_ALGO, and verbose().

◆ dns64_inform_super()

void dns64_inform_super ( struct module_qstate qstate,
int  id,
struct module_qstate super 
)

This function is called when a sub-query finishes to inform the parent query.

We issue two kinds of sub-queries: PTR and A.

Parameters
qstateState of the sub-query.
idThis module's instance ID.
superState of the super-query.

References log_err(), log_query_info(), module_qstate::minfo, module_qstate::qinfo, module_qstate::region, regional_alloc(), module_qstate::return_rcode, and VERB_ALGO.

Referenced by fptr_whitelist_mod_inform_super().

◆ dns64_clear()

void dns64_clear ( struct module_qstate qstate,
int  id 
)

Clear module-specific data from query state.

dns64 cleanup query state

Since we do not allocate memory, it's just a matter of setting a pointer to NULL.

Parameters
qstateQuery state.
idThis module's instance ID.

References module_qstate::minfo.

Referenced by fptr_whitelist_mod_clear().

◆ dns64_get_mem()

size_t dns64_get_mem ( struct module_env env,
int  id 
)

Returns the amount of global memory that this module uses, not including per-query data.

dns64 alloc size routine

Parameters
envModule environment.
idThis module's instance ID.

Referenced by fptr_whitelist_mod_get_mem().

◆ dns64_get_funcblock()

struct module_func_block* dns64_get_funcblock ( void  )

Function for returning the above function block.

Get the dns64 function block.

Referenced by module_funcs_avail().

Variable Documentation

◆ dns64_block

struct module_func_block dns64_block
static
Initial value:
= {
"dns64",
}
void dns64_deinit(struct module_env *env, int id)
Deinitializes this instance of the dns64 module.
Definition: dns64.c:436
size_t dns64_get_mem(struct module_env *env, int id)
Returns the amount of global memory that this module uses, not including per-query data.
Definition: dns64.c:1034
void dns64_operate(struct module_qstate *qstate, enum module_ev event, int id, struct outbound_entry *outbound)
This is the module's main() function.
Definition: dns64.c:681
void dns64_clear(struct module_qstate *qstate, int id)
Clear module-specific data from query state.
Definition: dns64.c:1021
int dns64_init(struct module_env *env, int id)
Initializes this instance of the dns64 module.
Definition: dns64.c:402
void dns64_inform_super(struct module_qstate *qstate, int id, struct module_qstate *super)
This function is called when a sub-query finishes to inform the parent query.
Definition: dns64.c:951

The dns64 function block.