1*7b5038d7SDag-Erling Smørgrav /* 2*7b5038d7SDag-Erling Smørgrav * work.c 3*7b5038d7SDag-Erling Smørgrav * Where all the hard work is done 4*7b5038d7SDag-Erling Smørgrav * (c) 2005 NLnet Labs 5*7b5038d7SDag-Erling Smørgrav * 6*7b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 7*7b5038d7SDag-Erling Smørgrav * 8*7b5038d7SDag-Erling Smørgrav */ 9*7b5038d7SDag-Erling Smørgrav 10*7b5038d7SDag-Erling Smørgrav #include "drill.h" 11*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 12*7b5038d7SDag-Erling Smørgrav 13*7b5038d7SDag-Erling Smørgrav /** 14*7b5038d7SDag-Erling Smørgrav * Converts a hex string to binary data 15*7b5038d7SDag-Erling Smørgrav * len is the length of the string 16*7b5038d7SDag-Erling Smørgrav * buf is the buffer to store the result in 17*7b5038d7SDag-Erling Smørgrav * offset is the starting position in the result buffer 18*7b5038d7SDag-Erling Smørgrav * 19*7b5038d7SDag-Erling Smørgrav * This function returns the length of the result 20*7b5038d7SDag-Erling Smørgrav */ 21*7b5038d7SDag-Erling Smørgrav size_t 22*7b5038d7SDag-Erling Smørgrav hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len) 23*7b5038d7SDag-Erling Smørgrav { 24*7b5038d7SDag-Erling Smørgrav char c; 25*7b5038d7SDag-Erling Smørgrav int i; 26*7b5038d7SDag-Erling Smørgrav uint8_t int8 = 0; 27*7b5038d7SDag-Erling Smørgrav int sec = 0; 28*7b5038d7SDag-Erling Smørgrav size_t bufpos = 0; 29*7b5038d7SDag-Erling Smørgrav 30*7b5038d7SDag-Erling Smørgrav if (len % 2 != 0) { 31*7b5038d7SDag-Erling Smørgrav return 0; 32*7b5038d7SDag-Erling Smørgrav } 33*7b5038d7SDag-Erling Smørgrav 34*7b5038d7SDag-Erling Smørgrav for (i=0; i<len; i++) { 35*7b5038d7SDag-Erling Smørgrav c = hexstr[i]; 36*7b5038d7SDag-Erling Smørgrav 37*7b5038d7SDag-Erling Smørgrav /* case insensitive, skip spaces */ 38*7b5038d7SDag-Erling Smørgrav if (c != ' ') { 39*7b5038d7SDag-Erling Smørgrav if (c >= '0' && c <= '9') { 40*7b5038d7SDag-Erling Smørgrav int8 += c & 0x0f; 41*7b5038d7SDag-Erling Smørgrav } else if (c >= 'a' && c <= 'z') { 42*7b5038d7SDag-Erling Smørgrav int8 += (c & 0x0f) + 9; 43*7b5038d7SDag-Erling Smørgrav } else if (c >= 'A' && c <= 'Z') { 44*7b5038d7SDag-Erling Smørgrav int8 += (c & 0x0f) + 9; 45*7b5038d7SDag-Erling Smørgrav } else { 46*7b5038d7SDag-Erling Smørgrav return 0; 47*7b5038d7SDag-Erling Smørgrav } 48*7b5038d7SDag-Erling Smørgrav 49*7b5038d7SDag-Erling Smørgrav if (sec == 0) { 50*7b5038d7SDag-Erling Smørgrav int8 = int8 << 4; 51*7b5038d7SDag-Erling Smørgrav sec = 1; 52*7b5038d7SDag-Erling Smørgrav } else { 53*7b5038d7SDag-Erling Smørgrav if (bufpos + offset + 1 <= buf_len) { 54*7b5038d7SDag-Erling Smørgrav buf[bufpos+offset] = int8; 55*7b5038d7SDag-Erling Smørgrav int8 = 0; 56*7b5038d7SDag-Erling Smørgrav sec = 0; 57*7b5038d7SDag-Erling Smørgrav bufpos++; 58*7b5038d7SDag-Erling Smørgrav } else { 59*7b5038d7SDag-Erling Smørgrav error("Buffer too small in hexstr2bin"); 60*7b5038d7SDag-Erling Smørgrav } 61*7b5038d7SDag-Erling Smørgrav } 62*7b5038d7SDag-Erling Smørgrav } 63*7b5038d7SDag-Erling Smørgrav } 64*7b5038d7SDag-Erling Smørgrav return bufpos; 65*7b5038d7SDag-Erling Smørgrav } 66*7b5038d7SDag-Erling Smørgrav 67*7b5038d7SDag-Erling Smørgrav size_t 68*7b5038d7SDag-Erling Smørgrav packetbuffromfile(char *filename, uint8_t *wire) 69*7b5038d7SDag-Erling Smørgrav { 70*7b5038d7SDag-Erling Smørgrav FILE *fp = NULL; 71*7b5038d7SDag-Erling Smørgrav int c; 72*7b5038d7SDag-Erling Smørgrav 73*7b5038d7SDag-Erling Smørgrav /* stat hack 74*7b5038d7SDag-Erling Smørgrav * 0 = normal 75*7b5038d7SDag-Erling Smørgrav * 1 = comment (skip to end of line) 76*7b5038d7SDag-Erling Smørgrav * 2 = unprintable character found, read binary data directly 77*7b5038d7SDag-Erling Smørgrav */ 78*7b5038d7SDag-Erling Smørgrav int state = 0; 79*7b5038d7SDag-Erling Smørgrav uint8_t *hexbuf = xmalloc(LDNS_MAX_PACKETLEN); 80*7b5038d7SDag-Erling Smørgrav int hexbufpos = 0; 81*7b5038d7SDag-Erling Smørgrav size_t wirelen; 82*7b5038d7SDag-Erling Smørgrav 83*7b5038d7SDag-Erling Smørgrav if (strncmp(filename, "-", 2) == 0) { 84*7b5038d7SDag-Erling Smørgrav fp = stdin; 85*7b5038d7SDag-Erling Smørgrav } else { 86*7b5038d7SDag-Erling Smørgrav fp = fopen(filename, "r"); 87*7b5038d7SDag-Erling Smørgrav } 88*7b5038d7SDag-Erling Smørgrav if (fp == NULL) { 89*7b5038d7SDag-Erling Smørgrav perror("Unable to open file for reading"); 90*7b5038d7SDag-Erling Smørgrav xfree(hexbuf); 91*7b5038d7SDag-Erling Smørgrav return 0; 92*7b5038d7SDag-Erling Smørgrav } 93*7b5038d7SDag-Erling Smørgrav 94*7b5038d7SDag-Erling Smørgrav /*verbose("Opened %s\n", filename);*/ 95*7b5038d7SDag-Erling Smørgrav 96*7b5038d7SDag-Erling Smørgrav c = fgetc(fp); 97*7b5038d7SDag-Erling Smørgrav while (c != EOF && hexbufpos < LDNS_MAX_PACKETLEN) { 98*7b5038d7SDag-Erling Smørgrav if (state < 2 && !isascii(c)) { 99*7b5038d7SDag-Erling Smørgrav /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/ 100*7b5038d7SDag-Erling Smørgrav state = 2; 101*7b5038d7SDag-Erling Smørgrav } 102*7b5038d7SDag-Erling Smørgrav switch (state) { 103*7b5038d7SDag-Erling Smørgrav case 0: 104*7b5038d7SDag-Erling Smørgrav if ( (c >= '0' && c <= '9') || 105*7b5038d7SDag-Erling Smørgrav (c >= 'a' && c <= 'f') || 106*7b5038d7SDag-Erling Smørgrav (c >= 'A' && c <= 'F') ) 107*7b5038d7SDag-Erling Smørgrav { 108*7b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) c; 109*7b5038d7SDag-Erling Smørgrav hexbufpos++; 110*7b5038d7SDag-Erling Smørgrav } else if (c == ';') { 111*7b5038d7SDag-Erling Smørgrav state = 1; 112*7b5038d7SDag-Erling Smørgrav } else if (c == ' ' || c == '\t' || c == '\n') { 113*7b5038d7SDag-Erling Smørgrav /* skip whitespace */ 114*7b5038d7SDag-Erling Smørgrav } 115*7b5038d7SDag-Erling Smørgrav break; 116*7b5038d7SDag-Erling Smørgrav case 1: 117*7b5038d7SDag-Erling Smørgrav if (c == '\n' || c == EOF) { 118*7b5038d7SDag-Erling Smørgrav state = 0; 119*7b5038d7SDag-Erling Smørgrav } 120*7b5038d7SDag-Erling Smørgrav break; 121*7b5038d7SDag-Erling Smørgrav case 2: 122*7b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) c; 123*7b5038d7SDag-Erling Smørgrav hexbufpos++; 124*7b5038d7SDag-Erling Smørgrav break; 125*7b5038d7SDag-Erling Smørgrav default: 126*7b5038d7SDag-Erling Smørgrav warning("unknown state while reading %s", filename); 127*7b5038d7SDag-Erling Smørgrav xfree(hexbuf); 128*7b5038d7SDag-Erling Smørgrav return 0; 129*7b5038d7SDag-Erling Smørgrav break; 130*7b5038d7SDag-Erling Smørgrav } 131*7b5038d7SDag-Erling Smørgrav c = fgetc(fp); 132*7b5038d7SDag-Erling Smørgrav } 133*7b5038d7SDag-Erling Smørgrav 134*7b5038d7SDag-Erling Smørgrav if (c == EOF) { 135*7b5038d7SDag-Erling Smørgrav /* 136*7b5038d7SDag-Erling Smørgrav if (have_drill_opt && drill_opt->verbose) { 137*7b5038d7SDag-Erling Smørgrav verbose("END OF FILE REACHED\n"); 138*7b5038d7SDag-Erling Smørgrav if (state < 2) { 139*7b5038d7SDag-Erling Smørgrav verbose("read:\n"); 140*7b5038d7SDag-Erling Smørgrav verbose("%s\n", hexbuf); 141*7b5038d7SDag-Erling Smørgrav } else { 142*7b5038d7SDag-Erling Smørgrav verbose("Not printing wire because it contains non ascii data\n"); 143*7b5038d7SDag-Erling Smørgrav } 144*7b5038d7SDag-Erling Smørgrav } 145*7b5038d7SDag-Erling Smørgrav */ 146*7b5038d7SDag-Erling Smørgrav } 147*7b5038d7SDag-Erling Smørgrav if (hexbufpos >= LDNS_MAX_PACKETLEN) { 148*7b5038d7SDag-Erling Smørgrav /*verbose("packet size reached\n");*/ 149*7b5038d7SDag-Erling Smørgrav } 150*7b5038d7SDag-Erling Smørgrav 151*7b5038d7SDag-Erling Smørgrav /* lenient mode: length must be multiple of 2 */ 152*7b5038d7SDag-Erling Smørgrav if (hexbufpos % 2 != 0) { 153*7b5038d7SDag-Erling Smørgrav hexbuf[hexbufpos] = (uint8_t) '0'; 154*7b5038d7SDag-Erling Smørgrav hexbufpos++; 155*7b5038d7SDag-Erling Smørgrav } 156*7b5038d7SDag-Erling Smørgrav 157*7b5038d7SDag-Erling Smørgrav if (state < 2) { 158*7b5038d7SDag-Erling Smørgrav wirelen = hexstr2bin((char *) hexbuf, 159*7b5038d7SDag-Erling Smørgrav hexbufpos, 160*7b5038d7SDag-Erling Smørgrav wire, 161*7b5038d7SDag-Erling Smørgrav 0, 162*7b5038d7SDag-Erling Smørgrav LDNS_MAX_PACKETLEN); 163*7b5038d7SDag-Erling Smørgrav } else { 164*7b5038d7SDag-Erling Smørgrav memcpy(wire, hexbuf, (size_t) hexbufpos); 165*7b5038d7SDag-Erling Smørgrav wirelen = (size_t) hexbufpos; 166*7b5038d7SDag-Erling Smørgrav } 167*7b5038d7SDag-Erling Smørgrav if (fp != stdin) { 168*7b5038d7SDag-Erling Smørgrav fclose(fp); 169*7b5038d7SDag-Erling Smørgrav } 170*7b5038d7SDag-Erling Smørgrav xfree(hexbuf); 171*7b5038d7SDag-Erling Smørgrav return wirelen; 172*7b5038d7SDag-Erling Smørgrav } 173*7b5038d7SDag-Erling Smørgrav 174*7b5038d7SDag-Erling Smørgrav ldns_buffer * 175*7b5038d7SDag-Erling Smørgrav read_hex_buffer(char *filename) 176*7b5038d7SDag-Erling Smørgrav { 177*7b5038d7SDag-Erling Smørgrav uint8_t *wire; 178*7b5038d7SDag-Erling Smørgrav size_t wiresize; 179*7b5038d7SDag-Erling Smørgrav ldns_buffer *result_buffer = NULL; 180*7b5038d7SDag-Erling Smørgrav 181*7b5038d7SDag-Erling Smørgrav FILE *fp = NULL; 182*7b5038d7SDag-Erling Smørgrav 183*7b5038d7SDag-Erling Smørgrav if (strncmp(filename, "-", 2) != 0) { 184*7b5038d7SDag-Erling Smørgrav fp = fopen(filename, "r"); 185*7b5038d7SDag-Erling Smørgrav } else { 186*7b5038d7SDag-Erling Smørgrav fp = stdin; 187*7b5038d7SDag-Erling Smørgrav } 188*7b5038d7SDag-Erling Smørgrav 189*7b5038d7SDag-Erling Smørgrav if (fp == NULL) { 190*7b5038d7SDag-Erling Smørgrav perror(""); 191*7b5038d7SDag-Erling Smørgrav warning("Unable to open %s", filename); 192*7b5038d7SDag-Erling Smørgrav return NULL; 193*7b5038d7SDag-Erling Smørgrav } 194*7b5038d7SDag-Erling Smørgrav 195*7b5038d7SDag-Erling Smørgrav wire = xmalloc(LDNS_MAX_PACKETLEN); 196*7b5038d7SDag-Erling Smørgrav 197*7b5038d7SDag-Erling Smørgrav wiresize = packetbuffromfile(filename, wire); 198*7b5038d7SDag-Erling Smørgrav 199*7b5038d7SDag-Erling Smørgrav result_buffer = LDNS_MALLOC(ldns_buffer); 200*7b5038d7SDag-Erling Smørgrav ldns_buffer_new_frm_data(result_buffer, wire, wiresize); 201*7b5038d7SDag-Erling Smørgrav ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer)); 202*7b5038d7SDag-Erling Smørgrav 203*7b5038d7SDag-Erling Smørgrav xfree(wire); 204*7b5038d7SDag-Erling Smørgrav return result_buffer; 205*7b5038d7SDag-Erling Smørgrav } 206*7b5038d7SDag-Erling Smørgrav 207*7b5038d7SDag-Erling Smørgrav ldns_pkt * 208*7b5038d7SDag-Erling Smørgrav read_hex_pkt(char *filename) 209*7b5038d7SDag-Erling Smørgrav { 210*7b5038d7SDag-Erling Smørgrav uint8_t *wire; 211*7b5038d7SDag-Erling Smørgrav size_t wiresize; 212*7b5038d7SDag-Erling Smørgrav 213*7b5038d7SDag-Erling Smørgrav ldns_pkt *pkt = NULL; 214*7b5038d7SDag-Erling Smørgrav 215*7b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_ERR; 216*7b5038d7SDag-Erling Smørgrav 217*7b5038d7SDag-Erling Smørgrav wire = xmalloc(LDNS_MAX_PACKETLEN); 218*7b5038d7SDag-Erling Smørgrav 219*7b5038d7SDag-Erling Smørgrav wiresize = packetbuffromfile(filename, wire); 220*7b5038d7SDag-Erling Smørgrav 221*7b5038d7SDag-Erling Smørgrav if (wiresize > 0) { 222*7b5038d7SDag-Erling Smørgrav status = ldns_wire2pkt(&pkt, wire, wiresize); 223*7b5038d7SDag-Erling Smørgrav } 224*7b5038d7SDag-Erling Smørgrav 225*7b5038d7SDag-Erling Smørgrav xfree(wire); 226*7b5038d7SDag-Erling Smørgrav 227*7b5038d7SDag-Erling Smørgrav if (status == LDNS_STATUS_OK) { 228*7b5038d7SDag-Erling Smørgrav return pkt; 229*7b5038d7SDag-Erling Smørgrav } else { 230*7b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error parsing hex file: %s\n", 231*7b5038d7SDag-Erling Smørgrav ldns_get_errorstr_by_id(status)); 232*7b5038d7SDag-Erling Smørgrav return NULL; 233*7b5038d7SDag-Erling Smørgrav } 234*7b5038d7SDag-Erling Smørgrav } 235*7b5038d7SDag-Erling Smørgrav 236*7b5038d7SDag-Erling Smørgrav void 237*7b5038d7SDag-Erling Smørgrav dump_hex(const ldns_pkt *pkt, const char *filename) 238*7b5038d7SDag-Erling Smørgrav { 239*7b5038d7SDag-Erling Smørgrav uint8_t *wire; 240*7b5038d7SDag-Erling Smørgrav size_t size, i; 241*7b5038d7SDag-Erling Smørgrav FILE *fp; 242*7b5038d7SDag-Erling Smørgrav ldns_status status; 243*7b5038d7SDag-Erling Smørgrav 244*7b5038d7SDag-Erling Smørgrav fp = fopen(filename, "w"); 245*7b5038d7SDag-Erling Smørgrav 246*7b5038d7SDag-Erling Smørgrav if (fp == NULL) { 247*7b5038d7SDag-Erling Smørgrav error("Unable to open %s for writing", filename); 248*7b5038d7SDag-Erling Smørgrav return; 249*7b5038d7SDag-Erling Smørgrav } 250*7b5038d7SDag-Erling Smørgrav 251*7b5038d7SDag-Erling Smørgrav status = ldns_pkt2wire(&wire, pkt, &size); 252*7b5038d7SDag-Erling Smørgrav 253*7b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 254*7b5038d7SDag-Erling Smørgrav error("Unable to convert packet: error code %u", status); 255*7b5038d7SDag-Erling Smørgrav return; 256*7b5038d7SDag-Erling Smørgrav } 257*7b5038d7SDag-Erling Smørgrav 258*7b5038d7SDag-Erling Smørgrav fprintf(fp, "; 0"); 259*7b5038d7SDag-Erling Smørgrav for (i = 1; i < 20; i++) { 260*7b5038d7SDag-Erling Smørgrav fprintf(fp, " %2u", (unsigned int) i); 261*7b5038d7SDag-Erling Smørgrav } 262*7b5038d7SDag-Erling Smørgrav fprintf(fp, "\n"); 263*7b5038d7SDag-Erling Smørgrav fprintf(fp, ";--"); 264*7b5038d7SDag-Erling Smørgrav for (i = 1; i < 20; i++) { 265*7b5038d7SDag-Erling Smørgrav fprintf(fp, " --"); 266*7b5038d7SDag-Erling Smørgrav } 267*7b5038d7SDag-Erling Smørgrav fprintf(fp, "\n"); 268*7b5038d7SDag-Erling Smørgrav for (i = 0; i < size; i++) { 269*7b5038d7SDag-Erling Smørgrav if (i % 20 == 0 && i > 0) { 270*7b5038d7SDag-Erling Smørgrav fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i); 271*7b5038d7SDag-Erling Smørgrav } 272*7b5038d7SDag-Erling Smørgrav fprintf(fp, " %02x", (unsigned int)wire[i]); 273*7b5038d7SDag-Erling Smørgrav } 274*7b5038d7SDag-Erling Smørgrav fprintf(fp, "\n"); 275*7b5038d7SDag-Erling Smørgrav fclose(fp); 276*7b5038d7SDag-Erling Smørgrav } 277