Functions
msgparse.c File Reference

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

#include "config.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/storage/lookup3.h"
#include "util/regional.h"
#include "ldns/rrdef.h"
#include "ldns/sbuffer.h"
#include "ldns/parseutil.h"
#include "ldns/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_t 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_t 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_t pkt_hash_rrset_first (sldns_buffer *pkt, uint8_t *dname)
 create partial dname hash for rrset hash
 
static hashvalue_t pkt_hash_rrset_rest (hashvalue_t 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_t 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_t 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_t *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...
 
int parse_extract_edns (struct msg_parse *msg, struct edns_data *edns)
 After parsing the packet, extract EDNS data from packet. More...
 
int parse_edns_from_pkt (sldns_buffer *pkt, struct edns_data *edns)
 If EDNS data follows a query section, extract it and initialize edns struct. More...
 

Detailed Description

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

Function Documentation

hashvalue_t 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
pkt,:the packet.
dname,:pointer to uncompressed dname, or compressed dname in packet.
type,:rrset type in host order.
dclass,:rrset class in network order.
rrset_flags,:rrset flags (same as packed_rrset flags).
Returns
hash value

References dname_pkt_hash().

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

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

Lookup in msg hashtable to find a rrset.

Parameters
msg,:with the hashtable.
pkt,:packet for compressed names.
h,:hash value
rrset_flags,:flags of rrset sought for.
dname,:name of rrset sought for.
dnamelen,:len of dname.
type,:rrset type, host order.
dclass,:rrset class, network order.
Returns
NULL or the rrset_parse if found.

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

Referenced by find_rrset(), and mark_additional_rrset().

void msgparse_bucket_remove ( struct msg_parse msg,
struct rrset_parse rrset 
)

Remove rrset from hash table.

Parameters
msg,:with hashtable.
rrset,:with hash value and id info.

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

Referenced by change_rrsig_rrset(), and remove_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_t 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
msg,:the message with hash table.
pkt,:the packet in wireformat (needed for compression ptrs).
dname,:pointer to start of dname (compressed) in packet.
dnamelen,:uncompressed wirefmt length of dname.
type,:type of current rr.
dclass,:class of current rr.
hash,:hash value is returned if the rrset could not be found.
rrset_flags,:is returned if the rrset could not be found.
prev_dname_first,:dname of last seen RR. First seen dname.
prev_dname_last,:dname of last seen RR. Last seen dname.
prev_dnamelen,:dname len of last seen RR.
prev_type,:type of last seen RR.
prev_dclass,:class of last seen RR.
rrset_prev,:last seen RRset.
section,:the current section in the packet.
region,:used to allocate temporary parsing data.
Returns
0 on out of memory.

References change_rrsig_rrset(), rrset_parse::dname, LDNS_RR_TYPE_RRSIG, LDNS_RR_TYPE_SOA, msgparse_hashtable_lookup(), PACKED_RRSET_NSEC_AT_APEX, PACKED_RRSET_SOA_NEG, pkt_hash_rrset_first(), pkt_hash_rrset_rest(), pkt_rrset_flags(), pkt_rrsig_covered(), pkt_rrsig_covered_equals(), rrset_has_sigover(), sldns_buffer_current(), smart_compare(), and rrset_parse::type.

Referenced by parse_section().

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

Parse query section.

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

References log_assert, pkt_dname_len(), msg_parse::qclass, msg_parse::qdcount, msg_parse::qname, msg_parse::qname_len, msg_parse::qtype, sldns_buffer_current(), sldns_buffer_read_u16(), and sldns_buffer_remaining().

Referenced by parse_packet().

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
rdf,:the 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 rdata_copy().

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
pkt,:packet, position at call must be at start of section. at end position is after section.
msg,:store results here.
region,:how to alloc results.
section,:section enum.
num_rrs,:how many rrs are in the section.
num_rrsets,:returns number of rrsets in the section.
Returns
: 0 if OK, or rcode on error.

References sldns_struct_rr_descriptor::_name, add_rr_to_rrset(), rrset_parse::dname, dname_print(), find_rrset(), LDNS_RR_TYPE_RRSIG, new_rrset(), pkt_dname_len(), pkt_rrsig_covered(), sldns_buffer_current(), sldns_buffer_read(), sldns_buffer_read_u16(), sldns_buffer_remaining(), sldns_lookup_by_id(), sldns_rr_classes, sldns_rr_descript(), and rrset_parse::type.

Referenced by parse_packet().

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

Parse the packet.

Parameters
pkt,:packet, position at call must be at start of packet. at end position is after packet.
msg,:where to store results.
region,:how to alloc results.
Returns
: 0 if OK, or rcode on error.

References msg_parse::an_rrsets, msg_parse::ancount, msg_parse::ar_rrsets, msg_parse::arcount, msg_parse::flags, msg_parse::id, msg_parse::ns_rrsets, msg_parse::nscount, parse_query_section(), parse_section(), msg_parse::qdcount, msg_parse::rrset_count, sldns_buffer_read(), sldns_buffer_read_u16(), and sldns_buffer_remaining().

Referenced by createResponse(), parse_reply(), process_response(), and reply_info_parse().

int parse_extract_edns ( struct msg_parse msg,
struct edns_data edns 
)

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
msg,:parsed message structure. Modified on exit, if EDNS was present it is removed from the additional section.
edns,:the edns data is stored here. Does not have to be initialised.
Returns
: 0 on success. or an RCODE on an error. RCODE formerr if OPT in wrong section, and so on.

References msg_parse::ar_rrsets, msg_parse::arcount, edns_data::bits, rrset_parse::dname, rrset_parse::dname_len, edns_data::edns_present, edns_data::edns_version, edns_data::ext_rcode, LDNS_RR_TYPE_OPT, log_assert, rrset_parse::rr_count, rrset_parse::rr_first, rrset_parse::rr_last, rrset_parse::rrset_all_next, rrset_parse::rrset_class, msg_parse::rrset_count, msg_parse::rrset_first, msg_parse::rrset_last, rrset_parse::section, rr_parse::ttl_data, rrset_parse::type, and edns_data::udp_size.

Referenced by createResponse(), process_response(), and reply_info_parse().

int parse_edns_from_pkt ( struct sldns_buffer pkt,
struct edns_data edns 
)

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

Parameters
pkt,:the packet. position at start must be right after the query section. At end, right after EDNS data or no movement if failed.
edns,:the edns data allocated by the caller. Does not have to be initialised.
Returns
: 0 on success, or an RCODE on error. RCODE formerr if OPT is badly formatted and so on.

References edns_data::bits, edns_data::edns_present, edns_data::edns_version, edns_data::ext_rcode, LDNS_RR_TYPE_OPT, log_assert, pkt_dname_len(), sldns_buffer_begin(), sldns_buffer_read_u16(), sldns_buffer_read_u8(), sldns_buffer_remaining(), and edns_data::udp_size.

Referenced by worker_handle_request().