int knot_edns_add_option(knot_opt_rr_t *opt_rr, uint16_t code, uint16_t length, const uint8_t *data) { if (opt_rr == NULL) { return KNOT_EINVAL; } if (opt_rr->option_count == opt_rr->options_max) { knot_opt_option_t *options_new = (knot_opt_option_t *)calloc( (opt_rr->options_max + KNOT_EDNS_OPTION_STEP), sizeof(knot_opt_option_t)); CHECK_ALLOC_LOG(options_new, KNOT_ENOMEM); memcpy(options_new, opt_rr->options, opt_rr->option_count * sizeof(knot_opt_option_t)); knot_opt_option_t *old_options = opt_rr->options; opt_rr->options = options_new; opt_rr->options_max += KNOT_EDNS_OPTION_STEP; free(old_options); } dbg_edns_verb("Adding option.\n"); dbg_edns_verb("Code: %u.\n", code); dbg_edns_verb("Length: %u.\n", length); dbg_edns_verb("Data: %p.\n", data); opt_rr->options[opt_rr->option_count].data = (uint8_t *)malloc(length); CHECK_ALLOC_LOG(opt_rr->options[opt_rr->option_count].data, KNOT_ENOMEM); memcpy(opt_rr->options[opt_rr->option_count].data, data, length); opt_rr->options[opt_rr->option_count].code = code; opt_rr->options[opt_rr->option_count].length = length; ++opt_rr->option_count; opt_rr->size += 4 + length; return KNOT_EOK; }
knot_opt_rr_t *knot_edns_new() { knot_opt_rr_t *opt_rr = (knot_opt_rr_t *)malloc(sizeof(knot_opt_rr_t)); CHECK_ALLOC_LOG(opt_rr, NULL); memset(opt_rr, 0, sizeof(knot_opt_rr_t)); opt_rr->size = EDNS_MIN_SIZE; opt_rr->option_count = 0; opt_rr->options_max = 0; opt_rr->ext_rcode = 0; opt_rr->flags = 0; opt_rr->version = 0; return opt_rr; }
int notify_create_response(knot_packet_t *request, uint8_t *buffer, size_t *size) { knot_packet_t *response = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); CHECK_ALLOC_LOG(response, KNOT_ENOMEM); /* Set maximum packet size. */ int rc = knot_packet_set_max_size(response, *size); if (rc == KNOT_EOK) { rc = knot_response_init_from_query(response, request, 1); } /* Aggregated result check. */ if (rc != KNOT_EOK) { dbg_notify("%s: failed to init response packet: %s", "notify_create_response", knot_strerror(rc)); knot_packet_free(&response); return KNOT_EINVAL; } // TODO: copy the SOA in Answer section uint8_t *wire = NULL; size_t wire_size = 0; rc = knot_packet_to_wire(response, &wire, &wire_size); if (rc != KNOT_EOK) { knot_packet_free(&response); return rc; } if (wire_size > *size) { knot_packet_free(&response); return KNOT_ESPACE; } memcpy(buffer, wire, wire_size); *size = wire_size; knot_packet_dump(response); knot_packet_free(&response); return KNOT_EOK; }
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; }