aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-12 04:09:09 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-12 04:09:09 +0000
commitddbf3bf35ffd70e7105f4cf8fe8aa81b3c7667e2 (patch)
tree304f23a0e40292b965486ca8564636549d4d2ef2
parent135cecbbcee8bfe10ef7f1edd8e485a7cf86be84 (diff)
downloadbusybox-w32-ddbf3bf35ffd70e7105f4cf8fe8aa81b3c7667e2.tar.gz
busybox-w32-ddbf3bf35ffd70e7105f4cf8fe8aa81b3c7667e2.tar.bz2
busybox-w32-ddbf3bf35ffd70e7105f4cf8fe8aa81b3c7667e2.zip
dnsd: fix a number of bugs. Ideas by Ming-Ching Tiew (mctiew AT yahoo.com)
function old new delta undot - 42 +42 dnsd_main 1394 1213 -181 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 42/-181) Total: -139 bytes
-rw-r--r--networking/dnsd.c488
1 files changed, 325 insertions, 163 deletions
diff --git a/networking/dnsd.c b/networking/dnsd.c
index f95ba6b40..4f980dccd 100644
--- a/networking/dnsd.c
+++ b/networking/dnsd.c
@@ -24,73 +24,63 @@
24#define DEBUG 0 24#define DEBUG 0
25 25
26enum { 26enum {
27 MAX_HOST_LEN = 16, // longest host name allowed is 15 27 /* Can tweak this */
28 IP_STRING_LEN = 18, // .xxx.xxx.xxx.xxx\0 28 DEFAULT_TTL = 120,
29 29
30//must be strlen('.in-addr.arpa') larger than IP_STRING_LEN 30/* Cannot get bigger packets than 512 per RFC1035.
31 MAX_NAME_LEN = (IP_STRING_LEN + 13), 31 * In practice this can be set considerably smaller:
32 32 * Length of response packet is header (12B) + 2*type(4B) + 2*class(4B) +
33/* Cannot get bigger packets than 512 per RFC1035 33 * ttl(4B) + rlen(2B) + r (MAX_NAME_LEN = 21B) +
34 In practice this can be set considerably smaller: 34 * 2*querystring (2 MAX_NAME_LEN = 42B), all together 90 Bytes
35 Length of response packet is header (12B) + 2*type(4B) + 2*class(4B) + 35 */
36 ttl(4B) + rlen(2B) + r (MAX_NAME_LEN =21B) +
37 2*querystring (2 MAX_NAME_LEN= 42B), all together 90 Byte
38*/
39 MAX_PACK_LEN = 512, 36 MAX_PACK_LEN = 512,
40 37 IP_STRING_LEN = sizeof(".xxx.xxx.xxx.xxx"),
41 DEFAULT_TTL = 30, // increase this when not testing? 38 MAX_NAME_LEN = IP_STRING_LEN - 1 + sizeof(".in-addr.arpa"),
42
43 REQ_A = 1, 39 REQ_A = 1,
44 REQ_PTR = 12 40 REQ_PTR = 12,
45}; 41};
46 42
47struct dns_head { // the message from client and first part of response mag 43/* the message from client and first part of response msg */
44struct dns_head {
48 uint16_t id; 45 uint16_t id;
49 uint16_t flags; 46 uint16_t flags;
50 uint16_t nquer; // accepts 0 47 uint16_t nquer;
51 uint16_t nansw; // 1 in response 48 uint16_t nansw;
52 uint16_t nauth; // 0 49 uint16_t nauth;
53 uint16_t nadd; // 0 50 uint16_t nadd;
54}; 51};
55struct dns_prop { 52struct dns_prop {
56 uint16_t type; 53 uint16_t type;
57 uint16_t class; 54 uint16_t class;
58}; 55};
59struct dns_entry { // element of known name, ip address and reversed ip address 56/* element of known name, ip address and reversed ip address */
57struct dns_entry {
60 struct dns_entry *next; 58 struct dns_entry *next;
61 char ip[IP_STRING_LEN]; // dotted decimal IP 59 uint32_t ip;
62 char rip[IP_STRING_LEN]; // length decimal reversed IP 60 char rip[IP_STRING_LEN]; /* length decimal reversed IP */
63 char name[MAX_HOST_LEN]; 61 char name[1];
64}; 62};
65 63
66#define OPT_verbose (option_mask32) 64#define OPT_verbose (option_mask32)
67 65
68 66
69/* 67/*
70 * Convert host name from C-string to dns length/string.
71 */
72static void convname(char *a, uint8_t *q)
73{
74 int i = (q[0] == '.') ? 0 : 1;
75 for (; i < MAX_HOST_LEN-1 && *q; i++, q++)
76 a[i] = tolower(*q);
77 a[0] = i - 1;
78 a[i] = 0;
79}
80
81/*
82 * Insert length of substrings instead of dots 68 * Insert length of substrings instead of dots
83 */ 69 */
84static void undot(uint8_t *rip) 70static void undot(char *rip)
85{ 71{
86 int i = 0, s = 0; 72 int i = 0;
73 int s = 0;
74
87 while (rip[i]) 75 while (rip[i])
88 i++; 76 i++;
89 for (--i; i >= 0; i--) { 77 for (--i; i >= 0; i--) {
90 if (rip[i] == '.') { 78 if (rip[i] == '.') {
91 rip[i] = s; 79 rip[i] = s;
92 s = 0; 80 s = 0;
93 } else s++; 81 } else {
82 s++;
83 }
94 } 84 }
95} 85}
96 86
@@ -101,199 +91,369 @@ static struct dns_entry *parse_conf_file(const char *fileconf)
101{ 91{
102 char *token[2]; 92 char *token[2];
103 parser_t *parser; 93 parser_t *parser;
104 struct dns_entry *m, *prev, *conf_data; 94 struct dns_entry *m, *conf_data;
95 struct dns_entry **nextp;
96
97 conf_data = NULL;
98 nextp = &conf_data;
105 99
106 prev = conf_data = NULL;
107 parser = config_open(fileconf); 100 parser = config_open(fileconf);
108 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) { 101 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
109 unsigned a, b, c, d; 102 struct in_addr ip;
110 /* 103 uint32_t v32;
111 * Assumes all host names are lower case only
112 * Hostnames with more than one label are not handled correctly.
113 * Presently the dot is copied into name without
114 * converting to a length/string substring for that label.
115 */
116// if (!token[1] || sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4)
117 if (sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4)
118 continue;
119 104
120 m = xzalloc(sizeof(*m)); 105 if (inet_aton(token[1], &ip) == 0) {
121 /*m->next = NULL;*/ 106 bb_error_msg("error at line %u, skipping", parser->lineno);
122 sprintf(m->ip, ".%u.%u.%u.%u"+1, a, b, c, d); 107 continue;
123 sprintf(m->rip, ".%u.%u.%u.%u", d, c, b, a); 108 }
124 undot((uint8_t*)m->rip);
125 convname(m->name, (uint8_t*)token[0]);
126 109
127 if (OPT_verbose) 110 if (OPT_verbose)
128 bb_error_msg("name:%s, ip:%s", &(m->name[1]), m->ip); 111 bb_error_msg("name:%s, ip:%s", token[0], token[1]);
129 112
130 if (prev == NULL) 113 /* sizeof(*m) includes 1 byte for m->name[0] */
131 conf_data = m; 114 m = xzalloc(sizeof(*m) + strlen(token[0]) + 1);
132 else 115 /*m->next = NULL;*/
133 prev->next = m; 116 *nextp = m;
134 prev = m; 117 nextp = &m->next;
118
119 m->name[0] = '.';
120 strcpy(m->name + 1, token[0]);
121 undot(m->name);
122 m->ip = ip.s_addr; /* in network order */
123 v32 = ntohl(m->ip);
124 /* inverted order */
125 sprintf(m->rip, ".%u.%u.%u.%u",
126 (uint8_t)(v32),
127 (uint8_t)(v32 >> 8),
128 (uint8_t)(v32 >> 16),
129 (v32 >> 24)
130 );
131 undot(m->rip);
135 } 132 }
136 config_close(parser); 133 config_close(parser);
137 return conf_data; 134 return conf_data;
138} 135}
139 136
140/* 137/*
141 * Look query up in dns records and return answer if found 138 * Look query up in dns records and return answer if found.
142 * qs is the query string, first byte the string length 139 * qs is the query string.
143 */ 140 */
144static int table_lookup(struct dns_entry *d, uint16_t type, uint8_t *as, uint8_t *qs) 141static int table_lookup(uint8_t *as, struct dns_entry *d, uint16_t type, uint8_t *qs)
145{ 142{
146 int i; 143 while (d) {
147 144 unsigned len = d->name[0];
148 do { 145 /* d->name[len] is the last (non NUL) char */
149#if DEBUG 146#if DEBUG
150 char *p, *q; 147 char *p, *q;
151 q = (char *)&(qs[1]); 148 q = (char *)&(qs[1]);
152 p = &(d->name[1]); 149 p = &(d->name[1]);
153 fprintf(stderr, "\n%s: %d/%d p:%s q:%s %d", 150 fprintf(stderr, "%d/%d p:%s q:%s %d\n",
154 __FUNCTION__, (int)strlen(p), (int)(d->name[0]), 151 (int)strlen(p), len,
155 p, q, (int)strlen(q)); 152 p, q, (int)strlen(q)
153 );
156#endif 154#endif
157 if (type == REQ_A) { 155 if (type == htons(REQ_A)) {
158 /* search by host name */ 156 /* search by host name */
159 for (i = 1; i <= (int)(d->name[0]); i++) 157 if (len != 1 || d->name[1] != '*') {
160 if (tolower(qs[i]) != d->name[i]) 158 if (strcasecmp(d->name, (char*)qs) != 0)
161 break; 159 goto next;
162 if (i > (int)(d->name[0]) 160 }
163 || (d->name[0] == 1 && d->name[1] == '*') 161 move_to_unaligned32((uint32_t *)as, d->ip);
164 ) {
165 strcpy((char *)as, d->ip);
166#if DEBUG 162#if DEBUG
167 fprintf(stderr, " OK as:%s\n", as); 163 fprintf(stderr, "OK as:%x\n", (int)d->ip);
168#endif 164#endif
169 return 0; 165 return 0;
170 }
171 } else if (type == REQ_PTR) {
172 /* search by IP-address */
173 if ((d->name[0] != 1 || d->name[1] != '*')
174 && !strncmp(d->rip + 1, (char*)qs + 1, strlen(d->rip)-1)
175 ) {
176 strcpy((char *)as, d->name);
177 return 0;
178 }
179 } 166 }
167 /* search by IP-address */
168 if ((len != 1 || d->name[1] != '*')
169 /* assume (do not check) that qs ends in ".in-addr.arpa" */
170 && strncmp(d->rip, (char*)qs, strlen(d->rip)) == 0
171 ) {
172 strcpy((char *)as, d->name);
173#if DEBUG
174 fprintf(stderr, "OK as:%s\n", as);
175#endif
176 return 0;
177 }
178 next:
180 d = d->next; 179 d = d->next;
181 } while (d); 180 }
181
182 return -1; 182 return -1;
183} 183}
184 184
185/* 185/*
186 * Decode message and generate answer 186 * Decode message and generate answer
187 */ 187 */
188/* RFC 1035
189...
190Whenever an octet represents a numeric quantity, the left most bit
191in the diagram is the high order or most significant bit.
192That is, the bit labeled 0 is the most significant bit.
193...
194
1954.1.1. Header section format
196 1 1 1 1 1 1
197 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
198 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
199 | ID |
200 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
201 |QR| OPCODE |AA|TC|RD|RA| Z | RCODE |
202 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
203 | QDCOUNT |
204 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
205 | ANCOUNT |
206 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
207 | NSCOUNT |
208 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
209 | ARCOUNT |
210 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
211ID 16 bit random identifier assigned by query.
212 Used to match query/response.
213QR message is a query (0), or a response (1).
214OPCODE 0 standard query (QUERY)
215 1 inverse query (IQUERY)
216 2 server status request (STATUS)
217AA Authoritative Answer - this bit is valid in responses,
218 and specifies that the responding name server is an
219 authority for the domain name in question section.
220 Note that the contents of the answer section may have
221 multiple owner names because of aliases. The AA bit
222 corresponds to the name which matches the query name, or
223 the first owner name in the answer section.
224TC TrunCation - specifies that this message was truncated.
225RD Recursion Desired - this bit may be set in a query and
226 is copied into the response. If RD is set, it directs
227 the name server to pursue the query recursively.
228 Recursive query support is optional.
229RA Recursion Available - this be is set or cleared in a
230 response, and denotes whether recursive query support is
231 available in the name server.
232Z Reserved for future use. Must be zero.
233RCODE Response code.
234 0 No error condition
235 1 Format error
236 2 Server failure - The name server was
237 unable to process this query due to a
238 problem with the name server.
239 3 Name Error - Meaningful only for
240 responses from an authoritative name
241 server, this code signifies that the
242 domain name referenced in the query does
243 not exist.
244 4 Not Implemented.
245 5 Refused.
246QDCOUNT number of entries in the question section.
247ANCOUNT number of resource records in the answer section.
248NSCOUNT number of name server resource records in the authority records section.
249ARCOUNT number of resource records in the additional records section.
250
2514.1.2. Question section format
252
253The section contains QDCOUNT (usually 1) entries, each of the following format:
254 1 1 1 1 1 1
255 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
256 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
257 / QNAME /
258 / /
259 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
260 | QTYPE |
261 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
262 | QCLASS |
263 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
264QNAME a domain name represented as a sequence of labels, where
265 each label consists of a length octet followed by that
266 number of octets. The domain name terminates with the
267 zero length octet for the null label of the root. Note
268 that this field may be an odd number of octets; no
269 padding is used.
270QTYPE a two octet type of the query.
271 1 a host address [REQ_A const]
272 2 an authoritative name server
273 3 a mail destination (Obsolete - use MX)
274 4 a mail forwarder (Obsolete - use MX)
275 5 the canonical name for an alias
276 6 marks the start of a zone of authority
277 7 a mailbox domain name (EXPERIMENTAL)
278 8 a mail group member (EXPERIMENTAL)
279 9 a mail rename domain name (EXPERIMENTAL)
280 10 a null RR (EXPERIMENTAL)
281 11 a well known service description
282 12 a domain name pointer [REQ_PTR const]
283 13 host information
284 14 mailbox or mail list information
285 15 mail exchange
286 16 text strings
287 0x1c IPv6?
288 252 a request for a transfer of an entire zone
289 253 a request for mailbox-related records (MB, MG or MR)
290 254 a request for mail agent RRs (Obsolete - see MX)
291 255 a request for all records
292QCLASS a two octet code that specifies the class of the query.
293 1 the Internet
294 (others are historic only)
295 255 any class
296
2974.1.3. Resource record format
298
299The answer, authority, and additional sections all share the same
300format: a variable number of resource records, where the number of
301records is specified in the corresponding count field in the header.
302Each resource record has the following format:
303 1 1 1 1 1 1
304 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
305 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
306 / /
307 / NAME /
308 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
309 | TYPE |
310 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
311 | CLASS |
312 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
313 | TTL |
314 | |
315 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
316 | RDLENGTH |
317 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
318 / RDATA /
319 / /
320 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
321NAME a domain name to which this resource record pertains.
322TYPE two octets containing one of the RR type codes. This
323 field specifies the meaning of the data in the RDATA
324 field.
325CLASS two octets which specify the class of the data in the
326 RDATA field.
327TTL a 32 bit unsigned integer that specifies the time
328 interval (in seconds) that the resource record may be
329 cached before it should be discarded. Zero values are
330 interpreted to mean that the RR can only be used for the
331 transaction in progress, and should not be cached.
332RDLENGTH an unsigned 16 bit integer that specifies the length in
333 octets of the RDATA field.
334RDATA a variable length string of octets that describes the
335 resource. The format of this information varies
336 according to the TYPE and CLASS of the resource record.
337 For example, if the TYPE is A and the CLASS is IN,
338 the RDATA field is a 4 octet ARPA Internet address.
339
3404.1.4. Message compression
341
342In order to reduce the size of messages, the domain system utilizes a
343compression scheme which eliminates the repetition of domain names in a
344message. In this scheme, an entire domain name or a list of labels at
345the end of a domain name is replaced with a pointer to a prior occurance
346of the same name.
347
348The pointer takes the form of a two octet sequence:
349 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
350 | 1 1| OFFSET |
351 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
352The first two bits are ones. This allows a pointer to be distinguished
353from a label, since the label must begin with two zero bits because
354labels are restricted to 63 octets or less. The OFFSET field specifies
355an offset from the start of the message (i.e., the first octet
356of the ID field in the domain header).
357A zero offset specifies the first byte of the ID field, etc.
358
359The compression scheme allows a domain name in a message to be
360represented as either:
361 - a sequence of labels ending in a zero octet
362 - a pointer
363 - a sequence of labels ending with a pointer
364 */
188static int process_packet(struct dns_entry *conf_data, uint32_t conf_ttl, uint8_t *buf) 365static int process_packet(struct dns_entry *conf_data, uint32_t conf_ttl, uint8_t *buf)
189{ 366{
190 uint8_t answstr[MAX_NAME_LEN + 1]; 367 uint8_t answstr[MAX_NAME_LEN + 1];
191 struct dns_head *head; 368 struct dns_head *head;
192 struct dns_prop *qprop; 369 struct dns_prop *unaligned_qprop;
193 uint8_t *from, *answb; 370 uint8_t *from, *answb;
194 uint16_t outr_rlen; 371 uint16_t outr_rlen;
195 uint16_t outr_flags; 372 uint16_t outr_flags;
196 uint16_t flags; 373 uint16_t type;
197 int lookup_result, type, packet_len; 374 uint16_t class;
198 int querystr_len; 375 int querystr_len;
199 376
200 answstr[0] = '\0'; 377 answstr[0] = '\0';
201 378
202 head = (struct dns_head *)buf; 379 head = (struct dns_head *)buf;
203 if (head->nquer == 0) { 380 if (head->nquer == 0) {
204 bb_error_msg("no queries"); 381 bb_error_msg("packet has 0 queries, ignored");
205 return -1; 382 return -1;
206 } 383 }
207 384
208 if (head->flags & 0x8000) { 385 if (head->flags & htons(0x8000)) { /* QR bit */
209 bb_error_msg("ignoring response packet"); 386 bb_error_msg("response packet, ignored");
210 return -1; 387 return -1;
211 } 388 }
212 389
213 from = (void *)&head[1]; // start of query string 390 /* start of query string */
214//FIXME: strlen of untrusted data??! 391 from = (void *)(head + 1);
215 querystr_len = strlen((char *)from) + 1 + sizeof(struct dns_prop); 392 /* caller guarantees strlen is <= MAX_PACK_LEN */
216 answb = from + querystr_len; // where to append answer block 393 querystr_len = strlen((char *)from) + 1;
394 /* may be unaligned! */
395 unaligned_qprop = (void *)(from + querystr_len);
396 /* where to append answer block */
397 answb = (void *)(unaligned_qprop + 1);
217 398
218 outr_rlen = 0; 399 outr_rlen = 0;
219 outr_flags = 0; 400 /* QR = 1 "response", RCODE = 4 "Not Implemented" */
220 401 outr_flags = htons(0x8000 | 4);
221 qprop = (struct dns_prop *)(answb - 4);
222 type = ntohs(qprop->type);
223 402
224 // only let REQ_A and REQ_PTR pass 403 move_from_unaligned16(type, &unaligned_qprop->type);
225 if (!(type == REQ_A || type == REQ_PTR)) { 404 if (type != htons(REQ_A) && type != htons(REQ_PTR)) {
226 goto empty_packet; /* we can't handle the query type */ 405 /* we can't handle the query type */
406 goto empty_packet;
227 } 407 }
228 408 move_from_unaligned16(class, &unaligned_qprop->class);
229 if (ntohs(qprop->class) != 1 /* class INET */ ) { 409 if (class != htons(1)) { /* not class INET? */
230 outr_flags = 4; /* not supported */
231 goto empty_packet; 410 goto empty_packet;
232 } 411 }
233 /* we only support standard queries */ 412 /* OPCODE != 0 "standard query" ? */
234 413 if ((head->flags & htons(0x7800)) != 0) {
235 if ((ntohs(head->flags) & 0x7800) != 0)
236 goto empty_packet; 414 goto empty_packet;
415 }
237 416
238 // We have a standard query
239 bb_info_msg("%s", (char *)from); 417 bb_info_msg("%s", (char *)from);
240 lookup_result = table_lookup(conf_data, type, answstr, from); 418 if (table_lookup(answstr, conf_data, type, from) != 0) {
241 if (lookup_result != 0) { 419 /* QR = 1 "response"
242 outr_flags = 3 | 0x0400; // name do not exist and auth 420 * AA = 1 "Authoritative Answer"
421 * RCODE = 3 "Name Error" */
422 outr_flags = htons(0x8000 | 0x0400 | 3);
243 goto empty_packet; 423 goto empty_packet;
244 } 424 }
245 if (type == REQ_A) { // return an address 425 /* return an address */
246 struct in_addr a; // NB! its "struct { unsigned __long__ s_addr; }" 426 outr_rlen = 4;
247 uint32_t v32; 427 if (type == htons(REQ_PTR)) {
248 if (!inet_aton((char*)answstr, &a)) { //dotted dec to long conv 428 /* return a host name */
249 outr_flags = 1; /* Frmt err */ 429 outr_rlen = strlen((char *)answstr) + 1;
250 goto empty_packet; 430 }
251 } 431 /* QR = 1 "response",
252 v32 = a.s_addr; /* in case long != int */ 432 * AA = 1 "Authoritative Answer",
253 move_to_unaligned32(answstr, v32); 433 * RCODE = 0 "success" */
254 outr_rlen = 4; // uint32_t IP 434 outr_flags = htons(0x8000 | 0x0400 | 0);
255 } else 435 /* we have one answer */
256 outr_rlen = strlen((char *)answstr) + 1; // a host name
257 outr_flags |= 0x0400; /* authority-bit */
258 // we have an answer
259 head->nansw = htons(1); 436 head->nansw = htons(1);
260 437 /* copy query block to answer block */
261 // copy query block to answer block 438 querystr_len += sizeof(unaligned_qprop);
262 memcpy(answb, from, querystr_len); 439 memcpy(answb, from, querystr_len);
263 answb += querystr_len; 440 answb += querystr_len;
264 441 /* append answer Resource Record */
265 // and append answer rr 442 move_to_unaligned32((uint32_t *)answb, htonl(conf_ttl));
266// FIXME: unaligned accesses??
267 *(uint32_t *) answb = htonl(conf_ttl);
268 answb += 4; 443 answb += 4;
269 *(uint16_t *) answb = htons(outr_rlen); 444 move_to_unaligned32((uint16_t *)answb, htons(outr_rlen));
270 answb += 2; 445 answb += 2;
271 memcpy(answb, answstr, outr_rlen); 446 memcpy(answb, answstr, outr_rlen);
272 answb += outr_rlen; 447 answb += outr_rlen;
273 448
274 empty_packet: 449 empty_packet:
275 450 head->flags |= outr_flags;
276 flags = ntohs(head->flags);
277 // clear rcode and RA, set responsebit and our new flags
278 flags |= (outr_flags & 0xff80) | 0x8000;
279 head->flags = htons(flags);
280 head->nauth = head->nadd = 0; 451 head->nauth = head->nadd = 0;
281 head->nquer = htons(1); 452 head->nquer = htons(1); // why???
282 453
283 packet_len = answb - buf; 454 return answb - buf;
284 return packet_len;
285} 455}
286 456
287/*
288 * Exit on signal
289 */
290//static void interrupt(int sig)
291//{
292// /* unlink("/var/run/dnsd.lock"); */
293// bb_error_msg("interrupt, exiting\n");
294// kill_myself_with_sig(sig);
295//}
296
297int dnsd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 457int dnsd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
298int dnsd_main(int argc UNUSED_PARAM, char **argv) 458int dnsd_main(int argc UNUSED_PARAM, char **argv)
299{ 459{
@@ -328,7 +488,6 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
328 488
329 conf_data = parse_conf_file(fileconf); 489 conf_data = parse_conf_file(fileconf);
330 490
331// signal(SIGINT, interrupt); - just for one message?
332 bb_signals(0 491 bb_signals(0
333 /* why? + (1 << SIGPIPE) */ 492 /* why? + (1 << SIGPIPE) */
334 + (1 << SIGHUP) 493 + (1 << SIGHUP)
@@ -348,8 +507,11 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
348 from = xzalloc(lsa_size); 507 from = xzalloc(lsa_size);
349 to = xzalloc(lsa_size); 508 to = xzalloc(lsa_size);
350 509
351 bb_info_msg("Accepting UDP packets on %s", 510 {
352 xmalloc_sockaddr2dotted(&lsa->u.sa)); 511 char *p = xmalloc_sockaddr2dotted(&lsa->u.sa);
512 bb_info_msg("Accepting UDP packets on %s", p);
513 free(p);
514 }
353 515
354 while (1) { 516 while (1) {
355 int r; 517 int r;
@@ -361,7 +523,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
361 memcpy(to, lsa, lsa_size); 523 memcpy(to, lsa, lsa_size);
362 r = recv_from_to(udps, buf, MAX_PACK_LEN + 1, 0, &from->u.sa, &to->u.sa, lsa->len); 524 r = recv_from_to(udps, buf, MAX_PACK_LEN + 1, 0, &from->u.sa, &to->u.sa, lsa->len);
363 if (r < 12 || r > MAX_PACK_LEN) { 525 if (r < 12 || r > MAX_PACK_LEN) {
364 bb_error_msg("invalid packet size"); 526 bb_error_msg("packet size %d, ignored", r);
365 continue; 527 continue;
366 } 528 }
367 if (OPT_verbose) 529 if (OPT_verbose)