17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav * work.c
37b5038d7SDag-Erling Smørgrav * Where all the hard work is done
47b5038d7SDag-Erling Smørgrav * (c) 2005 NLnet Labs
57b5038d7SDag-Erling Smørgrav *
67b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license
77b5038d7SDag-Erling Smørgrav *
87b5038d7SDag-Erling Smørgrav */
97b5038d7SDag-Erling Smørgrav
107b5038d7SDag-Erling Smørgrav #include "drill.h"
117b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
127b5038d7SDag-Erling Smørgrav
137b5038d7SDag-Erling Smørgrav /**
147b5038d7SDag-Erling Smørgrav * Converts a hex string to binary data
157b5038d7SDag-Erling Smørgrav * len is the length of the string
167b5038d7SDag-Erling Smørgrav * buf is the buffer to store the result in
177b5038d7SDag-Erling Smørgrav * offset is the starting position in the result buffer
187b5038d7SDag-Erling Smørgrav *
197b5038d7SDag-Erling Smørgrav * This function returns the length of the result
207b5038d7SDag-Erling Smørgrav */
21*986ba33cSDag-Erling Smørgrav static size_t
hexstr2bin(char * hexstr,int len,uint8_t * buf,size_t offset,size_t buf_len)227b5038d7SDag-Erling Smørgrav hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
237b5038d7SDag-Erling Smørgrav {
247b5038d7SDag-Erling Smørgrav char c;
257b5038d7SDag-Erling Smørgrav int i;
267b5038d7SDag-Erling Smørgrav uint8_t int8 = 0;
277b5038d7SDag-Erling Smørgrav int sec = 0;
287b5038d7SDag-Erling Smørgrav size_t bufpos = 0;
297b5038d7SDag-Erling Smørgrav
307b5038d7SDag-Erling Smørgrav if (len % 2 != 0) {
317b5038d7SDag-Erling Smørgrav return 0;
327b5038d7SDag-Erling Smørgrav }
337b5038d7SDag-Erling Smørgrav
347b5038d7SDag-Erling Smørgrav for (i=0; i<len; i++) {
357b5038d7SDag-Erling Smørgrav c = hexstr[i];
367b5038d7SDag-Erling Smørgrav
377b5038d7SDag-Erling Smørgrav /* case insensitive, skip spaces */
387b5038d7SDag-Erling Smørgrav if (c != ' ') {
397b5038d7SDag-Erling Smørgrav if (c >= '0' && c <= '9') {
407b5038d7SDag-Erling Smørgrav int8 += c & 0x0f;
417b5038d7SDag-Erling Smørgrav } else if (c >= 'a' && c <= 'z') {
427b5038d7SDag-Erling Smørgrav int8 += (c & 0x0f) + 9;
437b5038d7SDag-Erling Smørgrav } else if (c >= 'A' && c <= 'Z') {
447b5038d7SDag-Erling Smørgrav int8 += (c & 0x0f) + 9;
457b5038d7SDag-Erling Smørgrav } else {
467b5038d7SDag-Erling Smørgrav return 0;
477b5038d7SDag-Erling Smørgrav }
487b5038d7SDag-Erling Smørgrav
497b5038d7SDag-Erling Smørgrav if (sec == 0) {
507b5038d7SDag-Erling Smørgrav int8 = int8 << 4;
517b5038d7SDag-Erling Smørgrav sec = 1;
527b5038d7SDag-Erling Smørgrav } else {
537b5038d7SDag-Erling Smørgrav if (bufpos + offset + 1 <= buf_len) {
547b5038d7SDag-Erling Smørgrav buf[bufpos+offset] = int8;
557b5038d7SDag-Erling Smørgrav int8 = 0;
567b5038d7SDag-Erling Smørgrav sec = 0;
577b5038d7SDag-Erling Smørgrav bufpos++;
587b5038d7SDag-Erling Smørgrav } else {
597b5038d7SDag-Erling Smørgrav error("Buffer too small in hexstr2bin");
607b5038d7SDag-Erling Smørgrav }
617b5038d7SDag-Erling Smørgrav }
627b5038d7SDag-Erling Smørgrav }
637b5038d7SDag-Erling Smørgrav }
647b5038d7SDag-Erling Smørgrav return bufpos;
657b5038d7SDag-Erling Smørgrav }
667b5038d7SDag-Erling Smørgrav
67*986ba33cSDag-Erling Smørgrav static size_t
packetbuffromfile(char * filename,uint8_t * wire)687b5038d7SDag-Erling Smørgrav packetbuffromfile(char *filename, uint8_t *wire)
697b5038d7SDag-Erling Smørgrav {
707b5038d7SDag-Erling Smørgrav FILE *fp = NULL;
717b5038d7SDag-Erling Smørgrav int c;
727b5038d7SDag-Erling Smørgrav
737b5038d7SDag-Erling Smørgrav /* stat hack
747b5038d7SDag-Erling Smørgrav * 0 = normal
757b5038d7SDag-Erling Smørgrav * 1 = comment (skip to end of line)
767b5038d7SDag-Erling Smørgrav * 2 = unprintable character found, read binary data directly
777b5038d7SDag-Erling Smørgrav */
787b5038d7SDag-Erling Smørgrav int state = 0;
797b5038d7SDag-Erling Smørgrav uint8_t *hexbuf = xmalloc(LDNS_MAX_PACKETLEN);
807b5038d7SDag-Erling Smørgrav int hexbufpos = 0;
817b5038d7SDag-Erling Smørgrav size_t wirelen;
827b5038d7SDag-Erling Smørgrav
837b5038d7SDag-Erling Smørgrav if (strncmp(filename, "-", 2) == 0) {
847b5038d7SDag-Erling Smørgrav fp = stdin;
857b5038d7SDag-Erling Smørgrav } else {
867b5038d7SDag-Erling Smørgrav fp = fopen(filename, "r");
877b5038d7SDag-Erling Smørgrav }
887b5038d7SDag-Erling Smørgrav if (fp == NULL) {
897b5038d7SDag-Erling Smørgrav perror("Unable to open file for reading");
907b5038d7SDag-Erling Smørgrav xfree(hexbuf);
917b5038d7SDag-Erling Smørgrav return 0;
927b5038d7SDag-Erling Smørgrav }
937b5038d7SDag-Erling Smørgrav
947b5038d7SDag-Erling Smørgrav /*verbose("Opened %s\n", filename);*/
957b5038d7SDag-Erling Smørgrav
967b5038d7SDag-Erling Smørgrav c = fgetc(fp);
977b5038d7SDag-Erling Smørgrav while (c != EOF && hexbufpos < LDNS_MAX_PACKETLEN) {
987b5038d7SDag-Erling Smørgrav if (state < 2 && !isascii(c)) {
997b5038d7SDag-Erling Smørgrav /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
1007b5038d7SDag-Erling Smørgrav state = 2;
1017b5038d7SDag-Erling Smørgrav }
1027b5038d7SDag-Erling Smørgrav switch (state) {
1037b5038d7SDag-Erling Smørgrav case 0:
1047b5038d7SDag-Erling Smørgrav if ( (c >= '0' && c <= '9') ||
1057b5038d7SDag-Erling Smørgrav (c >= 'a' && c <= 'f') ||
1067b5038d7SDag-Erling Smørgrav (c >= 'A' && c <= 'F') )
1077b5038d7SDag-Erling Smørgrav {
1087b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) c;
1097b5038d7SDag-Erling Smørgrav hexbufpos++;
1107b5038d7SDag-Erling Smørgrav } else if (c == ';') {
1117b5038d7SDag-Erling Smørgrav state = 1;
1127b5038d7SDag-Erling Smørgrav } else if (c == ' ' || c == '\t' || c == '\n') {
1137b5038d7SDag-Erling Smørgrav /* skip whitespace */
1147b5038d7SDag-Erling Smørgrav }
1157b5038d7SDag-Erling Smørgrav break;
1167b5038d7SDag-Erling Smørgrav case 1:
1177b5038d7SDag-Erling Smørgrav if (c == '\n' || c == EOF) {
1187b5038d7SDag-Erling Smørgrav state = 0;
1197b5038d7SDag-Erling Smørgrav }
1207b5038d7SDag-Erling Smørgrav break;
1217b5038d7SDag-Erling Smørgrav case 2:
1227b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) c;
1237b5038d7SDag-Erling Smørgrav hexbufpos++;
1247b5038d7SDag-Erling Smørgrav break;
1257b5038d7SDag-Erling Smørgrav }
1267b5038d7SDag-Erling Smørgrav c = fgetc(fp);
1277b5038d7SDag-Erling Smørgrav }
1287b5038d7SDag-Erling Smørgrav
1297b5038d7SDag-Erling Smørgrav if (c == EOF) {
1307b5038d7SDag-Erling Smørgrav /*
1317b5038d7SDag-Erling Smørgrav if (have_drill_opt && drill_opt->verbose) {
1327b5038d7SDag-Erling Smørgrav verbose("END OF FILE REACHED\n");
1337b5038d7SDag-Erling Smørgrav if (state < 2) {
1347b5038d7SDag-Erling Smørgrav verbose("read:\n");
1357b5038d7SDag-Erling Smørgrav verbose("%s\n", hexbuf);
1367b5038d7SDag-Erling Smørgrav } else {
1377b5038d7SDag-Erling Smørgrav verbose("Not printing wire because it contains non ascii data\n");
1387b5038d7SDag-Erling Smørgrav }
1397b5038d7SDag-Erling Smørgrav }
1407b5038d7SDag-Erling Smørgrav */
1417b5038d7SDag-Erling Smørgrav }
1427b5038d7SDag-Erling Smørgrav if (hexbufpos >= LDNS_MAX_PACKETLEN) {
1437b5038d7SDag-Erling Smørgrav /*verbose("packet size reached\n");*/
1447b5038d7SDag-Erling Smørgrav }
1457b5038d7SDag-Erling Smørgrav
1467b5038d7SDag-Erling Smørgrav /* lenient mode: length must be multiple of 2 */
1477b5038d7SDag-Erling Smørgrav if (hexbufpos % 2 != 0) {
1487b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) '0';
1497b5038d7SDag-Erling Smørgrav hexbufpos++;
1507b5038d7SDag-Erling Smørgrav }
1517b5038d7SDag-Erling Smørgrav
1527b5038d7SDag-Erling Smørgrav if (state < 2) {
1537b5038d7SDag-Erling Smørgrav wirelen = hexstr2bin((char *) hexbuf,
1547b5038d7SDag-Erling Smørgrav hexbufpos,
1557b5038d7SDag-Erling Smørgrav wire,
1567b5038d7SDag-Erling Smørgrav 0,
1577b5038d7SDag-Erling Smørgrav LDNS_MAX_PACKETLEN);
1587b5038d7SDag-Erling Smørgrav } else {
1597b5038d7SDag-Erling Smørgrav memcpy(wire, hexbuf, (size_t) hexbufpos);
1607b5038d7SDag-Erling Smørgrav wirelen = (size_t) hexbufpos;
1617b5038d7SDag-Erling Smørgrav }
1627b5038d7SDag-Erling Smørgrav if (fp != stdin) {
1637b5038d7SDag-Erling Smørgrav fclose(fp);
1647b5038d7SDag-Erling Smørgrav }
1657b5038d7SDag-Erling Smørgrav xfree(hexbuf);
1667b5038d7SDag-Erling Smørgrav return wirelen;
1677b5038d7SDag-Erling Smørgrav }
1687b5038d7SDag-Erling Smørgrav
1697b5038d7SDag-Erling Smørgrav ldns_buffer *
read_hex_buffer(char * filename)1707b5038d7SDag-Erling Smørgrav read_hex_buffer(char *filename)
1717b5038d7SDag-Erling Smørgrav {
1727b5038d7SDag-Erling Smørgrav uint8_t *wire;
1737b5038d7SDag-Erling Smørgrav size_t wiresize;
1747b5038d7SDag-Erling Smørgrav ldns_buffer *result_buffer = NULL;
1757b5038d7SDag-Erling Smørgrav
1767b5038d7SDag-Erling Smørgrav
1777b5038d7SDag-Erling Smørgrav wire = xmalloc(LDNS_MAX_PACKETLEN);
1787b5038d7SDag-Erling Smørgrav
1797b5038d7SDag-Erling Smørgrav wiresize = packetbuffromfile(filename, wire);
1807b5038d7SDag-Erling Smørgrav
1817b5038d7SDag-Erling Smørgrav result_buffer = LDNS_MALLOC(ldns_buffer);
1827b5038d7SDag-Erling Smørgrav ldns_buffer_new_frm_data(result_buffer, wire, wiresize);
1837b5038d7SDag-Erling Smørgrav ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer));
1847b5038d7SDag-Erling Smørgrav xfree(wire);
1852787e39aSDag-Erling Smørgrav
1867b5038d7SDag-Erling Smørgrav return result_buffer;
1877b5038d7SDag-Erling Smørgrav }
1887b5038d7SDag-Erling Smørgrav
1897b5038d7SDag-Erling Smørgrav ldns_pkt *
read_hex_pkt(char * filename)1907b5038d7SDag-Erling Smørgrav read_hex_pkt(char *filename)
1917b5038d7SDag-Erling Smørgrav {
1927b5038d7SDag-Erling Smørgrav uint8_t *wire;
1937b5038d7SDag-Erling Smørgrav size_t wiresize;
1947b5038d7SDag-Erling Smørgrav
1957b5038d7SDag-Erling Smørgrav ldns_pkt *pkt = NULL;
1967b5038d7SDag-Erling Smørgrav
1977b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_ERR;
1987b5038d7SDag-Erling Smørgrav
1997b5038d7SDag-Erling Smørgrav wire = xmalloc(LDNS_MAX_PACKETLEN);
2007b5038d7SDag-Erling Smørgrav
2017b5038d7SDag-Erling Smørgrav wiresize = packetbuffromfile(filename, wire);
2027b5038d7SDag-Erling Smørgrav
2037b5038d7SDag-Erling Smørgrav if (wiresize > 0) {
2047b5038d7SDag-Erling Smørgrav status = ldns_wire2pkt(&pkt, wire, wiresize);
2057b5038d7SDag-Erling Smørgrav }
2067b5038d7SDag-Erling Smørgrav
2077b5038d7SDag-Erling Smørgrav xfree(wire);
2087b5038d7SDag-Erling Smørgrav
2097b5038d7SDag-Erling Smørgrav if (status == LDNS_STATUS_OK) {
2107b5038d7SDag-Erling Smørgrav return pkt;
2117b5038d7SDag-Erling Smørgrav } else {
2127b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error parsing hex file: %s\n",
2137b5038d7SDag-Erling Smørgrav ldns_get_errorstr_by_id(status));
2147b5038d7SDag-Erling Smørgrav return NULL;
2157b5038d7SDag-Erling Smørgrav }
2167b5038d7SDag-Erling Smørgrav }
2177b5038d7SDag-Erling Smørgrav
2187b5038d7SDag-Erling Smørgrav void
dump_hex(const ldns_pkt * pkt,const char * filename)2197b5038d7SDag-Erling Smørgrav dump_hex(const ldns_pkt *pkt, const char *filename)
2207b5038d7SDag-Erling Smørgrav {
2212787e39aSDag-Erling Smørgrav uint8_t *wire = NULL;
2227b5038d7SDag-Erling Smørgrav size_t size, i;
2237b5038d7SDag-Erling Smørgrav FILE *fp;
2247b5038d7SDag-Erling Smørgrav ldns_status status;
2257b5038d7SDag-Erling Smørgrav
2267b5038d7SDag-Erling Smørgrav fp = fopen(filename, "w");
2277b5038d7SDag-Erling Smørgrav
2287b5038d7SDag-Erling Smørgrav if (fp == NULL) {
2297b5038d7SDag-Erling Smørgrav error("Unable to open %s for writing", filename);
2307b5038d7SDag-Erling Smørgrav return;
2317b5038d7SDag-Erling Smørgrav }
2327b5038d7SDag-Erling Smørgrav
2337b5038d7SDag-Erling Smørgrav status = ldns_pkt2wire(&wire, pkt, &size);
2347b5038d7SDag-Erling Smørgrav
2357b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
2367b5038d7SDag-Erling Smørgrav error("Unable to convert packet: error code %u", status);
2372787e39aSDag-Erling Smørgrav LDNS_FREE(wire);
23817d15b25SDag-Erling Smørgrav fclose(fp);
2397b5038d7SDag-Erling Smørgrav return;
2407b5038d7SDag-Erling Smørgrav }
2417b5038d7SDag-Erling Smørgrav
2427b5038d7SDag-Erling Smørgrav fprintf(fp, "; 0");
2437b5038d7SDag-Erling Smørgrav for (i = 1; i < 20; i++) {
2447b5038d7SDag-Erling Smørgrav fprintf(fp, " %2u", (unsigned int) i);
2457b5038d7SDag-Erling Smørgrav }
2467b5038d7SDag-Erling Smørgrav fprintf(fp, "\n");
2477b5038d7SDag-Erling Smørgrav fprintf(fp, ";--");
2487b5038d7SDag-Erling Smørgrav for (i = 1; i < 20; i++) {
2497b5038d7SDag-Erling Smørgrav fprintf(fp, " --");
2507b5038d7SDag-Erling Smørgrav }
2517b5038d7SDag-Erling Smørgrav fprintf(fp, "\n");
2527b5038d7SDag-Erling Smørgrav for (i = 0; i < size; i++) {
2537b5038d7SDag-Erling Smørgrav if (i % 20 == 0 && i > 0) {
2547b5038d7SDag-Erling Smørgrav fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
2557b5038d7SDag-Erling Smørgrav }
2567b5038d7SDag-Erling Smørgrav fprintf(fp, " %02x", (unsigned int)wire[i]);
2577b5038d7SDag-Erling Smørgrav }
2587b5038d7SDag-Erling Smørgrav fprintf(fp, "\n");
2597b5038d7SDag-Erling Smørgrav fclose(fp);
2602787e39aSDag-Erling Smørgrav LDNS_FREE(wire);
2617b5038d7SDag-Erling Smørgrav }
262