Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/drill/work.c
39478 views
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
static 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
static 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
fclose(fp);
239
return;
240
}
241
242
fprintf(fp, "; 0");
243
for (i = 1; i < 20; i++) {
244
fprintf(fp, " %2u", (unsigned int) i);
245
}
246
fprintf(fp, "\n");
247
fprintf(fp, ";--");
248
for (i = 1; i < 20; i++) {
249
fprintf(fp, " --");
250
}
251
fprintf(fp, "\n");
252
for (i = 0; i < size; i++) {
253
if (i % 20 == 0 && i > 0) {
254
fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
255
}
256
fprintf(fp, " %02x", (unsigned int)wire[i]);
257
}
258
fprintf(fp, "\n");
259
fclose(fp);
260
LDNS_FREE(wire);
261
}
262
263