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