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"

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

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. More...
 
static struct compress_tree_nodecompress_tree_lookup (struct compress_tree_node **tree, uint8_t *dname, int labs, struct compress_tree_node ***insertpt)
 Lookup a domain name in compression tree. More...
 
static struct compress_tree_nodecompress_tree_newnode (uint8_t *dname, int labs, size_t offset, struct regional *region)
 Create node for domain name compression tree. More...
 
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. More...
 
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_descriptortype_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)
 
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)
 Regenerate the wireformat from the stored msg reply. More...
 
uint16_t calc_edns_field_size (struct edns_data *edns)
 Estimate size of EDNS record in packet. More...
 
void attach_edns_record (sldns_buffer *pkt, struct edns_data *edns)
 Attach EDNS record to buffer. More...
 
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. More...
 
void qinfo_query_encode (sldns_buffer *pkt, struct query_info *qinfo)
 Encode query packet. More...
 
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. More...
 

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.

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

◆ RETVAL_OK

#define RETVAL_OK   0

return code that means all is peachy keen.

Equal to DNS rcode NOERROR

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

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
treeroot of tree.
dnamepointer to uncompressed dname.
labsnumber of labels in domain name.
matchclosest or exact match. guaranteed to be smaller or equal to the sought dname. can be null if the tree is empty.
matchlabelsnumber of labels that match with closest match. can be zero is there is no match.
insertptinsert 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, 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
treeroot of tree (not the node with '.').
dnamepointer to uncompressed dname.
labsnumber of labels in domain name.
insertptinsert location for dname, if not found.
Returns
: 0 if not found or compress treenode with best compression.

References compress_tree_search(), 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
dnamepointer to uncompressed dname (stored in tree).
labsnumber of labels in dname.
offsetoffset into packet for dname.
regionhow 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
dnamepointer to uncompressed dname (stored in tree).
labsnumber of labels in dname.
offsetoffset into packet for dname.
regionhow to allocate memory for new node.
closestmatch 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.
insertptwhere to insert the dname in tree.
Returns
: 0 on memory error.

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

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

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

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
qinfoquery info to store.
repreply to store.
idid value to store, network order.
flagsflags value to store, host order.
bufferbuffer to store the packet into.
timenowtime now, to adjust ttl values.
regionto store temporary data in.
udpsizesize of the answer, 512, from EDNS, or 64k for TCP.
dnssecif 0 DNSSEC records are omitted from the answer.
Returns
: nonzero is success, or 0 on error: malloc failure (no log_err has been done).

References sldns_buffer_clear(), sldns_buffer_limit(), sldns_buffer_remaining(), and sldns_buffer_set_limit().

Referenced by log_dns_msg().

◆ 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
ednsedns data or NULL.
Returns
octets to reserve for EDNS.

References edns_data::edns_present, edns_option::next, edns_option::opt_len, and edns_data::opt_list.

Referenced by error_encode(), and write_q().

◆ attach_edns_record()

void attach_edns_record ( struct sldns_buffer pkt,
struct edns_data edns 
)

◆ 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
qinfquery information that provides query section in packet.
repreply to fill in.
idid word from the query.
qflagsflags word from the query.
destbuffer to put message into; will truncate if it does not fit.
timenowtime to subtract.
cachedset true if a cached reply (so no AA bit). set false for the first reply.
regionwhere to allocate temp variables (for compression).
udpsizesize of the answer, 512, from EDNS, or 64k for TCP.
ednsEDNS data included in the answer, NULL for none. or if edns_present = 0, it is not included.
dnssecif 0 DNSSEC records are omitted from the answer.
secureif 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_RD, reply_info::flags, FLAGS_GET_RCODE, and query_info::local_alias.

Referenced by local_encode().

◆ qinfo_query_encode()

void qinfo_query_encode ( struct sldns_buffer pkt,
struct query_info qinfo 
)

◆ 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
pktwhere to store the packet.
rRCODE value to encode.
qinfoif not NULL, the query is included.
qidquery ID to set in packet. network order.
qflagsoriginal query flags (to copy RD and CD bits). host order.
ednsif 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 libworker_bg_done_cb(), local_encode(), and local_error_encode().