Example #1
0
File: pkt.c Project: idtek/knot
/* @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");
}
Example #2
0
_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;
}
Example #3
0
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);
    }
}
Example #4
0
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;
    }
}