/* @note Packet equivalence test, 5 checks. */ static void packet_match(knot_pkt_t *in, knot_pkt_t *out) { /* Check counts */ is_int(knot_wire_get_qdcount(out->wire), knot_wire_get_qdcount(in->wire), "pkt: QD match"); is_int(knot_wire_get_ancount(out->wire), knot_wire_get_ancount(in->wire), "pkt: AN match"); is_int(knot_wire_get_nscount(out->wire), knot_wire_get_nscount(in->wire), "pkt: NS match"); is_int(knot_wire_get_arcount(out->wire), knot_wire_get_arcount(in->wire), "pkt: AR match"); /* Check RRs */ int rr_matched = 0; for (unsigned i = 0; i < NAMECOUNT; ++i) { if (knot_rrset_equal(&out->rr[i], &in->rr[i], KNOT_RRSET_COMPARE_WHOLE) > 0) { ++rr_matched; } } is_int(NAMECOUNT, rr_matched, "pkt: RR content match"); }
_public_ int knot_pkt_parse_question(knot_pkt_t *pkt) { if (pkt == NULL) { return KNOT_EINVAL; } /* Check at least header size. */ if (pkt->size < KNOT_WIRE_HEADER_SIZE) { return KNOT_EMALF; } /* We have at least some DNS header. */ pkt->parsed = KNOT_WIRE_HEADER_SIZE; /* Check QD count. */ uint16_t qd = knot_wire_get_qdcount(pkt->wire); if (qd > 1) { return KNOT_EMALF; } /* No question. */ if (qd == 0) { pkt->qname_size = 0; return KNOT_EOK; } /* Process question. */ int len = knot_dname_wire_check(pkt->wire + pkt->parsed, pkt->wire + pkt->size, NULL /* No compression in QNAME. */); if (len <= 0) { return KNOT_EMALF; } /* Check QCLASS/QTYPE size. */ uint16_t question_size = len + 2 * sizeof(uint16_t); /* QCLASS + QTYPE */ if (pkt->parsed + question_size > pkt->size) { return KNOT_EMALF; } pkt->parsed += question_size; pkt->qname_size = len; return KNOT_EOK; }
void print_packet(const knot_pkt_t *packet, const net_t *net, const size_t size, const float elapsed, const time_t exec_time, const bool incoming, const style_t *style) { if (packet == NULL || style == NULL) { DBG_NULL; return; } const knot_pktsection_t *answers = knot_pkt_section(packet, KNOT_ANSWER); const knot_pktsection_t *authority = knot_pkt_section(packet, KNOT_AUTHORITY); const knot_pktsection_t *additional = knot_pkt_section(packet, KNOT_ADDITIONAL); uint16_t qdcount = knot_wire_get_qdcount(packet->wire); uint16_t ancount = knot_wire_get_ancount(packet->wire); uint16_t nscount = knot_wire_get_nscount(packet->wire); uint16_t arcount = knot_wire_get_arcount(packet->wire); // Get Extended RCODE from the packet. uint16_t rcode = knot_pkt_get_ext_rcode(packet); // Disable additionals printing if there are no other records. // OPT record may be placed anywhere within additionals! if (knot_pkt_has_edns(packet) && arcount == 1) { arcount = 0; } // Print packet information header. if (style->show_header) { print_header(packet, style, rcode); } // Print EDNS section. if (style->show_edns && knot_pkt_has_edns(packet)) { printf("\n;; EDNS PSEUDOSECTION:\n;; "); print_section_opt(packet->opt_rr, knot_wire_get_rcode(packet->wire)); } // Print DNS sections. switch (style->format) { case FORMAT_DIG: if (ancount > 0) { print_section_dig(knot_pkt_rr(answers, 0), ancount, style); } break; case FORMAT_HOST: if (ancount > 0) { print_section_host(knot_pkt_rr(answers, 0), ancount, style); } else { print_error_host(rcode, packet, style); } break; case FORMAT_NSUPDATE: if (style->show_question && qdcount > 0) { printf("\n;; ZONE SECTION:\n;; "); print_section_question(knot_pkt_qname(packet), knot_pkt_qclass(packet), knot_pkt_qtype(packet), style); } if (style->show_answer && ancount > 0) { printf("\n;; PREREQUISITE SECTION:\n"); print_section_full(knot_pkt_rr(answers, 0), ancount, style, true); } if (style->show_authority && nscount > 0) { printf("\n;; UPDATE SECTION:\n"); print_section_full(knot_pkt_rr(authority, 0), nscount, style, true); } if (style->show_additional && arcount > 0) { printf("\n;; ADDITIONAL DATA:\n"); print_section_full(knot_pkt_rr(additional, 0), arcount, style, true); } break; case FORMAT_FULL: if (style->show_question && qdcount > 0) { printf("\n;; QUESTION SECTION:\n;; "); print_section_question(knot_pkt_qname(packet), knot_pkt_qclass(packet), knot_pkt_qtype(packet), style); } if (style->show_answer && ancount > 0) { printf("\n;; ANSWER SECTION:\n"); print_section_full(knot_pkt_rr(answers, 0), ancount, style, true); } if (style->show_authority && nscount > 0) { printf("\n;; AUTHORITY SECTION:\n"); print_section_full(knot_pkt_rr(authority, 0), nscount, style, true); } if (style->show_additional && arcount > 0) { printf("\n;; ADDITIONAL SECTION:\n"); print_section_full(knot_pkt_rr(additional, 0), arcount, style, true); } break; default: break; } // Print TSIG section. if (style->show_tsig && knot_pkt_has_tsig(packet)) { printf("\n;; TSIG PSEUDOSECTION:\n"); print_section_full(packet->tsig_rr, 1, style, false); } // Print packet statistics. if (style->show_footer) { printf("\n"); print_footer(size, 0, 0, net, elapsed, exec_time, incoming); } }
static void print_header(const knot_pkt_t *packet, const style_t *style, const uint16_t ext_rcode) { char flags[64] = ""; uint8_t opcode_id; const char *rcode_str = "Unknown"; const char *opcode_str = "Unknown"; lookup_table_t *rcode, *opcode; // Get RCODE from Header and check for Extended RCODE from OPT RR. rcode = lookup_by_id(knot_rcode_names, ext_rcode); if (rcode != NULL) { rcode_str = rcode->name; } // Get OPCODE. opcode_id = knot_wire_get_opcode(packet->wire); opcode = lookup_by_id(knot_opcode_names, opcode_id); if (opcode != NULL) { opcode_str = opcode->name; } // Get flags. size_t flags_rest = sizeof(flags); const size_t flag_len = 4; if (knot_wire_get_qr(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " qr", flags_rest); } if (knot_wire_get_aa(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " aa", flags_rest); } if (knot_wire_get_tc(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " tc", flags_rest); } if (knot_wire_get_rd(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " rd", flags_rest); } if (knot_wire_get_ra(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " ra", flags_rest); } if (knot_wire_get_z(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " z", flags_rest); } if (knot_wire_get_ad(packet->wire) != 0 && flags_rest > flag_len) { flags_rest -= strlcat(flags, " ad", flags_rest); } if (knot_wire_get_cd(packet->wire) != 0 && flags_rest > flag_len) { strlcat(flags, " cd", flags_rest); } uint16_t id = knot_wire_get_id(packet->wire); uint16_t qdcount = knot_wire_get_qdcount(packet->wire); uint16_t ancount = knot_wire_get_ancount(packet->wire); uint16_t nscount = knot_wire_get_nscount(packet->wire); uint16_t arcount = knot_wire_get_arcount(packet->wire); if (knot_pkt_has_tsig(packet)) { arcount++; } // Print formatted info. switch (style->format) { case FORMAT_NSUPDATE: printf(";; ->>HEADER<<- opcode: %s; status: %s; id: %u\n" ";; Flags:%1s; " "ZONE: %u; PREREQ: %u; UPDATE: %u; ADDITIONAL: %u\n", opcode_str, rcode_str, id, flags, qdcount, ancount, nscount, arcount); break; default: printf(";; ->>HEADER<<- opcode: %s; status: %s; id: %u\n" ";; Flags:%1s; " "QUERY: %u; ANSWER: %u; AUTHORITY: %u; ADDITIONAL: %u\n", opcode_str, rcode_str, id, flags, qdcount, ancount, nscount, arcount); break; } }