msgparse.c File Reference

Routines for message parsing a packet buffer to a descriptive structure. More...

#include "config.h"
#include "util/config_file.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/netevent.h"
#include "util/storage/lookup3.h"
#include "util/regional.h"
#include "util/rfc_1982.h"
#include "util/edns.h"
#include "util/net_help.h"
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"

Functions

static int smart_compare (sldns_buffer *pkt, uint8_t *dnow, uint8_t *dprfirst, uint8_t *dprlast)
 smart comparison of (compressed, valid) dnames from packet
 
static struct rrset_parsenew_rrset (struct msg_parse *msg, uint8_t *dname, size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type hash, uint32_t rrset_flags, sldns_pkt_section section, struct regional *region)
 Allocate new rrset in region, fill with data.
 
static int nsec_at_apex (sldns_buffer *pkt)
 See if next rrset is nsec at zone apex.
 
static uint32_t pkt_rrset_flags (sldns_buffer *pkt, uint16_t type, sldns_pkt_section sec)
 Calculate rrset flags.
 
hashvalue_type pkt_hash_rrset (sldns_buffer *pkt, uint8_t *dname, uint16_t type, uint16_t dclass, uint32_t rrset_flags)
 Calculate hash value for rrset in packet. More...
 
static hashvalue_type pkt_hash_rrset_first (sldns_buffer *pkt, uint8_t *dname)
 create partial dname hash for rrset hash
 
static hashvalue_type pkt_hash_rrset_rest (hashvalue_type dname_h, uint16_t type, uint16_t dclass, uint32_t rrset_flags)
 create a rrset hash from a partial dname hash
 
static int rrset_parse_equals (struct rrset_parse *p, sldns_buffer *pkt, hashvalue_type h, uint32_t rrset_flags, uint8_t *dname, size_t dnamelen, uint16_t type, uint16_t dclass)
 compare rrset_parse with data
 
struct rrset_parsemsgparse_hashtable_lookup (struct msg_parse *msg, sldns_buffer *pkt, hashvalue_type h, uint32_t rrset_flags, uint8_t *dname, size_t dnamelen, uint16_t type, uint16_t dclass)
 Lookup in msg hashtable to find a rrset. More...
 
static int pkt_rrsig_covered (sldns_buffer *pkt, uint8_t *here, uint16_t *type)
 return type networkformat that rrsig in packet covers
 
static int pkt_rrsig_covered_equals (sldns_buffer *pkt, uint8_t *here, uint16_t type)
 true if covered type equals prevtype
 
void msgparse_bucket_remove (struct msg_parse *msg, struct rrset_parse *rrset)
 Remove rrset from hash table. More...
 
static void change_section (struct msg_parse *msg, struct rrset_parse *rrset, sldns_pkt_section section)
 change section of rrset from previous to current section
 
static int rrset_has_sigover (sldns_buffer *pkt, struct rrset_parse *rrset, uint16_t type, int *hasother)
 see if rrset of type RRSIG contains sig over given type
 
static int moveover_rrsigs (sldns_buffer *pkt, struct regional *region, struct rrset_parse *sigset, struct rrset_parse *dataset, int duplicate)
 move rrsigs from sigset to dataset
 
static struct rrset_parsechange_rrsig_rrset (struct rrset_parse *sigset, struct msg_parse *msg, sldns_buffer *pkt, uint16_t datatype, uint32_t rrset_flags, int hasother, sldns_pkt_section section, struct regional *region)
 change an rrsig rrset for use as data rrset
 
static int find_rrset (struct msg_parse *msg, sldns_buffer *pkt, uint8_t *dname, size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type *hash, uint32_t *rrset_flags, uint8_t **prev_dname_first, uint8_t **prev_dname_last, size_t *prev_dnamelen, uint16_t *prev_type, uint16_t *prev_dclass, struct rrset_parse **rrset_prev, sldns_pkt_section section, struct regional *region)
 Find rrset. More...
 
static int parse_query_section (sldns_buffer *pkt, struct msg_parse *msg)
 Parse query section. More...
 
size_t get_rdf_size (sldns_rdf_type rdf)
 Obtain size in the packet of an rr type, that is before dname type. More...
 
static int calc_size (sldns_buffer *pkt, uint16_t type, struct rr_parse *rr)
 calculate the size of one rr
 
static int skip_ttl_rdata (sldns_buffer *pkt)
 skip rr ttl and rdata
 
static int sig_is_double (sldns_buffer *pkt, struct rrset_parse *rrset, uint8_t *ttldata)
 see if RRSIG is a duplicate of another
 
static int add_rr_to_rrset (struct rrset_parse *rrset, sldns_buffer *pkt, struct msg_parse *msg, struct regional *region, sldns_pkt_section section, uint16_t type)
 Add rr (from packet here) to rrset, skips rr.
 
static int parse_section (sldns_buffer *pkt, struct msg_parse *msg, struct regional *region, sldns_pkt_section section, uint16_t num_rrs, size_t *num_rrsets)
 Parse packet RR section, for answer, authority and additional sections. More...
 
int parse_packet (sldns_buffer *pkt, struct msg_parse *msg, struct regional *region)
 Parse the packet. More...
 
static int parse_edns_options_from_query (uint8_t *rdata_ptr, size_t rdata_len, struct edns_data *edns, struct config_file *cfg, struct comm_point *c, struct comm_reply *repinfo, uint32_t now, struct regional *region)
 parse EDNS options from EDNS wireformat rdata
 
int parse_extract_edns_from_response_msg (struct msg_parse *msg, struct edns_data *edns, struct regional *region)
 After parsing the packet, extract EDNS data from packet. More...
 
static int skip_pkt_rr (sldns_buffer *pkt)
 skip RR in packet
 
int skip_pkt_rrs (sldns_buffer *pkt, int num)
 skip RRs from packet More...
 
int parse_edns_from_query_pkt (sldns_buffer *pkt, struct edns_data *edns, struct config_file *cfg, struct comm_point *c, struct comm_reply *repinfo, time_t now, struct regional *region)
 If EDNS data follows a query section, extract it and initialize edns struct. More...
 
void log_edns_opt_list (enum verbosity_value level, const char *info_str, struct edns_option *list)
 Log the edns options in the edns option list. More...
 
int msgparse_rrset_remove_rr (const char *str, sldns_buffer *pkt, struct rrset_parse *rrset, struct rr_parse *prev, struct rr_parse *rr, struct sockaddr_storage *addr, socklen_t addrlen)
 remove RR from msgparse RRset, return true if rrset is entirely bad More...
 

Detailed Description

Routines for message parsing a packet buffer to a descriptive structure.

Function Documentation

◆ pkt_hash_rrset()

hashvalue_type pkt_hash_rrset ( struct sldns_buffer pkt,
uint8_t *  dname,
uint16_t  type,
uint16_t  dclass,
uint32_t  rrset_flags 
)

Calculate hash value for rrset in packet.

Parameters
pktthe packet.
dnamepointer to uncompressed dname, or compressed dname in packet.
typerrset type in host order.
dclassrrset class in network order.
rrset_flagsrrset flags (same as packed_rrset flags).
Returns
hash value

References rrset_parse::dname, dname_pkt_hash(), hashlittle(), and rrset_parse::type.

Referenced by change_rrsig_rrset(), mark_additional_rrset(), and synth_cname_rrset().

◆ msgparse_hashtable_lookup()

struct rrset_parse* msgparse_hashtable_lookup ( struct msg_parse msg,
struct sldns_buffer pkt,
hashvalue_type  h,
uint32_t  rrset_flags,
uint8_t *  dname,
size_t  dnamelen,
uint16_t  type,
uint16_t  dclass 
)

Lookup in msg hashtable to find a rrset.

Parameters
msgwith the hashtable.
pktpacket for compressed names.
hhash value
rrset_flagsflags of rrset sought for.
dnamename of rrset sought for.
dnamelenlen of dname.
typerrset type, host order.
dclassrrset class, network order.
Returns
NULL or the rrset_parse if found.

References rrset_parse::dname, msg_parse::hashtable, PARSE_TABLE_SIZE, rrset_parse::rrset_bucket_next, rrset_parse_equals(), and rrset_parse::type.

Referenced by find_rrset(), and mark_additional_rrset().

◆ msgparse_bucket_remove()

void msgparse_bucket_remove ( struct msg_parse msg,
struct rrset_parse rrset 
)

Remove rrset from hash table.

Parameters
msgwith hashtable.
rrsetwith hash value and id info.

References rrset_parse::hash, msg_parse::hashtable, PARSE_TABLE_SIZE, and rrset_parse::rrset_bucket_next.

◆ find_rrset()

static int find_rrset ( struct msg_parse msg,
sldns_buffer pkt,
uint8_t *  dname,
size_t  dnamelen,
uint16_t  type,
uint16_t  dclass,
hashvalue_type hash,
uint32_t *  rrset_flags,
uint8_t **  prev_dname_first,
uint8_t **  prev_dname_last,
size_t *  prev_dnamelen,
uint16_t *  prev_type,
uint16_t *  prev_dclass,
struct rrset_parse **  rrset_prev,
sldns_pkt_section  section,
struct regional region 
)
static

Find rrset.

If equal to previous it is fast. hash if not so.

Parameters
msgthe message with hash table.
pktthe packet in wireformat (needed for compression ptrs).
dnamepointer to start of dname (compressed) in packet.
dnamelenuncompressed wirefmt length of dname.
typetype of current rr.
dclassclass of current rr.
hashhash value is returned if the rrset could not be found.
rrset_flagsis returned if the rrset could not be found.
prev_dname_firstdname of last seen RR. First seen dname.
prev_dname_lastdname of last seen RR. Last seen dname.
prev_dnamelendname len of last seen RR.
prev_typetype of last seen RR.
prev_dclassclass of last seen RR.
rrset_prevlast seen RRset.
sectionthe current section in the packet.
regionused to allocate temporary parsing data.
Returns
0 on out of memory.

References rrset_parse::dname, rrset_parse::hash, LDNS_RR_TYPE_RRSIG, msgparse_hashtable_lookup(), pkt_hash_rrset_first(), pkt_hash_rrset_rest(), pkt_rrset_flags(), pkt_rrsig_covered(), pkt_rrsig_covered_equals(), rrset_parse::section, sldns_buffer_current(), smart_compare(), and rrset_parse::type.

◆ parse_query_section()

static int parse_query_section ( sldns_buffer pkt,
struct msg_parse msg 
)
static

Parse query section.

Parameters
pktpacket, position at call must be at start of query section. at end position is after query section.
msgstore results here.
Returns
: 0 if OK, or rcode on error.

References msg_parse::qdcount.

◆ get_rdf_size()

size_t get_rdf_size ( sldns_rdf_type  rdf)

Obtain size in the packet of an rr type, that is before dname type.

Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types.

Parameters
rdfthe rdf type from the descriptor.
Returns
: size in octets. 0 on failure.

References LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_AAAA, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_CLASS, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT32, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TSIGTIME, LDNS_RDF_TYPE_TYPE, and log_assert.

Referenced by analyze_rdata(), calc_size(), canonical_compare_byfield(), compress_rdata(), and decompress_rr_into_buffer().

◆ parse_section()

static int parse_section ( sldns_buffer pkt,
struct msg_parse msg,
struct regional region,
sldns_pkt_section  section,
uint16_t  num_rrs,
size_t *  num_rrsets 
)
static

Parse packet RR section, for answer, authority and additional sections.

Parameters
pktpacket, position at call must be at start of section. at end position is after section.
msgstore results here.
regionhow to alloc results.
sectionsection enum.
num_rrshow many rrs are in the section.
num_rrsetsreturns number of rrsets in the section.
Returns
: 0 if OK, or rcode on error.

References sldns_buffer_remaining().

◆ parse_packet()

int parse_packet ( struct sldns_buffer pkt,
struct msg_parse msg,
struct regional region 
)

Parse the packet.

Parameters
pktpacket, position at call must be at start of packet. at end position is after packet.
msgwhere to store results.
regionhow to alloc results.
Returns
: 0 if OK, or rcode on error.

References sldns_buffer_remaining().

Referenced by createResponse(), and parse_reply_in_temp_region().

◆ parse_extract_edns_from_response_msg()

int parse_extract_edns_from_response_msg ( struct msg_parse msg,
struct edns_data edns,
struct regional region 
)

After parsing the packet, extract EDNS data from packet.

If not present this is noted in the data structure. If a parse error happens, an error code is returned.

Quirks: o ignores OPT rdata. o ignores OPT owner name. o ignores extra OPT records, except the last one in the packet.

Parameters
msgparsed message structure. Modified on exit, if EDNS was present it is removed from the additional section.
ednsthe edns data is stored here. Does not have to be initialised.
regionregion to alloc results in (edns option contents)
Returns
: 0 on success. or an RCODE on an error. RCODE formerr if OPT in wrong section, and so on.

References LDNS_RR_TYPE_OPT, msg_parse::rrset_first, and rrset_parse::type.

◆ skip_pkt_rrs()

int skip_pkt_rrs ( sldns_buffer pkt,
int  num 
)

skip RRs from packet

Skip RRs from packet.

References skip_pkt_rr().

◆ parse_edns_from_query_pkt()

int parse_edns_from_query_pkt ( struct sldns_buffer pkt,
struct edns_data edns,
struct config_file cfg,
struct comm_point c,
struct comm_reply repinfo,
time_t  now,
struct regional region 
)

If EDNS data follows a query section, extract it and initialize edns struct.

Parameters
pktthe packet. position at start must be right after the query section. At end, right after EDNS data or no movement if failed.
ednsthe edns data allocated by the caller. Does not have to be initialised.
cfgthe configuration (with nsid value etc.)
ccommpoint to determine transport (if needed)
repinfocommreply to determine the client address
nowcurrent time
regionregion to alloc results in (edns option contents)
Returns
: 0 on success, or an RCODE on error. RCODE formerr if OPT is badly formatted and so on.

References log_assert.

◆ log_edns_opt_list()

void log_edns_opt_list ( enum verbosity_value  level,
const char *  info_str,
struct edns_option list 
)

Log the edns options in the edns option list.

Parameters
levelthe verbosity level.
info_strthe informational string to be printed before the options.
listthe edns option list.

References verbosity.

◆ msgparse_rrset_remove_rr()

int msgparse_rrset_remove_rr ( const char *  str,
sldns_buffer pkt,
struct rrset_parse rrset,
struct rr_parse prev,
struct rr_parse rr,
struct sockaddr_storage *  addr,
socklen_t  addrlen 
)

remove RR from msgparse RRset, return true if rrset is entirely bad

Remove RR from msgparse RRset.