unbound: util/data/msgparse.c File Reference

unbound 0.1

Functions
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 "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_parse * | new_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.
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_parse * | msgparse_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.
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.
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_parse * | change_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.
static int | parse_query_section (sldns_buffer *pkt, struct msg_parse *msg)
| Parse query section.
size_t | get_rdf_size (sldns_rdf_type rdf)
| Obtain size in the packet of an rr type, that is before dname type.
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.
int | parse_packet (sldns_buffer *pkt, struct msg_parse *msg, struct regional *region)
| Parse the packet.
static int | edns_opt_list_append_keepalive (struct edns_option **list, int msec, struct regional *region)
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 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.
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
int | parse_edns_from_query_pkt (sldns_buffer *pkt, struct edns_data *edns, struct config_file *cfg, struct comm_point *c, struct regional *region)
| If EDNS data follows a query section, extract it and initialize edns struct.
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.

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

  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 rrset_parse::dname, dname_pkt_hash(), 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

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

  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().

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

  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, rrset_parse::hash, 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(), rrset_parse::section, sldns_buffer_current(), smart_compare(), and rrset_parse::type.

Referenced by parse_section().

## ◆ parse_query_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().

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

  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(), decompress_rr_into_buffer(), and rdata_copy().

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

  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(), rrset_parse::hash, LDNS_RR_TYPE_RRSIG, new_rrset(), pkt_dname_len(), pkt_rrsig_covered(), rrset_parse::section, sldns_buffer_current(), sldns_buffer_read(), sldns_buffer_read_u16(), sldns_buffer_remaining(), sldns_rr_classes, sldns_rr_descript(), and rrset_parse::type.

Referenced by parse_packet().

## ◆ 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_in_temp_region(), process_response(), and reply_info_parse().

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

  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.
  region | region 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 msg_parse::ar_rrsets, msg_parse::arcount, edns_data::bits, rrset_parse::dname, rrset_parse::dname_len, edns_opt_list_append(), edns_data::edns_present, edns_data::edns_version, edns_data::ext_rcode, LDNS_RR_TYPE_OPT, log_assert, log_err(), edns_data::opt_list_in, edns_data::opt_list_inplace_cb_out, edns_data::opt_list_out, edns_data::padding_block_size, 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::size, rr_parse::ttl_data, rrset_parse::type, and edns_data::udp_size.

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

## ◆ skip_pkt_rrs()

int skip_pkt_rrs | ( | sldns_buffer * | pkt,
|  | int | num
| ) |  |

skip RRs from packet

Skip RRs from packet.

References skip_pkt_rr().

Referenced by parse_edns_from_query_pkt().

## ◆ 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 regional * | region
| ) |  |

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.
  cfg | the configuration (with nsid value etc.)
  c | commpoint to determine transport (if needed)
  region | region 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 edns_data::bits, edns_data::edns_present, edns_data::edns_version, edns_data::ext_rcode, LDNS_RR_TYPE_OPT, log_assert, edns_data::opt_list_in, edns_data::opt_list_inplace_cb_out, edns_data::opt_list_out, edns_data::padding_block_size, parse_edns_options_from_query(), pkt_dname_len(), skip_pkt_rrs(), sldns_buffer_begin(), sldns_buffer_current(), sldns_buffer_read_u16(), sldns_buffer_read_u8(), sldns_buffer_remaining(), and edns_data::udp_size.

Referenced by worker_handle_request().

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

  level | the verbosity level.
  info_str | the informational string to be printed before the options.
  list | the edns option list.

References edns_option::next, edns_option::opt_code, edns_option::opt_data, edns_option::opt_len, sldns_wire2str_edns_option_print(), verbose(), and verbosity.