unbound: dns64/dns64.c File Reference

unbound 0.1

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"`
`#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)
| Generic macro for swapping two variables.

## 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.
static int | uitoa (unsigned n, char *s)
| Convert an unsigned integer to a string.
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).
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.
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.
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.
static int | dns64_insert_ignore_aaaa (struct dns64_env *dns64_env, char *str)
| insert ignore_aaaa element into the tree
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.
int | dns64_init (struct module_env *env, int id)
| Initializes this instance of the dns64 module.
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.
static enum module_ext_state | handle_ipv6_ptr (struct module_qstate *qstate, int id)
| Handle PTR queries for IPv6 addresses.
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.
static enum module_ext_state | handle_event_pass (struct module_qstate *qstate, int id)
| Handles the "pass" event for a query.
static enum module_ext_state | handle_event_moddone (struct module_qstate *qstate, int id)
| Handles the "done" event for a query.
void | dns64_operate (struct module_qstate *qstate, enum module_ev event, int id, struct outbound_entry *outbound)
| This is the module's main() function.
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.
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.
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.
void | dns64_clear (struct module_qstate *qstate, int id)
| Clear module-specific data from query state.
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.
struct module_func_block * | dns64_get_funcblock (void)
| Function for returning the above function block.

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

## Detailed Description

This file contains a module that performs DNS64 query processing.

## Macro Definition Documentation

## ◆ swap

#define swap | ( |  | t,
|  |  | a,
|  |  | b )

Value:
do {t x = a; a = b; b = x;} while(0)

Generic macro for swapping two variables.

Parameters

  t | Type of the variables. (e.g. int)
  a | First variable.
  b | Second variable.

Warning
  Do not attempt something foolish such as swap(int,a++,b++)!

Referenced by reverse().

## Enumeration Type Documentation

## ◆ dns64_state

enum 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

  begin | Points to the first character of the string.
  end | Points 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

  n | The number to be converted.
  s | The 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

  ipv6 | IPv6 address represented as a 128-bit array in big-endian order.
  ipv6_len | length of the ipv6 byte array.
  offset | Index of the MSB of the IPv4 address embedded in the IPv6 address.

References log_assert.

Referenced by handle_ipv6_ptr().

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

  ipv4 | IPv4 address represented as an unsigned 32-bit number.
  ptr | The result will be written here. Must be large enough, be careful!
  nm_len | length of the ptr buffer.

Returns
  The number of characters written.

References log_assert, MAX_PTR_QNAME_IPV4, and uitoa().

Referenced by handle_ipv6_ptr().

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

  ptr | The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa")
  ipv6 | The result will be written here, in network byte order.
  ipv6_len | length of the ipv6 byte array.

Returns
  1 on success, 0 on failure.

References log_assert.

Referenced by handle_ipv6_ptr().

## ◆ 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_addr | DNS64 prefix address.
  prefix_addr_len | length of the prefix_addr buffer.
  prefix_net | CIDR length of the DNS64 prefix. Must be between 0 and 96.
  a | IPv4 address.
  a_len | length of the a buffer.
  aaaa | IPv6 address. The result will be written here.
  aaaa_len | length 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_env | module env.
  str | string with domain name.

Returns
  false on failure.

References dname_count_labels(), dns64_env::ignore_aaaa, LDNS_RR_CLASS_IN, log_err(), name_tree_insert(), name_tree_node::node, and sldns_str2wire_dname().

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_env | Module-specific global parameters.
  cfg | Parsed 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

  env | Global state of all module instances.
  id | This 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

  env | Global state of all module instances.
  id | This 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

  qstate | Query state structure.
  id | This module instance's ID number.

Returns
  The new state of the query.

References addr_in_common(), module_env::attach_sub, module_qstate::curmod, module_qstate::env, module_qstate::ext_state, extract_ipv4(), fptr_ok, fptr_whitelist_modenv_attach_sub(), ipv4_to_ptr(), MAX_PTR_QNAME_IPV4, module_qstate::minfo, 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, query_info::qname_len, module_qstate::query_flags, module_qstate::region, regional_alloc(), VERB_ALGO, and verbose().

Referenced by handle_event_pass().

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

  qstate | query state.
  id | module 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.

Referenced by handle_event_moddone(), and 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

  qstate | A structure representing the state of the query that has just received the "pass" event.
  id | This module's instance ID.

Returns
  The new state of the query.

References BIT_CD, module_env::cfg, dns64_always_synth_for_qname(), DNS64_NEW_QUERY, DNS64_SUBQUERY_FINISHED, module_qstate::env, handle_ipv6_ptr(), LDNS_RR_TYPE_AAAA, LDNS_RR_TYPE_PTR, module_qstate::minfo, module_finished, module_wait_module, module_qstate::qinfo, query_info::qname, query_info::qname_len, query_info::qtype, module_qstate::query_flags, dns64_qstate::state, VERB_ALGO, and verbose().

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

  qstate | A structure representing the state of the query that has just received the "pass" event.
  id | This module's instance ID.

Returns
  The new state of the query.

References BIT_CD, dns64_always_synth_for_qname(), DNS64_INTERNAL_QUERY, dns_cache_store(), module_qstate::env, LDNS_RR_TYPE_AAAA, log_err(), module_qstate::minfo, module_finished, module_qstate::qinfo, module_qstate::qstarttime, query_info::qtype, module_qstate::query_flags, dns_msg::rep, reply_find_answer_rrset(), module_qstate::return_msg, dns64_qstate::started_no_cache_store, dns64_qstate::state, VERB_ALGO, and verbose().

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

  qstate | Structure containing the state of the query.
  event | Event that has just been received.
  id | This module's instance ID.
  outbound | State 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

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

Parameters

  id | This module's instance ID.
  super | Original AAAA query.
  qstate | A query.

References reply_info::an_numrrsets, reply_info::ar_numrrsets, construct_reply_info_base(), lruhash_entry::data, packed_rrset_key::dname, packed_rrset_key::dname_len, ub_packed_rrset_key::entry, module_qstate::env, reply_info::flags, lruhash_entry::hash, ub_packed_rrset_key::id, LDNS_RR_CLASS_IN, LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA, log_assert, module_env::modinfo, msg_cache_remove(), reply_info::ns_numrrsets, packed_rrset_ptr_fixup(), packed_rrset_sizeof(), reply_info::prefetch_ttl, reply_info::qdcount, dns_msg::qinfo, module_qstate::qinfo, module_qstate::region, regional_alloc(), regional_alloc_init(), dns_msg::rep, reply_info_alloc_rrset_keys(), module_qstate::return_msg, ub_packed_rrset_key::rk, module_env::rrset_cache, rrset_cache_remove(), reply_info::rrset_count, reply_info::rrsets, reply_info::security, reply_info::serve_expired_ttl, reply_info::ttl, packed_rrset_key::type, VERB_ALGO, and verbose().

Referenced by dns64_inform_super().

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

  qstate | IPv4 PTR sub-query.
  super | Original 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().

Referenced by dns64_inform_super().

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

  qstate | State of the sub-query.
  id | This module's instance ID.
  super | State of the super-query.

References dns64_adjust_a(), dns64_adjust_ptr(), DNS64_INTERNAL_QUERY, DNS64_SUBQUERY_FINISHED, dns_cache_store(), module_qstate::env, LDNS_RR_TYPE_A, LDNS_RR_TYPE_PTR, log_assert, log_err(), log_query_info(), module_qstate::minfo, module_qstate::no_cache_store, module_qstate::qinfo, module_qstate::qstarttime, query_info::qtype, module_qstate::query_flags, module_qstate::region, regional_alloc(), dns_msg::rep, reply_find_answer_rrset(), module_qstate::return_msg, module_qstate::return_rcode, dns64_qstate::started_no_cache_store, dns64_qstate::state, 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

  qstate | Query state.
  id | This 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

  env | Module environment.
  id | This 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",
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
&dns64_inform_super, &dns64_clear, &dns64_get_mem
}
dns64_deinit
void dns64_deinit(struct module_env *env, int id)
Deinitializes this instance of the dns64 module.
Definition dns64.c:436
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.
Definition dns64.c:1035
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.
Definition dns64.c:681
dns64_clear
void dns64_clear(struct module_qstate *qstate, int id)
Clear module-specific data from query state.
Definition dns64.c:1022
dns64_init
int dns64_init(struct module_env *env, int id)
Initializes this instance of the dns64 module.
Definition dns64.c:402
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.
Definition dns64.c:952

The dns64 function block.

Referenced by dns64_get_funcblock().