Maintained by: NLnet Labs
Data Structures | Macros | Enumerations | Functions | Variables
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"

Data Structures

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_qstate { DNS64_INTERNAL_QUERY, DNS64_NEW_QUERY, DNS64_SUBQUERY_FINISHED }
 Per-query module-specific state. 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[16], 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[MAX_PTR_QNAME_IPV4])
 Builds the PTR query name corresponding to an IPv4 address. More...
 
static int ptr_to_ipv6 (const char *ptr, uint8_t ipv6[16])
 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[16], int prefix_net, const uint8_t a[4], uint8_t aaaa[16])
 Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix. 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...
 
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 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 whent he 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++)!

Referenced by reverse().

Enumeration Type Documentation

◆ dns64_qstate

Per-query module-specific state.

This is usually a dynamically-allocated structure, but in our case we only need to store one variable describing the state the query is in. So we repurpose the minfo pointer by storing an integer in there.

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 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[16],
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.
offsetIndex of the MSB of the IPv4 address embedded in the IPv6 address.

Referenced by handle_ipv6_ptr().

◆ ipv4_to_ptr()

static size_t ipv4_to_ptr ( uint32_t  ipv4,
char  ptr[MAX_PTR_QNAME_IPV4] 
)
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!
Returns
The number of characters written.

References uitoa().

Referenced by handle_ipv6_ptr().

◆ ptr_to_ipv6()

static int ptr_to_ipv6 ( const char *  ptr,
uint8_t  ipv6[16] 
)
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.
Returns
1 on success, 0 on failure.

Referenced by handle_ipv6_ptr().

◆ synthesize_aaaa()

static void synthesize_aaaa ( const uint8_t  prefix_addr[16],
int  prefix_net,
const uint8_t  a[4],
uint8_t  aaaa[16] 
)
static

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

Parameters
prefix_addrDNS64 prefix address.
prefix_netCIDR length of the DNS64 prefix. Must be between 0 and 96.
aIPv4 address.
aaaaIPv6 address. The result will be written here.

◆ 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, log_err(), netblockstrtoaddr(), dns64_env::prefix_addr, dns64_env::prefix_addrlen, dns64_env::prefix_net, 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(), log_err(), and module_env::modinfo.

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 module_env::modinfo.

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.

References addr_in_common(), module_env::attach_sub, module_qstate::env, extract_ipv4(), fptr_ok, fptr_whitelist_modenv_attach_sub(), ipv4_to_ptr(), MAX_PTR_QNAME_IPV4, module_env::modinfo, module_error, module_state_initial, module_wait_module, module_wait_subquery, dns64_env::prefix_addr, dns64_env::prefix_net, ptr_to_ipv6(), module_qstate::qinfo, query_info::qname, module_qstate::query_flags, module_qstate::region, regional_alloc(), VERB_ALGO, and verbose().

Referenced by handle_event_pass().

◆ 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.

References module_env::cfg, DNS64_NEW_QUERY, module_qstate::env, handle_ipv6_ptr(), LDNS_RR_TYPE_AAAA, LDNS_RR_TYPE_PTR, module_qstate::minfo, module_qstate::qinfo, query_info::qname, query_info::qname_len, and query_info::qtype.

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.

References BIT_CD, DNS64_INTERNAL_QUERY, LDNS_RR_TYPE_AAAA, module_qstate::minfo, module_finished, module_qstate::qinfo, query_info::qtype, module_qstate::query_flags, dns_msg::rep, reply_find_answer_rrset(), and module_qstate::return_msg.

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_NEW_QUERY, module_qstate::ext_state, handle_event_moddone(), handle_event_pass(), log_query_info(), module_qstate::minfo, module_event_moddone, module_event_new, module_event_pass, module_finished, module_qstate::qinfo, 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

Synthesize an AAAA RR set from an A sub-query's answer and add it to the original empty response.

Parameters
idThis module's instance ID.
superOriginal AAAA query.
qstateA query.

References construct_reply_info_base(), lruhash_entry::data, ub_packed_rrset_key::entry, module_qstate::env, ub_packed_rrset_key::id, LDNS_RR_TYPE_A, log_assert, module_env::modinfo, dns_msg::qinfo, module_qstate::qinfo, module_qstate::region, regional_alloc(), dns_msg::rep, reply_info_alloc_rrset_keys(), module_qstate::return_msg, ub_packed_rrset_key::rk, VERB_ALGO, and verbose().

◆ 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, log_assert, 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 DNS64_SUBQUERY_FINISHED, ub_packed_rrset_key::id, log_query_info(), module_qstate::minfo, module_qstate::qinfo, 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 ub_packed_rrset_key::id, and 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.

References module_env::modinfo.

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.

References dns64_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:347
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:835
int dns64_init(struct module_env *env, int id)
Initializes this instance of the dns64 module.
Definition: dns64.c:324
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:530
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:774
void dns64_clear(struct module_qstate *qstate, int id)
Clear module-specific data from query state.
Definition: dns64.c:822

The dns64 function block.

Referenced by dns64_get_funcblock().