unbound: util/data/msgencode.c File Reference

unbound 0.1

Data Structures | Macros | Functions
msgencode.c File Reference

This file contains a routines to encode DNS messages. More...

`#include "config.h"`
`#include "util/data/msgencode.h"`
`#include "util/data/msgreply.h"`
`#include "util/data/msgparse.h"`
`#include "util/data/dname.h"`
`#include "util/log.h"`
`#include "util/regional.h"`
`#include "util/net_help.h"`
`#include "sldns/sbuffer.h"`
`#include "services/localzone.h"`
`#include <sys/time.h>`

## Data Structures
struct | compress_tree_node
| Data structure to help domain name compression in outgoing messages. More...

## Macros
#define | RETVAL_OUTMEM -2
| return code that means the function ran out of memory.
#define | RETVAL_TRUNC -4
| return code that means the data did not fit (completely) in the packet
#define | RETVAL_OK 0
| return code that means all is peachy keen.

## Functions
static int | compress_tree_search (struct compress_tree_node **tree, uint8_t *dname, int labs, struct compress_tree_node **match, int *matchlabels, struct compress_tree_node ***insertpt)
| Find domain name in tree, returns exact and closest match.
static struct compress_tree_node * | compress_tree_lookup (struct compress_tree_node **tree, uint8_t *dname, int labs, struct compress_tree_node ***insertpt)
| Lookup a domain name in compression tree.
static struct compress_tree_node * | compress_tree_newnode (uint8_t *dname, int labs, size_t offset, struct regional *region)
| Create node for domain name compression tree.
static int | compress_tree_store (uint8_t *dname, int labs, size_t offset, struct regional *region, struct compress_tree_node *closest, struct compress_tree_node **insertpt)
| Store domain name and ancestors into compression tree.
static int | write_compressed_dname (sldns_buffer *pkt, uint8_t *dname, int labs, struct compress_tree_node *p)
| compress a domain name
static int | compress_owner (struct ub_packed_rrset_key *key, sldns_buffer *pkt, struct regional *region, struct compress_tree_node **tree, size_t owner_pos, uint16_t *owner_ptr, int owner_labs)
| compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC
static int | compress_any_dname (uint8_t *dname, sldns_buffer *pkt, int labs, struct regional *region, struct compress_tree_node **tree)
| compress any domain name to the packet, return RETVAL_*
static const sldns_rr_descriptor * | type_rdata_compressable (struct ub_packed_rrset_key *key)
| return true if type needs domain name compression in rdata
static int | compress_rdata (sldns_buffer *pkt, uint8_t *rdata, size_t todolen, struct regional *region, struct compress_tree_node **tree, const sldns_rr_descriptor *desc)
| compress domain names in rdata, return RETVAL_*
static int | rrset_belongs_in_reply (sldns_pkt_section s, uint16_t rrtype, uint16_t qtype, int dnssec)
| Returns true if RR type should be included.
static int | packed_rrset_encode (struct ub_packed_rrset_key *key, sldns_buffer *pkt, uint16_t *num_rrs, time_t timenow, struct regional *region, int do_data, int do_sig, struct compress_tree_node **tree, sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
| store rrset in buffer in wireformat, return RETVAL_*
static int | insert_section (struct reply_info *rep, size_t num_rrsets, uint16_t *num_rrs, sldns_buffer *pkt, size_t rrsets_before, time_t timenow, struct regional *region, struct compress_tree_node **tree, sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
| store msg section in wireformat buffer, return RETVAL_*
static int | insert_query (struct query_info *qinfo, struct compress_tree_node **tree, sldns_buffer *buffer, struct regional *region)
| store query section in wireformat buffer, return RETVAL
static int | positive_answer (struct reply_info *rep, uint16_t qtype)
static int | negative_answer (struct reply_info *rep)
int | reply_info_encode (struct query_info *qinfo, struct reply_info *rep, uint16_t id, uint16_t flags, sldns_buffer *buffer, time_t timenow, struct regional *region, uint16_t udpsize, int dnssec, int minimise)
| Regenerate the wireformat from the stored msg reply.
uint16_t | calc_edns_field_size (struct edns_data *edns)
| Estimate size of EDNS record in packet.
static void | attach_edns_record_max_msg_sz (sldns_buffer *pkt, struct edns_data *edns, uint16_t max_msg_sz)
void | attach_edns_record (sldns_buffer *pkt, struct edns_data *edns)
| Attach EDNS record to buffer.
int | reply_info_answer_encode (struct query_info *qinf, struct reply_info *rep, uint16_t id, uint16_t qflags, sldns_buffer *pkt, time_t timenow, int cached, struct regional *region, uint16_t udpsize, struct edns_data *edns, int dnssec, int secure)
| Generate answer from reply_info.
void | qinfo_query_encode (sldns_buffer *pkt, struct query_info *qinfo)
| Encode query packet.
void | error_encode (sldns_buffer *buf, int r, struct query_info *qinfo, uint16_t qid, uint16_t qflags, struct edns_data *edns)
| Encode an error.

## Detailed Description

This file contains a routines to encode DNS messages.

## Macro Definition Documentation

## ◆ RETVAL_OUTMEM

#define RETVAL_OUTMEM -2

return code that means the function ran out of memory.

negative so it does not conflict with DNS rcodes.

## ◆ RETVAL_OK

#define RETVAL_OK 0

return code that means all is peachy keen.

Equal to DNS rcode NOERROR

## Function Documentation

## ◆ compress_tree_search()

static int compress_tree_search | ( | struct compress_tree_node ** | tree,
|  | uint8_t * | dname,
|  | int | labs,
|  | struct compress_tree_node ** | match,
|  | int * | matchlabels,
|  | struct compress_tree_node *** | insertpt
| ) |  |
| static

Find domain name in tree, returns exact and closest match.

Parameters

  tree | root of tree.
  dname | pointer to uncompressed dname.
  labs | number of labels in domain name.
  match | closest or exact match. guaranteed to be smaller or equal to the sought dname. can be null if the tree is empty.
  matchlabels | number of labels that match with closest match. can be zero is there is no match.
  insertpt | insert location for dname, if not found.

Returns
  : 0 if no exact match.

References compress_tree_node::dname, dname_lab_cmp(), compress_tree_node::labs, compress_tree_node::left, match(), and compress_tree_node::right.

Referenced by compress_tree_lookup().

## ◆ compress_tree_lookup()

static struct compress_tree_node * compress_tree_lookup | ( | struct compress_tree_node ** | tree,
|  | uint8_t * | dname,
|  | int | labs,
|  | struct compress_tree_node *** | insertpt
| ) |  |
| static

Lookup a domain name in compression tree.

Parameters

  tree | root of tree (not the node with '.').
  dname | pointer to uncompressed dname.
  labs | number of labels in domain name.
  insertpt | insert location for dname, if not found.

Returns
  : 0 if not found or compress treenode with best compression.

References compress_tree_search(), compress_tree_node::dname, compress_tree_node::labs, and compress_tree_node::parent.

Referenced by compress_any_dname(), and compress_owner().

## ◆ compress_tree_newnode()

static struct compress_tree_node * compress_tree_newnode | ( | uint8_t * | dname,
|  | int | labs,
|  | size_t | offset,
|  | struct regional * | region
| ) |  |
| static

Create node for domain name compression tree.

Parameters

  dname | pointer to uncompressed dname (stored in tree).
  labs | number of labels in dname.
  offset | offset into packet for dname.
  region | how to allocate memory for new node.

Returns
  new node or 0 on malloc failure.

References compress_tree_node::dname, compress_tree_node::labs, compress_tree_node::left, compress_tree_node::offset, compress_tree_node::parent, regional_alloc(), and compress_tree_node::right.

Referenced by compress_tree_store().

## ◆ compress_tree_store()

static int compress_tree_store | ( | uint8_t * | dname,
|  | int | labs,
|  | size_t | offset,
|  | struct regional * | region,
|  | struct compress_tree_node * | closest,
|  | struct compress_tree_node ** | insertpt
| ) |  |
| static

Store domain name and ancestors into compression tree.

Parameters

  dname | pointer to uncompressed dname (stored in tree).
  labs | number of labels in dname.
  offset | offset into packet for dname.
  region | how to allocate memory for new node.
  closest | match from previous lookup, used to compress dname. may be NULL if no previous match. if the tree has an ancestor of dname already, this must be it.
  insertpt | where to insert the dname in tree.

Returns
  : 0 on memory error.

References compress_tree_newnode(), compress_tree_node::dname, compress_tree_node::labs, log_assert, compress_tree_node::offset, compress_tree_node::parent, PTR_MAX_OFFSET, and compress_tree_node::right.

Referenced by compress_any_dname(), compress_owner(), and insert_query().

## ◆ packed_rrset_encode()

static int packed_rrset_encode | ( | struct ub_packed_rrset_key * | key,
|  | sldns_buffer * | pkt,
|  | uint16_t * | num_rrs,
|  | time_t | timenow,
|  | struct regional * | region,
|  | int | do_data,
|  | int | do_sig,
|  | struct compress_tree_node ** | tree,
|  | sldns_pkt_section | s,
|  | uint16_t | qtype,
|  | int | dnssec,
|  | size_t | rr_offset
| ) |  |
| static

store rrset in buffer in wireformat, return RETVAL_*

Determine relative time adjustment for TTL values. For an rrset with a fixed TTL, use the rrset's TTL as given.

References compress_any_dname(), compress_owner(), compress_rdata(), packed_rrset_data::count, lruhash_entry::data, packed_rrset_key::dname, dname_count_labels(), ub_packed_rrset_key::entry, packed_rrset_key::flags, LDNS_RR_TYPE_RRSIG, PACKED_RRSET_FIXEDTTL, RETVAL_OK, RETVAL_TRUNC, ub_packed_rrset_key::rk, packed_rrset_data::rr_data, packed_rrset_data::rr_len, packed_rrset_data::rr_ttl, rrset_belongs_in_reply(), packed_rrset_key::rrset_class, packed_rrset_data::rrsig_count, SERVE_EXPIRED, SERVE_EXPIRED_REPLY_TTL, SERVE_ORIGINAL_TTL, sldns_buffer_position(), sldns_buffer_remaining(), sldns_buffer_write(), sldns_buffer_write_u16(), sldns_buffer_write_u32(), packed_rrset_data::ttl_add, packed_rrset_key::type, and type_rdata_compressable().

Referenced by insert_section().

## ◆ reply_info_encode()

int reply_info_encode | ( | struct query_info * | qinfo,
|  | struct reply_info * | rep,
|  | uint16_t | id,
|  | uint16_t | flags,
|  | struct sldns_buffer * | buffer,
|  | time_t | timenow,
|  | struct regional * | region,
|  | uint16_t | udpsize,
|  | int | dnssec,
|  | int | minimise
| ) |  |

Regenerate the wireformat from the stored msg reply.

If the buffer is too small then the message is truncated at a whole rrset and the TC bit set, or whole rrsets are left out of the additional and the TC bit is not set.

Parameters

  qinfo | query info to store.
  rep | reply to store.
  id | id value to store, network order.
  flags | flags value to store, host order.
  buffer | buffer to store the packet into.
  timenow | time now, to adjust ttl values.
  region | to store temporary data in.
  udpsize | size of the answer, 512, from EDNS, or 64k for TCP.
  dnssec | if 0 DNSSEC records are omitted from the answer.
  minimise | if true, the answer is a minimal response, with authority and additional removed if possible.

Returns
  : nonzero is success, or 0 on error: malloc failure (no log_err has been done).

References reply_info::an_numrrsets, reply_info::ar_numrrsets, BIT_AA, reply_info::flags, insert_query(), insert_section(), query_info::local_alias, reply_info::ns_numrrsets, reply_info::qdcount, query_info::qtype, RETVAL_OK, RETVAL_TRUNC, local_rrset::rrset, reply_info::rrset_count, RRSET_ROUNDROBIN, reply_info::rrsets, sldns_buffer_begin(), sldns_buffer_clear(), sldns_buffer_flip(), sldns_buffer_limit(), sldns_buffer_remaining(), sldns_buffer_set_limit(), sldns_buffer_write(), sldns_buffer_write_u16(), and sldns_buffer_write_u16_at().

Referenced by log_dns_msg(), perf_encode(), reply_info_answer_encode(), and testpkt().

## ◆ calc_edns_field_size()

uint16_t calc_edns_field_size | ( | struct edns_data * | edns | ) |

Estimate size of EDNS record in packet.

EDNS record will be no larger.

Parameters

  edns | edns data or NULL.

Returns
  octets to reserve for EDNS.

References edns_data::edns_present, edns_option::next, edns_option::opt_len, edns_data::opt_list_inplace_cb_out, and edns_data::opt_list_out.

Referenced by chaos_replystr(), error_encode(), reply_info_answer_encode(), testpkt(), worker_handle_request(), and write_q().

## ◆ attach_edns_record()

void attach_edns_record | ( | struct sldns_buffer * | pkt,
|  | struct edns_data * | edns
| ) |  |

Attach EDNS record to buffer.

Buffer has complete packet. There must be enough room left for the EDNS record.

Parameters

  pkt | packet added to.
  edns | if NULL or present=0, nothing is added to the packet.

References edns_data::edns_present, and edns_data::udp_size.

Referenced by chaos_replystr(), error_encode(), perf_encode(), qlist_parse_line(), serviced_encode(), testpkt(), worker_handle_request(), and write_q().

## ◆ reply_info_answer_encode()

int reply_info_answer_encode | ( | struct query_info * | qinf,
|  | struct reply_info * | rep,
|  | uint16_t | id,
|  | uint16_t | qflags,
|  | struct sldns_buffer * | dest,
|  | time_t | timenow,
|  | int | cached,
|  | struct regional * | region,
|  | uint16_t | udpsize,
|  | struct edns_data * | edns,
|  | int | dnssec,
|  | int | secure
| ) |  |

Generate answer from reply_info.

Parameters

  qinf | query information that provides query section in packet.
  rep | reply to fill in.
  id | id word from the query.
  qflags | flags word from the query.
  dest | buffer to put message into; will truncate if it does not fit.
  timenow | time to subtract.
  cached | set true if a cached reply (so no AA bit). set false for the first reply.
  region | where to allocate temp variables (for compression).
  udpsize | size of the answer, 512, from EDNS, or 64k for TCP.
  edns | EDNS data included in the answer, NULL for none. or if edns_present = 0, it is not included.
  dnssec | if 0 DNSSEC records are omitted from the answer.
  secure | if 1, the AD bit is set in the reply.

Returns
  : 0 on error (server failure).

References reply_info::authoritative, BIT_AA, BIT_AD, BIT_CD, BIT_QR, BIT_RD, calc_edns_field_size(), reply_info::flags, FLAGS_GET_RCODE, query_info::local_alias, log_assert, log_err(), MINIMAL_RESPONSES, reply_info_encode(), sldns_buffer_capacity(), and sldns_buffer_limit().

Referenced by answer_from_cache(), answer_norec_from_cache(), auth_answer_encode(), local_encode(), mesh_do_callback(), mesh_send_reply(), and rpz_local_encode().

## ◆ qinfo_query_encode()

void qinfo_query_encode | ( | struct sldns_buffer * | pkt,
|  | struct query_info * | qinfo
| ) |  |

Encode query packet.

Assumes the buffer is large enough.

Parameters

  pkt | where to store the packet.
  qinfo | query info.

References packed_rrset_key::dname, packed_rrset_key::dname_len, query_info::local_alias, log_assert, query_info::qclass, query_info::qname, query_info::qname_len, query_info::qtype, ub_packed_rrset_key::rk, local_rrset::rrset, sldns_buffer_clear(), sldns_buffer_flip(), sldns_buffer_remaining(), sldns_buffer_skip(), sldns_buffer_write(), and sldns_buffer_write_u16().

Referenced by qlist_parse_line(), write_q(), xfr_create_ixfr_packet(), and xfr_create_soa_probe_packet().

## ◆ error_encode()

void error_encode | ( | struct sldns_buffer * | pkt,
|  | int | r,
|  | struct query_info * | qinfo,
|  | uint16_t | qid,
|  | uint16_t | qflags,
|  | struct edns_data * | edns
| ) |  |

Encode an error.

With QR and RA set.

Parameters

  pkt | where to store the packet.
  r | RCODE value to encode.
  qinfo | if not NULL, the query is included.
  qid | query ID to set in packet. network order.
  qflags | original query flags (to copy RD and CD bits). host order.
  edns | if not NULL, this is the query edns info, and an edns reply is attached. Only attached if EDNS record fits reply.

References attach_edns_record(), BIT_CD, BIT_QR, BIT_RA, BIT_RD, edns_data::bits, calc_edns_field_size(), packed_rrset_key::dname, packed_rrset_key::dname_len, EDNS_ADVERTISED_SIZE, EDNS_ADVERTISED_VERSION, EDNS_DO, edns_data::edns_version, edns_data::ext_rcode, query_info::local_alias, query_info::qclass, query_info::qname, query_info::qname_len, query_info::qtype, ub_packed_rrset_key::rk, local_rrset::rrset, sldns_buffer_clear(), sldns_buffer_current(), sldns_buffer_flip(), sldns_buffer_limit(), sldns_buffer_skip(), sldns_buffer_write(), sldns_buffer_write_u16(), and edns_data::udp_size.

Referenced by answer_from_cache(), answer_norec_from_cache(), answer_notify(), auth_answer_encode(), auth_error_encode(), libworker_bg_done_cb(), local_encode(), local_error_encode(), mesh_new_client(), mesh_send_reply(), rpz_local_encode(), and worker_handle_request().