/*! \brief Check constraints (position, uniqueness, validity) for special types * (TSIG, OPT). */ static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_size, unsigned flags) { /* Check RR constraints. */ switch(rr->type) { case KNOT_RRTYPE_TSIG: CHECK_AR_CONSTRAINTS(pkt, rr, tsig_rr, knot_tsig_rdata_is_ok); /* Strip TSIG RR from wireformat and decrease ARCOUNT. */ if (!(flags & KNOT_PF_KEEPWIRE)) { pkt->parsed -= rr_size; pkt->size -= rr_size; knot_wire_set_id(pkt->wire, knot_tsig_rdata_orig_id(rr)); knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1); } break; case KNOT_RRTYPE_OPT: CHECK_AR_CONSTRAINTS(pkt, rr, opt_rr, knot_edns_check_record); break; default: break; } return KNOT_EOK; }
knot_pkt_t* create_empty_packet(const size_t max_size) { // Create packet skeleton. knot_pkt_t *packet = knot_pkt_new(NULL, max_size, NULL); if (packet == NULL) { DBG_NULL; return NULL; } // Set random sequence id. knot_wire_set_id(packet->wire, dnssec_random_uint16_t()); return packet; }
/*! \brief Create zone query packet. */ static knot_pkt_t *zone_query(const zone_t *zone, uint16_t pkt_type, knot_mm_t *mm) { /* Determine query type and opcode. */ uint16_t query_type = KNOT_RRTYPE_SOA; uint16_t opcode = KNOT_OPCODE_QUERY; switch(pkt_type) { case KNOT_QUERY_AXFR: query_type = KNOT_RRTYPE_AXFR; break; case KNOT_QUERY_IXFR: query_type = KNOT_RRTYPE_IXFR; break; case KNOT_QUERY_NOTIFY: opcode = KNOT_OPCODE_NOTIFY; break; } knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, mm); if (pkt == NULL) { return NULL; } knot_wire_set_id(pkt->wire, dnssec_random_uint16_t()); knot_wire_set_opcode(pkt->wire, opcode); if (pkt_type == KNOT_QUERY_NOTIFY) { knot_wire_set_aa(pkt->wire); } knot_pkt_put_question(pkt, zone->name, KNOT_CLASS_IN, query_type); /* Put current SOA (optional). */ zone_contents_t *contents = zone->contents; if (pkt_type == KNOT_QUERY_IXFR) { /* RFC1995, SOA in AUTHORITY. */ knot_pkt_begin(pkt, KNOT_AUTHORITY); knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA); knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0); } else if (pkt_type == KNOT_QUERY_NOTIFY) { /* RFC1996, SOA in ANSWER. */ knot_pkt_begin(pkt, KNOT_ANSWER); knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA); knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0); } return pkt; }
static int notify_request(const knot_rrset_t *rrset, uint8_t *buffer, size_t *size) { knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); CHECK_ALLOC_LOG(pkt, KNOT_ENOMEM); /*! \todo Get rid of the numeric constant. */ int rc = knot_packet_set_max_size(pkt, 512); if (rc != KNOT_EOK) { knot_packet_free(&pkt); return KNOT_ERROR; } rc = knot_query_init(pkt); if (rc != KNOT_EOK) { knot_packet_free(&pkt); return KNOT_ERROR; } knot_question_t question; // this is ugly!! question.qname = rrset->owner; question.qtype = rrset->type; question.qclass = rrset->rclass; rc = knot_query_set_question(pkt, &question); if (rc != KNOT_EOK) { knot_packet_free(&pkt); return KNOT_ERROR; } /* Set random query ID. */ knot_packet_set_random_id(pkt); knot_wire_set_id(pkt->wireformat, pkt->header.id); /*! \todo add the SOA RR to the Answer section as a hint */ /*! \todo this should not use response API!! */ // rc = knot_response_add_rrset_answer(pkt, rrset, 0, 0, 0); // if (rc != KNOT_EOK) { // knot_packet_free(&pkt); // return rc; // } /*! \todo this should not use response API!! */ knot_response_set_aa(pkt); knot_query_set_opcode(pkt, KNOT_OPCODE_NOTIFY); /*! \todo OPT RR ?? */ uint8_t *wire = NULL; size_t wire_size = 0; rc = knot_packet_to_wire(pkt, &wire, &wire_size); if (rc != KNOT_EOK) { knot_packet_free(&pkt); return KNOT_ERROR; } if (wire_size > *size) { knot_packet_free(&pkt); return KNOT_ESPACE; } memcpy(buffer, wire, wire_size); *size = wire_size; knot_packet_dump(pkt); knot_packet_free(&pkt); return KNOT_EOK; }