PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/ldns/wire2host.c

https://gitlab.com/HowTheStoryEnds/freebsd11-psm-port
C | 456 lines | 335 code | 59 blank | 62 comment | 66 complexity | f1ae00a4fd94ddd811f7e1c2c97ce87f MD5 | raw file
  1. /*
  2. * wire2host.c
  3. *
  4. * conversion routines from the wire to the host
  5. * format.
  6. * This will usually just a re-ordering of the
  7. * data (as we store it in network format)
  8. *
  9. * a Net::DNS like library for C
  10. *
  11. * (c) NLnet Labs, 2004-2006
  12. *
  13. * See the file LICENSE for the license
  14. */
  15. #include <ldns/config.h>
  16. #include <ldns/ldns.h>
  17. /*#include <ldns/wire2host.h>*/
  18. #include <strings.h>
  19. #include <limits.h>
  20. /*
  21. * Set of macro's to deal with the dns message header as specified
  22. * in RFC1035 in portable way.
  23. *
  24. */
  25. /*
  26. *
  27. * 1 1 1 1 1 1
  28. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  29. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  30. * | ID |
  31. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  32. * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
  33. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  34. * | QDCOUNT |
  35. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  36. * | ANCOUNT |
  37. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  38. * | NSCOUNT |
  39. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  40. * | ARCOUNT |
  41. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  42. *
  43. */
  44. /* allocates memory to *dname! */
  45. ldns_status
  46. ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos)
  47. {
  48. uint8_t label_size;
  49. uint16_t pointer_target;
  50. uint8_t pointer_target_buf[2];
  51. size_t dname_pos = 0;
  52. size_t uncompressed_length = 0;
  53. size_t compression_pos = 0;
  54. uint8_t tmp_dname[LDNS_MAX_DOMAINLEN];
  55. unsigned int pointer_count = 0;
  56. if (*pos >= max) {
  57. return LDNS_STATUS_PACKET_OVERFLOW;
  58. }
  59. label_size = wire[*pos];
  60. while (label_size > 0) {
  61. /* compression */
  62. while (label_size >= 192) {
  63. if (compression_pos == 0) {
  64. compression_pos = *pos + 2;
  65. }
  66. pointer_count++;
  67. /* remove first two bits */
  68. if (*pos + 2 > max) {
  69. return LDNS_STATUS_PACKET_OVERFLOW;
  70. }
  71. pointer_target_buf[0] = wire[*pos] & 63;
  72. pointer_target_buf[1] = wire[*pos + 1];
  73. pointer_target = ldns_read_uint16(pointer_target_buf);
  74. if (pointer_target == 0) {
  75. return LDNS_STATUS_INVALID_POINTER;
  76. } else if (pointer_target >= max) {
  77. return LDNS_STATUS_INVALID_POINTER;
  78. } else if (pointer_count > LDNS_MAX_POINTERS) {
  79. return LDNS_STATUS_INVALID_POINTER;
  80. }
  81. *pos = pointer_target;
  82. label_size = wire[*pos];
  83. }
  84. if(label_size == 0)
  85. break; /* break from pointer to 0 byte */
  86. if (label_size > LDNS_MAX_LABELLEN) {
  87. return LDNS_STATUS_LABEL_OVERFLOW;
  88. }
  89. if (*pos + 1 + label_size > max) {
  90. return LDNS_STATUS_LABEL_OVERFLOW;
  91. }
  92. /* check space for labelcount itself */
  93. if (dname_pos + 1 > LDNS_MAX_DOMAINLEN) {
  94. return LDNS_STATUS_DOMAINNAME_OVERFLOW;
  95. }
  96. tmp_dname[dname_pos] = label_size;
  97. if (label_size > 0) {
  98. dname_pos++;
  99. }
  100. *pos = *pos + 1;
  101. if (dname_pos + label_size > LDNS_MAX_DOMAINLEN) {
  102. return LDNS_STATUS_DOMAINNAME_OVERFLOW;
  103. }
  104. memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size);
  105. uncompressed_length += label_size + 1;
  106. dname_pos += label_size;
  107. *pos = *pos + label_size;
  108. if (*pos < max) {
  109. label_size = wire[*pos];
  110. }
  111. }
  112. if (compression_pos > 0) {
  113. *pos = compression_pos;
  114. } else {
  115. *pos = *pos + 1;
  116. }
  117. if (dname_pos >= LDNS_MAX_DOMAINLEN) {
  118. return LDNS_STATUS_DOMAINNAME_OVERFLOW;
  119. }
  120. tmp_dname[dname_pos] = 0;
  121. dname_pos++;
  122. *dname = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
  123. (uint16_t) dname_pos, tmp_dname);
  124. if (!*dname) {
  125. return LDNS_STATUS_MEM_ERR;
  126. }
  127. return LDNS_STATUS_OK;
  128. }
  129. /* maybe make this a goto error so data can be freed or something/ */
  130. #define LDNS_STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }}
  131. #define LDNS_STATUS_CHECK_GOTO(st, label) {if (st != LDNS_STATUS_OK) { /*printf("STG %s:%d: status code %d\n", __FILE__, __LINE__, st);*/ goto label; }}
  132. ldns_status
  133. ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
  134. {
  135. size_t end;
  136. size_t cur_rdf_length;
  137. uint8_t rdf_index;
  138. uint8_t *data;
  139. uint16_t rd_length;
  140. ldns_rdf *cur_rdf = NULL;
  141. ldns_rdf_type cur_rdf_type;
  142. const ldns_rr_descriptor *descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
  143. ldns_status status;
  144. if (*pos + 2 > max) {
  145. return LDNS_STATUS_PACKET_OVERFLOW;
  146. }
  147. rd_length = ldns_read_uint16(&wire[*pos]);
  148. *pos = *pos + 2;
  149. if (*pos + rd_length > max) {
  150. return LDNS_STATUS_PACKET_OVERFLOW;
  151. }
  152. end = *pos + (size_t) rd_length;
  153. for (rdf_index = 0;
  154. rdf_index < ldns_rr_descriptor_maximum(descriptor); rdf_index++) {
  155. if (*pos >= end) {
  156. break;
  157. }
  158. cur_rdf_length = 0;
  159. cur_rdf_type = ldns_rr_descriptor_field_type(descriptor, rdf_index);
  160. /* handle special cases immediately, set length
  161. for fixed length rdata and do them below */
  162. switch (cur_rdf_type) {
  163. case LDNS_RDF_TYPE_DNAME:
  164. status = ldns_wire2dname(&cur_rdf, wire, max, pos);
  165. LDNS_STATUS_CHECK_RETURN(status);
  166. break;
  167. case LDNS_RDF_TYPE_CLASS:
  168. case LDNS_RDF_TYPE_ALG:
  169. case LDNS_RDF_TYPE_INT8:
  170. cur_rdf_length = LDNS_RDF_SIZE_BYTE;
  171. break;
  172. case LDNS_RDF_TYPE_TYPE:
  173. case LDNS_RDF_TYPE_INT16:
  174. case LDNS_RDF_TYPE_CERT_ALG:
  175. cur_rdf_length = LDNS_RDF_SIZE_WORD;
  176. break;
  177. case LDNS_RDF_TYPE_TIME:
  178. case LDNS_RDF_TYPE_INT32:
  179. case LDNS_RDF_TYPE_A:
  180. case LDNS_RDF_TYPE_PERIOD:
  181. cur_rdf_length = LDNS_RDF_SIZE_DOUBLEWORD;
  182. break;
  183. case LDNS_RDF_TYPE_TSIGTIME:
  184. cur_rdf_length = LDNS_RDF_SIZE_6BYTES;
  185. break;
  186. case LDNS_RDF_TYPE_AAAA:
  187. cur_rdf_length = LDNS_RDF_SIZE_16BYTES;
  188. break;
  189. case LDNS_RDF_TYPE_STR:
  190. case LDNS_RDF_TYPE_NSEC3_SALT:
  191. /* len is stored in first byte
  192. * it should be in the rdf too, so just
  193. * copy len+1 from this position
  194. */
  195. cur_rdf_length = ((size_t) wire[*pos]) + 1;
  196. break;
  197. case LDNS_RDF_TYPE_INT16_DATA:
  198. cur_rdf_length = (size_t) ldns_read_uint16(&wire[*pos]) + 2;
  199. break;
  200. case LDNS_RDF_TYPE_B32_EXT:
  201. case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
  202. /* length is stored in first byte */
  203. cur_rdf_length = ((size_t) wire[*pos]) + 1;
  204. break;
  205. case LDNS_RDF_TYPE_APL:
  206. case LDNS_RDF_TYPE_B64:
  207. case LDNS_RDF_TYPE_HEX:
  208. case LDNS_RDF_TYPE_NSEC:
  209. case LDNS_RDF_TYPE_UNKNOWN:
  210. case LDNS_RDF_TYPE_SERVICE:
  211. case LDNS_RDF_TYPE_LOC:
  212. case LDNS_RDF_TYPE_WKS:
  213. case LDNS_RDF_TYPE_NSAP:
  214. case LDNS_RDF_TYPE_ATMA:
  215. case LDNS_RDF_TYPE_IPSECKEY:
  216. case LDNS_RDF_TYPE_TSIG:
  217. case LDNS_RDF_TYPE_NONE:
  218. /*
  219. * Read to end of rr rdata
  220. */
  221. cur_rdf_length = end - *pos;
  222. break;
  223. }
  224. /* fixed length rdata */
  225. if (cur_rdf_length > 0) {
  226. if (cur_rdf_length + *pos > end) {
  227. return LDNS_STATUS_PACKET_OVERFLOW;
  228. }
  229. data = LDNS_XMALLOC(uint8_t, rd_length);
  230. if (!data) {
  231. return LDNS_STATUS_MEM_ERR;
  232. }
  233. memcpy(data, &wire[*pos], cur_rdf_length);
  234. cur_rdf = ldns_rdf_new(cur_rdf_type, cur_rdf_length, data);
  235. *pos = *pos + cur_rdf_length;
  236. }
  237. if (cur_rdf) {
  238. ldns_rr_push_rdf(rr, cur_rdf);
  239. cur_rdf = NULL;
  240. }
  241. }
  242. return LDNS_STATUS_OK;
  243. }
  244. /* TODO:
  245. can *pos be incremented at READ_INT? or maybe use something like
  246. RR_CLASS(wire)?
  247. uhhm Jelte??
  248. */
  249. ldns_status
  250. ldns_wire2rr(ldns_rr **rr_p, const uint8_t *wire, size_t max,
  251. size_t *pos, ldns_pkt_section section)
  252. {
  253. ldns_rdf *owner = NULL;
  254. ldns_rr *rr = ldns_rr_new();
  255. ldns_status status;
  256. status = ldns_wire2dname(&owner, wire, max, pos);
  257. LDNS_STATUS_CHECK_GOTO(status, status_error);
  258. ldns_rr_set_owner(rr, owner);
  259. if (*pos + 4 > max) {
  260. status = LDNS_STATUS_PACKET_OVERFLOW;
  261. goto status_error;
  262. }
  263. ldns_rr_set_type(rr, ldns_read_uint16(&wire[*pos]));
  264. *pos = *pos + 2;
  265. ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos]));
  266. *pos = *pos + 2;
  267. if (section != LDNS_SECTION_QUESTION) {
  268. if (*pos + 4 > max) {
  269. status = LDNS_STATUS_PACKET_OVERFLOW;
  270. goto status_error;
  271. }
  272. ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos]));
  273. *pos = *pos + 4;
  274. status = ldns_wire2rdf(rr, wire, max, pos);
  275. LDNS_STATUS_CHECK_GOTO(status, status_error);
  276. ldns_rr_set_question(rr, false);
  277. } else {
  278. ldns_rr_set_question(rr, true);
  279. }
  280. *rr_p = rr;
  281. return LDNS_STATUS_OK;
  282. status_error:
  283. ldns_rr_free(rr);
  284. return status;
  285. }
  286. static ldns_status
  287. ldns_wire2pkt_hdr(ldns_pkt *packet, const uint8_t *wire, size_t max, size_t *pos)
  288. {
  289. if (*pos + LDNS_HEADER_SIZE > max) {
  290. return LDNS_STATUS_WIRE_INCOMPLETE_HEADER;
  291. } else {
  292. ldns_pkt_set_id(packet, LDNS_ID_WIRE(wire));
  293. ldns_pkt_set_qr(packet, LDNS_QR_WIRE(wire));
  294. ldns_pkt_set_opcode(packet, LDNS_OPCODE_WIRE(wire));
  295. ldns_pkt_set_aa(packet, LDNS_AA_WIRE(wire));
  296. ldns_pkt_set_tc(packet, LDNS_TC_WIRE(wire));
  297. ldns_pkt_set_rd(packet, LDNS_RD_WIRE(wire));
  298. ldns_pkt_set_ra(packet, LDNS_RA_WIRE(wire));
  299. ldns_pkt_set_ad(packet, LDNS_AD_WIRE(wire));
  300. ldns_pkt_set_cd(packet, LDNS_CD_WIRE(wire));
  301. ldns_pkt_set_rcode(packet, LDNS_RCODE_WIRE(wire));
  302. ldns_pkt_set_qdcount(packet, LDNS_QDCOUNT(wire));
  303. ldns_pkt_set_ancount(packet, LDNS_ANCOUNT(wire));
  304. ldns_pkt_set_nscount(packet, LDNS_NSCOUNT(wire));
  305. ldns_pkt_set_arcount(packet, LDNS_ARCOUNT(wire));
  306. *pos += LDNS_HEADER_SIZE;
  307. return LDNS_STATUS_OK;
  308. }
  309. }
  310. ldns_status
  311. ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer)
  312. {
  313. /* lazy */
  314. return ldns_wire2pkt(packet, ldns_buffer_begin(buffer),
  315. ldns_buffer_limit(buffer));
  316. }
  317. ldns_status
  318. ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
  319. {
  320. size_t pos = 0;
  321. uint16_t i;
  322. ldns_rr *rr;
  323. ldns_pkt *packet = ldns_pkt_new();
  324. ldns_status status = LDNS_STATUS_OK;
  325. int have_edns = 0;
  326. uint8_t data[4];
  327. status = ldns_wire2pkt_hdr(packet, wire, max, &pos);
  328. LDNS_STATUS_CHECK_GOTO(status, status_error);
  329. for (i = 0; i < ldns_pkt_qdcount(packet); i++) {
  330. status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_QUESTION);
  331. if (status == LDNS_STATUS_PACKET_OVERFLOW) {
  332. status = LDNS_STATUS_WIRE_INCOMPLETE_QUESTION;
  333. }
  334. LDNS_STATUS_CHECK_GOTO(status, status_error);
  335. if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
  336. ldns_pkt_free(packet);
  337. return LDNS_STATUS_INTERNAL_ERR;
  338. }
  339. }
  340. for (i = 0; i < ldns_pkt_ancount(packet); i++) {
  341. status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ANSWER);
  342. if (status == LDNS_STATUS_PACKET_OVERFLOW) {
  343. status = LDNS_STATUS_WIRE_INCOMPLETE_ANSWER;
  344. }
  345. LDNS_STATUS_CHECK_GOTO(status, status_error);
  346. if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
  347. ldns_pkt_free(packet);
  348. return LDNS_STATUS_INTERNAL_ERR;
  349. }
  350. }
  351. for (i = 0; i < ldns_pkt_nscount(packet); i++) {
  352. status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_AUTHORITY);
  353. if (status == LDNS_STATUS_PACKET_OVERFLOW) {
  354. status = LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY;
  355. }
  356. LDNS_STATUS_CHECK_GOTO(status, status_error);
  357. if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
  358. ldns_pkt_free(packet);
  359. return LDNS_STATUS_INTERNAL_ERR;
  360. }
  361. }
  362. for (i = 0; i < ldns_pkt_arcount(packet); i++) {
  363. status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
  364. if (status == LDNS_STATUS_PACKET_OVERFLOW) {
  365. status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL;
  366. }
  367. LDNS_STATUS_CHECK_GOTO(status, status_error);
  368. if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_OPT) {
  369. ldns_pkt_set_edns_udp_size(packet, ldns_rr_get_class(rr));
  370. ldns_write_uint32(data, ldns_rr_ttl(rr));
  371. ldns_pkt_set_edns_extended_rcode(packet, data[0]);
  372. ldns_pkt_set_edns_version(packet, data[1]);
  373. ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2]));
  374. /* edns might not have rdfs */
  375. if (ldns_rr_rdf(rr, 0)) {
  376. ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0)));
  377. }
  378. ldns_rr_free(rr);
  379. have_edns += 1;
  380. } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) {
  381. ldns_pkt_set_tsig(packet, rr);
  382. ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1);
  383. } else if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
  384. ldns_pkt_free(packet);
  385. return LDNS_STATUS_INTERNAL_ERR;
  386. }
  387. }
  388. ldns_pkt_set_size(packet, max);
  389. if(have_edns)
  390. ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet)
  391. - have_edns);
  392. *packet_p = packet;
  393. return status;
  394. status_error:
  395. ldns_pkt_free(packet);
  396. return status;
  397. }