xref: /dflybsd-src/contrib/ldns/drill/work.c (revision 5340022ad92b5f5299ced3631de5d1bf90a7f749)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * work.c
3825eb42bSJan Lentfer  * Where all the hard work is done
4825eb42bSJan Lentfer  * (c) 2005 NLnet Labs
5825eb42bSJan Lentfer  *
6825eb42bSJan Lentfer  * See the file LICENSE for the license
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  */
9825eb42bSJan Lentfer 
10825eb42bSJan Lentfer #include "drill.h"
11825eb42bSJan Lentfer #include <ldns/ldns.h>
12825eb42bSJan Lentfer 
13825eb42bSJan Lentfer /**
14825eb42bSJan Lentfer  * Converts a hex string to binary data
15825eb42bSJan Lentfer  * len is the length of the string
16825eb42bSJan Lentfer  * buf is the buffer to store the result in
17825eb42bSJan Lentfer  * offset is the starting position in the result buffer
18825eb42bSJan Lentfer  *
19825eb42bSJan Lentfer  * This function returns the length of the result
20825eb42bSJan Lentfer  */
21*5340022aSzrj static size_t
hexstr2bin(char * hexstr,int len,uint8_t * buf,size_t offset,size_t buf_len)22825eb42bSJan Lentfer hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
23825eb42bSJan Lentfer {
24825eb42bSJan Lentfer 	char c;
25825eb42bSJan Lentfer 	int i;
26825eb42bSJan Lentfer 	uint8_t int8 = 0;
27825eb42bSJan Lentfer 	int sec = 0;
28825eb42bSJan Lentfer 	size_t bufpos = 0;
29825eb42bSJan Lentfer 
30825eb42bSJan Lentfer 	if (len % 2 != 0) {
31825eb42bSJan Lentfer 		return 0;
32825eb42bSJan Lentfer 	}
33825eb42bSJan Lentfer 
34825eb42bSJan Lentfer 	for (i=0; i<len; i++) {
35825eb42bSJan Lentfer 		c = hexstr[i];
36825eb42bSJan Lentfer 
37825eb42bSJan Lentfer 		/* case insensitive, skip spaces */
38825eb42bSJan Lentfer 		if (c != ' ') {
39825eb42bSJan Lentfer 			if (c >= '0' && c <= '9') {
40825eb42bSJan Lentfer 				int8 += c & 0x0f;
41825eb42bSJan Lentfer 			} else if (c >= 'a' && c <= 'z') {
42825eb42bSJan Lentfer 				int8 += (c & 0x0f) + 9;
43825eb42bSJan Lentfer 			} else if (c >= 'A' && c <= 'Z') {
44825eb42bSJan Lentfer 				int8 += (c & 0x0f) + 9;
45825eb42bSJan Lentfer 			} else {
46825eb42bSJan Lentfer 				return 0;
47825eb42bSJan Lentfer 			}
48825eb42bSJan Lentfer 
49825eb42bSJan Lentfer 			if (sec == 0) {
50825eb42bSJan Lentfer 				int8 = int8 << 4;
51825eb42bSJan Lentfer 				sec = 1;
52825eb42bSJan Lentfer 			} else {
53825eb42bSJan Lentfer 				if (bufpos + offset + 1 <= buf_len) {
54825eb42bSJan Lentfer 					buf[bufpos+offset] = int8;
55825eb42bSJan Lentfer 					int8 = 0;
56825eb42bSJan Lentfer 					sec = 0;
57825eb42bSJan Lentfer 					bufpos++;
58825eb42bSJan Lentfer 				} else {
59825eb42bSJan Lentfer 					error("Buffer too small in hexstr2bin");
60825eb42bSJan Lentfer 				}
61825eb42bSJan Lentfer 			}
62825eb42bSJan Lentfer 		}
63825eb42bSJan Lentfer         }
64825eb42bSJan Lentfer         return bufpos;
65825eb42bSJan Lentfer }
66825eb42bSJan Lentfer 
67*5340022aSzrj static size_t
packetbuffromfile(char * filename,uint8_t * wire)68825eb42bSJan Lentfer packetbuffromfile(char *filename, uint8_t *wire)
69825eb42bSJan Lentfer {
70825eb42bSJan Lentfer 	FILE *fp = NULL;
71825eb42bSJan Lentfer 	int c;
72825eb42bSJan Lentfer 
73825eb42bSJan Lentfer 	/* stat hack
74825eb42bSJan Lentfer 	 * 0 = normal
75825eb42bSJan Lentfer 	 * 1 = comment (skip to end of line)
76825eb42bSJan Lentfer 	 * 2 = unprintable character found, read binary data directly
77825eb42bSJan Lentfer 	 */
78825eb42bSJan Lentfer 	int state = 0;
79825eb42bSJan Lentfer 	uint8_t *hexbuf = xmalloc(LDNS_MAX_PACKETLEN);
80825eb42bSJan Lentfer 	int hexbufpos = 0;
81825eb42bSJan Lentfer 	size_t wirelen;
82825eb42bSJan Lentfer 
83825eb42bSJan Lentfer 	if (strncmp(filename, "-", 2) == 0) {
84825eb42bSJan Lentfer 		fp = stdin;
85825eb42bSJan Lentfer 	} else {
86825eb42bSJan Lentfer 		fp = fopen(filename, "r");
87825eb42bSJan Lentfer 	}
88825eb42bSJan Lentfer 	if (fp == NULL) {
89825eb42bSJan Lentfer 		perror("Unable to open file for reading");
90825eb42bSJan Lentfer 		xfree(hexbuf);
91825eb42bSJan Lentfer 		return 0;
92825eb42bSJan Lentfer 	}
93825eb42bSJan Lentfer 
94825eb42bSJan Lentfer 	/*verbose("Opened %s\n", filename);*/
95825eb42bSJan Lentfer 
96825eb42bSJan Lentfer 	c = fgetc(fp);
97825eb42bSJan Lentfer 	while (c != EOF && hexbufpos < LDNS_MAX_PACKETLEN) {
98825eb42bSJan Lentfer 		if (state < 2 && !isascii(c)) {
99825eb42bSJan Lentfer 			/*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
100825eb42bSJan Lentfer 			state = 2;
101825eb42bSJan Lentfer 		}
102825eb42bSJan Lentfer 		switch (state) {
103825eb42bSJan Lentfer 			case 0:
104825eb42bSJan Lentfer 				if (	(c >= '0' && c <= '9') ||
105825eb42bSJan Lentfer 					(c >= 'a' && c <= 'f') ||
106825eb42bSJan Lentfer 					(c >= 'A' && c <= 'F') )
107825eb42bSJan Lentfer 				{
108825eb42bSJan Lentfer 					hexbuf[hexbufpos] = (uint8_t) c;
109825eb42bSJan Lentfer 					hexbufpos++;
110825eb42bSJan Lentfer 				} else if (c == ';') {
111825eb42bSJan Lentfer 					state = 1;
112825eb42bSJan Lentfer 				} else if (c == ' ' || c == '\t' || c == '\n') {
113825eb42bSJan Lentfer 					/* skip whitespace */
114825eb42bSJan Lentfer 				}
115825eb42bSJan Lentfer 				break;
116825eb42bSJan Lentfer 			case 1:
117825eb42bSJan Lentfer 				if (c == '\n' || c == EOF) {
118825eb42bSJan Lentfer 					state = 0;
119825eb42bSJan Lentfer 				}
120825eb42bSJan Lentfer 				break;
121825eb42bSJan Lentfer 			case 2:
122825eb42bSJan Lentfer 				hexbuf[hexbufpos] = (uint8_t) c;
123825eb42bSJan Lentfer 				hexbufpos++;
124825eb42bSJan Lentfer 				break;
125825eb42bSJan Lentfer 		}
126825eb42bSJan Lentfer 		c = fgetc(fp);
127825eb42bSJan Lentfer 	}
128825eb42bSJan Lentfer 
129825eb42bSJan Lentfer 	if (c == EOF) {
130825eb42bSJan Lentfer 		/*
131825eb42bSJan Lentfer 		if (have_drill_opt && drill_opt->verbose) {
132825eb42bSJan Lentfer 			verbose("END OF FILE REACHED\n");
133825eb42bSJan Lentfer 			if (state < 2) {
134825eb42bSJan Lentfer 				verbose("read:\n");
135825eb42bSJan Lentfer 				verbose("%s\n", hexbuf);
136825eb42bSJan Lentfer 			} else {
137825eb42bSJan Lentfer 				verbose("Not printing wire because it contains non ascii data\n");
138825eb42bSJan Lentfer 			}
139825eb42bSJan Lentfer 		}
140825eb42bSJan Lentfer 		*/
141825eb42bSJan Lentfer 	}
142825eb42bSJan Lentfer 	if (hexbufpos >= LDNS_MAX_PACKETLEN) {
143825eb42bSJan Lentfer 		/*verbose("packet size reached\n");*/
144825eb42bSJan Lentfer 	}
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer 	/* lenient mode: length must be multiple of 2 */
147825eb42bSJan Lentfer 	if (hexbufpos % 2 != 0) {
148825eb42bSJan Lentfer 		hexbuf[hexbufpos] = (uint8_t) '0';
149825eb42bSJan Lentfer 		hexbufpos++;
150825eb42bSJan Lentfer 	}
151825eb42bSJan Lentfer 
152825eb42bSJan Lentfer 	if (state < 2) {
153825eb42bSJan Lentfer 		wirelen = hexstr2bin((char *) hexbuf,
154825eb42bSJan Lentfer 						 hexbufpos,
155825eb42bSJan Lentfer 						 wire,
156825eb42bSJan Lentfer 						 0,
157825eb42bSJan Lentfer 						 LDNS_MAX_PACKETLEN);
158825eb42bSJan Lentfer 	} else {
159825eb42bSJan Lentfer 		memcpy(wire, hexbuf, (size_t) hexbufpos);
160825eb42bSJan Lentfer 		wirelen = (size_t) hexbufpos;
161825eb42bSJan Lentfer 	}
162825eb42bSJan Lentfer 	if (fp != stdin) {
163825eb42bSJan Lentfer 		fclose(fp);
164825eb42bSJan Lentfer 	}
165825eb42bSJan Lentfer 	xfree(hexbuf);
166825eb42bSJan Lentfer 	return wirelen;
167825eb42bSJan Lentfer }
168825eb42bSJan Lentfer 
169825eb42bSJan Lentfer ldns_buffer *
read_hex_buffer(char * filename)170825eb42bSJan Lentfer read_hex_buffer(char *filename)
171825eb42bSJan Lentfer {
172825eb42bSJan Lentfer 	uint8_t *wire;
173825eb42bSJan Lentfer 	size_t wiresize;
174825eb42bSJan Lentfer 	ldns_buffer *result_buffer = NULL;
175825eb42bSJan Lentfer 
176825eb42bSJan Lentfer 
177825eb42bSJan Lentfer 	wire = xmalloc(LDNS_MAX_PACKETLEN);
178825eb42bSJan Lentfer 
179825eb42bSJan Lentfer 	wiresize = packetbuffromfile(filename, wire);
180825eb42bSJan Lentfer 
181825eb42bSJan Lentfer 	result_buffer = LDNS_MALLOC(ldns_buffer);
182825eb42bSJan Lentfer 	ldns_buffer_new_frm_data(result_buffer, wire, wiresize);
183825eb42bSJan Lentfer 	ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer));
184825eb42bSJan Lentfer 	xfree(wire);
185d1b2b5caSJohn Marino 
186825eb42bSJan Lentfer 	return result_buffer;
187825eb42bSJan Lentfer }
188825eb42bSJan Lentfer 
189825eb42bSJan Lentfer ldns_pkt *
read_hex_pkt(char * filename)190825eb42bSJan Lentfer read_hex_pkt(char *filename)
191825eb42bSJan Lentfer {
192825eb42bSJan Lentfer 	uint8_t *wire;
193825eb42bSJan Lentfer 	size_t wiresize;
194825eb42bSJan Lentfer 
195825eb42bSJan Lentfer 	ldns_pkt *pkt = NULL;
196825eb42bSJan Lentfer 
197825eb42bSJan Lentfer 	ldns_status status = LDNS_STATUS_ERR;
198825eb42bSJan Lentfer 
199825eb42bSJan Lentfer 	wire = xmalloc(LDNS_MAX_PACKETLEN);
200825eb42bSJan Lentfer 
201825eb42bSJan Lentfer 	wiresize = packetbuffromfile(filename, wire);
202825eb42bSJan Lentfer 
203825eb42bSJan Lentfer 	if (wiresize > 0) {
204825eb42bSJan Lentfer 		status = ldns_wire2pkt(&pkt, wire, wiresize);
205825eb42bSJan Lentfer 	}
206825eb42bSJan Lentfer 
207825eb42bSJan Lentfer 	xfree(wire);
208825eb42bSJan Lentfer 
209825eb42bSJan Lentfer 	if (status == LDNS_STATUS_OK) {
210825eb42bSJan Lentfer 		return pkt;
211825eb42bSJan Lentfer 	} else {
212825eb42bSJan Lentfer 		fprintf(stderr, "Error parsing hex file: %s\n",
213825eb42bSJan Lentfer 			   ldns_get_errorstr_by_id(status));
214825eb42bSJan Lentfer 		return NULL;
215825eb42bSJan Lentfer 	}
216825eb42bSJan Lentfer }
217825eb42bSJan Lentfer 
218825eb42bSJan Lentfer void
dump_hex(const ldns_pkt * pkt,const char * filename)219825eb42bSJan Lentfer dump_hex(const ldns_pkt *pkt, const char *filename)
220825eb42bSJan Lentfer {
221d1b2b5caSJohn Marino 	uint8_t *wire = NULL;
222825eb42bSJan Lentfer 	size_t size, i;
223825eb42bSJan Lentfer 	FILE *fp;
224825eb42bSJan Lentfer 	ldns_status status;
225825eb42bSJan Lentfer 
226825eb42bSJan Lentfer 	fp = fopen(filename, "w");
227825eb42bSJan Lentfer 
228825eb42bSJan Lentfer 	if (fp == NULL) {
229825eb42bSJan Lentfer 		error("Unable to open %s for writing", filename);
230825eb42bSJan Lentfer 		return;
231825eb42bSJan Lentfer 	}
232825eb42bSJan Lentfer 
233825eb42bSJan Lentfer 	status = ldns_pkt2wire(&wire, pkt, &size);
234825eb42bSJan Lentfer 
235825eb42bSJan Lentfer 	if (status != LDNS_STATUS_OK) {
236825eb42bSJan Lentfer 		error("Unable to convert packet: error code %u", status);
237d1b2b5caSJohn Marino 		LDNS_FREE(wire);
238*5340022aSzrj 		fclose(fp);
239825eb42bSJan Lentfer 		return;
240825eb42bSJan Lentfer 	}
241825eb42bSJan Lentfer 
242825eb42bSJan Lentfer 	fprintf(fp, "; 0");
243825eb42bSJan Lentfer 	for (i = 1; i < 20; i++) {
244825eb42bSJan Lentfer 		fprintf(fp, " %2u", (unsigned int) i);
245825eb42bSJan Lentfer 	}
246825eb42bSJan Lentfer 	fprintf(fp, "\n");
247825eb42bSJan Lentfer 	fprintf(fp, ";--");
248825eb42bSJan Lentfer 	for (i = 1; i < 20; i++) {
249825eb42bSJan Lentfer 		fprintf(fp, " --");
250825eb42bSJan Lentfer 	}
251825eb42bSJan Lentfer 	fprintf(fp, "\n");
252825eb42bSJan Lentfer 	for (i = 0; i < size; i++) {
253825eb42bSJan Lentfer 		if (i % 20 == 0 && i > 0) {
254825eb42bSJan Lentfer 			fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
255825eb42bSJan Lentfer 		}
256825eb42bSJan Lentfer 		fprintf(fp, " %02x", (unsigned int)wire[i]);
257825eb42bSJan Lentfer 	}
258825eb42bSJan Lentfer 	fprintf(fp, "\n");
259825eb42bSJan Lentfer 	fclose(fp);
260d1b2b5caSJohn Marino 	LDNS_FREE(wire);
261825eb42bSJan Lentfer }
262