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 */ 217b5038d7SDag-Erling Smørgrav size_t 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 677b5038d7SDag-Erling Smørgrav size_t 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 * 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 * 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 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); 238*17d15b25SDag-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