00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <ldns/config.h>
00018
00019 #include <ldns/ldns.h>
00020
00021
00022 #include <strings.h>
00023 #include <limits.h>
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 ldns_status
00056 ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos)
00057 {
00058 uint8_t label_size;
00059 uint16_t pointer_target;
00060 uint8_t pointer_target_buf[2];
00061 size_t dname_pos = 0;
00062 size_t uncompressed_length = 0;
00063 size_t compression_pos = 0;
00064 uint8_t tmp_dname[LDNS_MAX_DOMAINLEN];
00065 unsigned int pointer_count = 0;
00066
00067 if (pos == NULL) {
00068 return LDNS_STATUS_WIRE_RDATA_ERR;
00069 }
00070 if (*pos >= max) {
00071 return LDNS_STATUS_PACKET_OVERFLOW;
00072 }
00073 label_size = wire[*pos];
00074 while (label_size > 0) {
00075
00076 while (label_size >= 192) {
00077 if (compression_pos == 0) {
00078 compression_pos = *pos + 2;
00079 }
00080
00081 pointer_count++;
00082
00083
00084 if (*pos + 2 > max) {
00085 return LDNS_STATUS_PACKET_OVERFLOW;
00086 }
00087 pointer_target_buf[0] = wire[*pos] & 63;
00088 pointer_target_buf[1] = wire[*pos + 1];
00089 pointer_target = ldns_read_uint16(pointer_target_buf);
00090
00091 if (pointer_target == 0) {
00092 return LDNS_STATUS_INVALID_POINTER;
00093 } else if (pointer_target >= max) {
00094 return LDNS_STATUS_INVALID_POINTER;
00095 } else if (pointer_count > LDNS_MAX_POINTERS) {
00096 return LDNS_STATUS_INVALID_POINTER;
00097 }
00098 *pos = pointer_target;
00099 label_size = wire[*pos];
00100 }
00101 if(label_size == 0)
00102 break;
00103 if (label_size > LDNS_MAX_LABELLEN) {
00104 return LDNS_STATUS_LABEL_OVERFLOW;
00105 }
00106 if (*pos + 1 + label_size > max) {
00107 return LDNS_STATUS_LABEL_OVERFLOW;
00108 }
00109
00110
00111 if (dname_pos + 1 > LDNS_MAX_DOMAINLEN) {
00112 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00113 }
00114 tmp_dname[dname_pos] = label_size;
00115 if (label_size > 0) {
00116 dname_pos++;
00117 }
00118 *pos = *pos + 1;
00119 if (dname_pos + label_size > LDNS_MAX_DOMAINLEN) {
00120 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00121 }
00122 memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size);
00123 uncompressed_length += label_size + 1;
00124 dname_pos += label_size;
00125 *pos = *pos + label_size;
00126
00127 if (*pos < max) {
00128 label_size = wire[*pos];
00129 }
00130 }
00131
00132 if (compression_pos > 0) {
00133 *pos = compression_pos;
00134 } else {
00135 *pos = *pos + 1;
00136 }
00137
00138 if (dname_pos >= LDNS_MAX_DOMAINLEN) {
00139 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
00140 }
00141
00142 tmp_dname[dname_pos] = 0;
00143 dname_pos++;
00144
00145 *dname = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
00146 (uint16_t) dname_pos, tmp_dname);
00147 if (!*dname) {
00148 return LDNS_STATUS_MEM_ERR;
00149 }
00150 return LDNS_STATUS_OK;
00151 }
00152
00153
00154 #define LDNS_STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }}
00155 #define LDNS_STATUS_CHECK_GOTO(st, label) {if (st != LDNS_STATUS_OK) { goto label; }}
00156
00157 ldns_status
00158 ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
00159 {
00160 size_t end;
00161 size_t cur_rdf_length;
00162 uint8_t rdf_index;
00163 uint8_t *data;
00164 uint16_t rd_length;
00165 ldns_rdf *cur_rdf = NULL;
00166 ldns_rdf_type cur_rdf_type;
00167 const ldns_rr_descriptor *descriptor;
00168 ldns_status status;
00169
00170 assert(rr != NULL);
00171
00172 descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
00173
00174 if (*pos + 2 > max) {
00175 return LDNS_STATUS_PACKET_OVERFLOW;
00176 }
00177
00178 rd_length = ldns_read_uint16(&wire[*pos]);
00179 *pos = *pos + 2;
00180
00181 if (*pos + rd_length > max) {
00182 return LDNS_STATUS_PACKET_OVERFLOW;
00183 }
00184
00185 end = *pos + (size_t) rd_length;
00186
00187 rdf_index = 0;
00188 while (*pos < end &&
00189 rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
00190
00191 cur_rdf_length = 0;
00192
00193 cur_rdf_type = ldns_rr_descriptor_field_type(
00194 descriptor, rdf_index);
00195
00196
00197
00198 switch (cur_rdf_type) {
00199 case LDNS_RDF_TYPE_DNAME:
00200 status = ldns_wire2dname(&cur_rdf, wire, max, pos);
00201 LDNS_STATUS_CHECK_RETURN(status);
00202 break;
00203 case LDNS_RDF_TYPE_CLASS:
00204 case LDNS_RDF_TYPE_ALG:
00205 case LDNS_RDF_TYPE_INT8:
00206 cur_rdf_length = LDNS_RDF_SIZE_BYTE;
00207 break;
00208 case LDNS_RDF_TYPE_TYPE:
00209 case LDNS_RDF_TYPE_INT16:
00210 case LDNS_RDF_TYPE_CERT_ALG:
00211 cur_rdf_length = LDNS_RDF_SIZE_WORD;
00212 break;
00213 case LDNS_RDF_TYPE_TIME:
00214 case LDNS_RDF_TYPE_INT32:
00215 case LDNS_RDF_TYPE_A:
00216 case LDNS_RDF_TYPE_PERIOD:
00217 cur_rdf_length = LDNS_RDF_SIZE_DOUBLEWORD;
00218 break;
00219 case LDNS_RDF_TYPE_TSIGTIME:
00220 case LDNS_RDF_TYPE_EUI48:
00221 cur_rdf_length = LDNS_RDF_SIZE_6BYTES;
00222 break;
00223 case LDNS_RDF_TYPE_ILNP64:
00224 case LDNS_RDF_TYPE_EUI64:
00225 cur_rdf_length = LDNS_RDF_SIZE_8BYTES;
00226 break;
00227 case LDNS_RDF_TYPE_AAAA:
00228 cur_rdf_length = LDNS_RDF_SIZE_16BYTES;
00229 break;
00230 case LDNS_RDF_TYPE_STR:
00231 case LDNS_RDF_TYPE_NSEC3_SALT:
00232 case LDNS_RDF_TYPE_TAG:
00233
00234
00235
00236
00237 cur_rdf_length = ((size_t) wire[*pos]) + 1;
00238 break;
00239
00240 case LDNS_RDF_TYPE_INT16_DATA:
00241 if (*pos + 2 > end) {
00242 return LDNS_STATUS_PACKET_OVERFLOW;
00243 }
00244 cur_rdf_length =
00245 (size_t) ldns_read_uint16(&wire[*pos]) + 2;
00246 break;
00247 case LDNS_RDF_TYPE_HIP:
00248 if (*pos + 4 > end) {
00249 return LDNS_STATUS_PACKET_OVERFLOW;
00250 }
00251 cur_rdf_length =
00252 (size_t) wire[*pos] +
00253 (size_t) ldns_read_uint16(&wire[*pos + 2]) + 4;
00254 break;
00255 case LDNS_RDF_TYPE_B32_EXT:
00256 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
00257
00258 cur_rdf_length = ((size_t) wire[*pos]) + 1;
00259 break;
00260 case LDNS_RDF_TYPE_APL:
00261 case LDNS_RDF_TYPE_B64:
00262 case LDNS_RDF_TYPE_HEX:
00263 case LDNS_RDF_TYPE_NSEC:
00264 case LDNS_RDF_TYPE_UNKNOWN:
00265 case LDNS_RDF_TYPE_SERVICE:
00266 case LDNS_RDF_TYPE_LOC:
00267 case LDNS_RDF_TYPE_WKS:
00268 case LDNS_RDF_TYPE_NSAP:
00269 case LDNS_RDF_TYPE_ATMA:
00270 case LDNS_RDF_TYPE_IPSECKEY:
00271 case LDNS_RDF_TYPE_LONG_STR:
00272 case LDNS_RDF_TYPE_NONE:
00273
00274
00275
00276 cur_rdf_length = end - *pos;
00277 break;
00278 }
00279
00280
00281 if (cur_rdf_length > 0) {
00282 if (cur_rdf_length + *pos > end) {
00283 return LDNS_STATUS_PACKET_OVERFLOW;
00284 }
00285 data = LDNS_XMALLOC(uint8_t, rd_length);
00286 if (!data) {
00287 return LDNS_STATUS_MEM_ERR;
00288 }
00289 memcpy(data, &wire[*pos], cur_rdf_length);
00290
00291 cur_rdf = ldns_rdf_new(cur_rdf_type,
00292 cur_rdf_length, data);
00293 *pos = *pos + cur_rdf_length;
00294 }
00295
00296 if (cur_rdf) {
00297 ldns_rr_push_rdf(rr, cur_rdf);
00298 cur_rdf = NULL;
00299 }
00300
00301 rdf_index++;
00302
00303 }
00304
00305
00306 return LDNS_STATUS_OK;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315 ldns_status
00316 ldns_wire2rr(ldns_rr **rr_p, const uint8_t *wire, size_t max,
00317 size_t *pos, ldns_pkt_section section)
00318 {
00319 ldns_rdf *owner = NULL;
00320 ldns_rr *rr = ldns_rr_new();
00321 ldns_status status;
00322
00323 status = ldns_wire2dname(&owner, wire, max, pos);
00324 LDNS_STATUS_CHECK_GOTO(status, status_error);
00325
00326 ldns_rr_set_owner(rr, owner);
00327
00328 if (*pos + 4 > max) {
00329 status = LDNS_STATUS_PACKET_OVERFLOW;
00330 goto status_error;
00331 }
00332
00333 ldns_rr_set_type(rr, ldns_read_uint16(&wire[*pos]));
00334 *pos = *pos + 2;
00335
00336 ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos]));
00337 *pos = *pos + 2;
00338
00339 if (section != LDNS_SECTION_QUESTION) {
00340 if (*pos + 4 > max) {
00341 status = LDNS_STATUS_PACKET_OVERFLOW;
00342 goto status_error;
00343 }
00344 ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos]));
00345
00346 *pos = *pos + 4;
00347 status = ldns_wire2rdf(rr, wire, max, pos);
00348
00349 LDNS_STATUS_CHECK_GOTO(status, status_error);
00350 ldns_rr_set_question(rr, false);
00351 } else {
00352 ldns_rr_set_question(rr, true);
00353 }
00354
00355 *rr_p = rr;
00356 return LDNS_STATUS_OK;
00357
00358 status_error:
00359 ldns_rr_free(rr);
00360 return status;
00361 }
00362
00363 static ldns_status
00364 ldns_wire2pkt_hdr(ldns_pkt *packet, const uint8_t *wire, size_t max, size_t *pos)
00365 {
00366 if (*pos + LDNS_HEADER_SIZE > max) {
00367 return LDNS_STATUS_WIRE_INCOMPLETE_HEADER;
00368 } else {
00369 ldns_pkt_set_id(packet, LDNS_ID_WIRE(wire));
00370 ldns_pkt_set_qr(packet, LDNS_QR_WIRE(wire));
00371 ldns_pkt_set_opcode(packet, LDNS_OPCODE_WIRE(wire));
00372 ldns_pkt_set_aa(packet, LDNS_AA_WIRE(wire));
00373 ldns_pkt_set_tc(packet, LDNS_TC_WIRE(wire));
00374 ldns_pkt_set_rd(packet, LDNS_RD_WIRE(wire));
00375 ldns_pkt_set_ra(packet, LDNS_RA_WIRE(wire));
00376 ldns_pkt_set_ad(packet, LDNS_AD_WIRE(wire));
00377 ldns_pkt_set_cd(packet, LDNS_CD_WIRE(wire));
00378 ldns_pkt_set_rcode(packet, LDNS_RCODE_WIRE(wire));
00379
00380 ldns_pkt_set_qdcount(packet, LDNS_QDCOUNT(wire));
00381 ldns_pkt_set_ancount(packet, LDNS_ANCOUNT(wire));
00382 ldns_pkt_set_nscount(packet, LDNS_NSCOUNT(wire));
00383 ldns_pkt_set_arcount(packet, LDNS_ARCOUNT(wire));
00384
00385 *pos += LDNS_HEADER_SIZE;
00386
00387 return LDNS_STATUS_OK;
00388 }
00389 }
00390
00391 ldns_status
00392 ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer)
00393 {
00394
00395 return ldns_wire2pkt(packet, ldns_buffer_begin(buffer),
00396 ldns_buffer_limit(buffer));
00397
00398 }
00399
00400 ldns_status
00401 ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
00402 {
00403 size_t pos = 0;
00404 uint16_t i;
00405 ldns_rr *rr;
00406 ldns_pkt *packet = ldns_pkt_new();
00407 ldns_status status = LDNS_STATUS_OK;
00408 int have_edns = 0;
00409
00410 uint8_t data[4];
00411
00412 status = ldns_wire2pkt_hdr(packet, wire, max, &pos);
00413 LDNS_STATUS_CHECK_GOTO(status, status_error);
00414
00415 for (i = 0; i < ldns_pkt_qdcount(packet); i++) {
00416
00417 status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_QUESTION);
00418 if (status == LDNS_STATUS_PACKET_OVERFLOW) {
00419 status = LDNS_STATUS_WIRE_INCOMPLETE_QUESTION;
00420 }
00421 LDNS_STATUS_CHECK_GOTO(status, status_error);
00422 if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
00423 ldns_pkt_free(packet);
00424 return LDNS_STATUS_INTERNAL_ERR;
00425 }
00426 }
00427 for (i = 0; i < ldns_pkt_ancount(packet); i++) {
00428 status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ANSWER);
00429 if (status == LDNS_STATUS_PACKET_OVERFLOW) {
00430 status = LDNS_STATUS_WIRE_INCOMPLETE_ANSWER;
00431 }
00432 LDNS_STATUS_CHECK_GOTO(status, status_error);
00433 if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
00434 ldns_pkt_free(packet);
00435 return LDNS_STATUS_INTERNAL_ERR;
00436 }
00437 }
00438 for (i = 0; i < ldns_pkt_nscount(packet); i++) {
00439 status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_AUTHORITY);
00440 if (status == LDNS_STATUS_PACKET_OVERFLOW) {
00441 status = LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY;
00442 }
00443 LDNS_STATUS_CHECK_GOTO(status, status_error);
00444 if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
00445 ldns_pkt_free(packet);
00446 return LDNS_STATUS_INTERNAL_ERR;
00447 }
00448 }
00449 for (i = 0; i < ldns_pkt_arcount(packet); i++) {
00450 status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
00451 if (status == LDNS_STATUS_PACKET_OVERFLOW) {
00452 status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL;
00453 }
00454 LDNS_STATUS_CHECK_GOTO(status, status_error);
00455
00456 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_OPT) {
00457 ldns_pkt_set_edns_udp_size(packet, ldns_rr_get_class(rr));
00458 ldns_write_uint32(data, ldns_rr_ttl(rr));
00459 ldns_pkt_set_edns_extended_rcode(packet, data[0]);
00460 ldns_pkt_set_edns_version(packet, data[1]);
00461 ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2]));
00462
00463 if (ldns_rr_rdf(rr, 0)) {
00464 ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0)));
00465 }
00466 ldns_rr_free(rr);
00467 have_edns += 1;
00468 } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) {
00469 ldns_pkt_set_tsig(packet, rr);
00470 ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1);
00471 } else if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
00472 ldns_pkt_free(packet);
00473 return LDNS_STATUS_INTERNAL_ERR;
00474 }
00475 }
00476 ldns_pkt_set_size(packet, max);
00477 if(have_edns)
00478 ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet)
00479 - have_edns);
00480
00481 *packet_p = packet;
00482 return status;
00483
00484 status_error:
00485 ldns_pkt_free(packet);
00486 return status;
00487 }